mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Humongous merge. It is incomplete, however; faces-config-navigation.xml and ClientConfigElement
were both beyond me, and are just the raw conflict merge data. If Kev can't figure out how they should go together by tomorrow AM (for me) I'll dig back in. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@4306 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
|
||||
<!-- Default Audit Configuration -->
|
||||
|
||||
|
||||
<Audit xmlns="http://www.alfresco.org/model/audit/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" enabled="false" auditInternal="false" mode="all">
|
||||
|
||||
<!-- -->
|
||||
|
@@ -35,7 +35,7 @@
|
||||
</property>
|
||||
<property name="postCreateScriptUrls">
|
||||
<list>
|
||||
<value>classpath:alfresco/dbscripts/create/1.4/${db.script.dialect}/sample.sql</value>
|
||||
<value>classpath:alfresco/dbscripts/create/1.4/${db.script.dialect}/post-create-indexes.sql</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="validateUpdateScriptPatches">
|
||||
@@ -149,10 +149,6 @@
|
||||
<prop key="path">/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.scripts.childname}</prop>
|
||||
<prop key="location">alfresco/bootstrap/example_javascripts.acp</prop>
|
||||
</props>
|
||||
<props>
|
||||
<prop key="path">/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.templates.childname}</prop>
|
||||
<prop key="location">alfresco/bootstrap/file_plan.xml</prop>
|
||||
</props>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
@@ -192,6 +188,10 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Bootstrap any extensions -->
|
||||
|
||||
<import resource="classpath*:alfresco/extension/bootstrap/*-context.xml" />
|
||||
|
||||
<!-- Descriptor Service -->
|
||||
|
||||
<bean id="descriptorComponent" class="org.alfresco.repo.descriptor.DescriptorServiceImpl">
|
||||
|
@@ -1098,102 +1098,10 @@
|
||||
</cm:category>
|
||||
</cm:subcategories>
|
||||
|
||||
</cm:category>
|
||||
|
||||
</cm:category>
|
||||
</cm:subcategories>
|
||||
|
||||
<cm:category><cm:name>Records Categories</cm:name><sys:node-uuid>rm:recordCategory-root</sys:node-uuid><cm:subcategories>
|
||||
|
||||
<cm:category><cm:name>Review Period</cm:name><sys:node-uuid>rm:reviewPeriod-root</sys:node-uuid><cm:subcategories>
|
||||
|
||||
<cm:category><cm:name>None</cm:name><sys:node-uuid>rm:reviewPeriod-0</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>TBD</cm:name><sys:node-uuid>rm:reviewPeriod-1</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>Annually</cm:name><sys:node-uuid>rm:reviewPeriod-2</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>Calendar Year End</cm:name><sys:node-uuid>rm:reviewPeriod-3</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>Fiscal Year End</cm:name><sys:node-uuid>rm:reviewPeriod-4</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>Semi-Annually</cm:name><sys:node-uuid>rm:reviewPeriod-5</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>Quarterly</cm:name><sys:node-uuid>rm:reviewPeriod-6</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>Monthly</cm:name><sys:node-uuid>rm:reviewPeriod-7</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>Weekly</cm:name><sys:node-uuid>rm:reviewPeriod-8</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>Daily</cm:name><sys:node-uuid>rm:reviewPeriod-9</sys:node-uuid></cm:category>
|
||||
|
||||
</cm:subcategories></cm:category>
|
||||
|
||||
<cm:category><cm:name>Media Types</cm:name><sys:node-uuid>rm:mediaTypes-root</sys:node-uuid><cm:subcategories>
|
||||
|
||||
<cm:category><cm:name>TBD</cm:name><sys:node-uuid>rm:mediaTypes-0</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>Electronic</cm:name><sys:node-uuid>rm:mediaTypes-1</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>Paper</cm:name><sys:node-uuid>rm:mediaTypes-2</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>Microform</cm:name><sys:node-uuid>rm:mediaTypes-3</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>Portable</cm:name><sys:node-uuid>rm:mediaTypes-4</sys:node-uuid></cm:category>
|
||||
|
||||
</cm:subcategories></cm:category>
|
||||
|
||||
<cm:category><cm:name>Markings</cm:name><sys:node-uuid>rm:markings-root</sys:node-uuid><cm:subcategories>
|
||||
|
||||
<cm:category><cm:name>NONE</cm:name><sys:node-uuid>rm:markings-0</sys:node-uuid></cm:category>
|
||||
|
||||
<cm:category><cm:name>Classifications</cm:name><sys:node-uuid>rm:markings-1</sys:node-uuid><cm:subcategories>
|
||||
|
||||
<cm:category><cm:name>UNCLASSIFIED</cm:name><sys:node-uuid>rm:markings-1-1</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>RESTRICTED</cm:name><sys:node-uuid>rm:markings-1-2</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>CONFIDENTIAL</cm:name><sys:node-uuid>rm:markings-1-3</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>SECRET</cm:name><sys:node-uuid>rm:markings-1-4</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>TOP SECRET</cm:name><sys:node-uuid>rm:markings-1-5</sys:node-uuid></cm:category>
|
||||
|
||||
</cm:subcategories></cm:category>
|
||||
|
||||
<cm:category><cm:name>Handling</cm:name><sys:node-uuid>rm:markings-2</sys:node-uuid><cm:subcategories>
|
||||
|
||||
<cm:category><cm:name>COMSEC</cm:name><sys:node-uuid>rm:markings-2-1</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>RD</cm:name><sys:node-uuid>rm:markings-2-2</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>FRD</cm:name><sys:node-uuid>rm:markings-2-3</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>SPECAT-A SIOP-ESI</cm:name><sys:node-uuid>rm:markings-2-4</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>SPECAT-B</cm:name><sys:node-uuid>rm:markings-2-5</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>US-UK EYES ONLY</cm:name><sys:node-uuid>rm:markings-2-6</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>ATOMAL</cm:name><sys:node-uuid>rm:markings-2-7</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>EXCLUSIVE</cm:name><sys:node-uuid>rm:markings-2-8</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>CRYPTO</cm:name><sys:node-uuid>rm:markings-2-9</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>TRC</cm:name><sys:node-uuid>rm:markings-2-10</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>FOR OFFICIAL USE ONLY</cm:name><sys:node-uuid>rm:markings-2-11</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>SBU</cm:name><sys:node-uuid>rm:markings-2-12</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>DEA SENSITIVE</cm:name><sys:node-uuid>rm:markings-2-13</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>DOD UCNI</cm:name><sys:node-uuid>rm:markings-2-14</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>EXDIS</cm:name><sys:node-uuid>rm:markings-2-15</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>LIMDIS</cm:name><sys:node-uuid>rm:markings-2-16</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>NODIS</cm:name><sys:node-uuid>rm:markings-2-17</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>SOSUS</cm:name><sys:node-uuid>rm:markings-2-18</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>EYES ONLY</cm:name><sys:node-uuid>rm:markings-2-19</sys:node-uuid></cm:category>
|
||||
|
||||
</cm:subcategories></cm:category>
|
||||
|
||||
<cm:category><cm:name>Dissemination</cm:name><sys:node-uuid>rm:markings-3</sys:node-uuid><cm:subcategories>
|
||||
|
||||
<cm:category><cm:name>ORCON</cm:name><sys:node-uuid>rm:markings-3-1</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>PROPIN</cm:name><sys:node-uuid>rm:markings-3-2</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>NOFORN</cm:name><sys:node-uuid>rm:markings-3-3</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>NOCONTRACT</cm:name><sys:node-uuid>rm:markings-3-34</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>FOUO</cm:name><sys:node-uuid>rm:markings-3-5</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>RELTO</cm:name><sys:node-uuid>rm:markings-3-6</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>EYES ONLY</cm:name><sys:node-uuid>rm:markings-3-7</sys:node-uuid></cm:category>
|
||||
|
||||
</cm:subcategories></cm:category>
|
||||
|
||||
<cm:category><cm:name>Reason</cm:name><sys:node-uuid>rm:markings-4</sys:node-uuid><cm:subcategories>
|
||||
|
||||
<cm:category><cm:name>CLASS</cm:name><sys:node-uuid>rm:markings-4-1</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>RSN</cm:name><sys:node-uuid>rm:markings-4-2</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>DERV</cm:name><sys:node-uuid>rm:markings-4-3</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>DNG</cm:name><sys:node-uuid>rm:markings-4-4</sys:node-uuid></cm:category>
|
||||
<cm:category><cm:name>DECL</cm:name><sys:node-uuid>rm:markings-4-5</sys:node-uuid></cm:category>
|
||||
|
||||
</cm:subcategories></cm:category>
|
||||
|
||||
</cm:subcategories></cm:category>
|
||||
|
||||
</cm:subcategories></cm:category>
|
||||
|
||||
|
||||
</cm:subcategories>
|
||||
</cm:category>
|
||||
</cm:categories>
|
||||
</cm:category_root>
|
||||
|
Binary file not shown.
@@ -1,828 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<view:view xmlns:view="http://www.alfresco.org/view/repository/1.0">
|
||||
<view:metadata>
|
||||
<view:exportBy>admin</view:exportBy>
|
||||
<view:exportDate>2006-09-02T09:54:43.796+01:00</view:exportDate>
|
||||
<view:exporterVersion>1.4.0 (Dev @build-number@)</view:exporterVersion>
|
||||
<view:exportOf>/app:company_home/app:dictionary/app:space_templates/cm:File_x0020_Plan</view:exportOf>
|
||||
</view:metadata>
|
||||
<cm:folder xmlns:nt="http://www.jcp.org/jcr/nt/1.0" xmlns:alf="http://www.alfresco.org" xmlns:d="http://www.alfresco.org/model/dictionary/1.0" xmlns:view="http://www.alfresco.org/view/repository/1.0" xmlns:act="http://www.alfresco.org/model/action/1.0" xmlns:rma="http://www.alfresco.org/model/record/1.0" xmlns:wf="http://www.alfresco.org/model/workflow/1.0" xmlns:app="http://www.alfresco.org/model/application/1.0" xmlns:usr="http://www.alfresco.org/model/user/1.0" xmlns:ver="http://www.alfresco.org/model/versionstore/1.0" xmlns:cm="http://www.alfresco.org/model/content/1.0" xmlns:sv="http://www.jcp.org/jcr/sv/1.0" xmlns:mix="http://www.jcp.org/jcr/mix/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:sys="http://www.alfresco.org/model/system/1.0" xmlns:rule="http://www.alfresco.org/model/rule/1.0" xmlns:fm="http://www.alfresco.org/model/forum/1.0" xmlns:bpm="http://www.alfresco.org/model/bpm/1.0" xmlns:custom="custom.model" xmlns="" view:childName="cm:File Plan">
|
||||
<view:aspects>
|
||||
<rule:rules></rule:rules>
|
||||
<cm:templatable></cm:templatable>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
<app:uifacets></app:uifacets>
|
||||
<rma:userSpecifiedData></rma:userSpecifiedData>
|
||||
<rma:filePlan></rma:filePlan>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<rma:vitalRecordIndicator>false</rma:vitalRecordIndicator>
|
||||
<rma:privacyActSystem>N/A</rma:privacyActSystem>
|
||||
<rma:defaultTransferLocation>ISF</rma:defaultTransferLocation>
|
||||
<cm:template>/app:company_home/app:dictionary/app:content_templates/cm:records_report.ftl</cm:template>
|
||||
<app:icon>space-icon-cd</app:icon>
|
||||
<sys:node-uuid>15cc634c-3a5c-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<rma:processAccession>false</rma:processAccession>
|
||||
<rma:dispositionAuthority>GRS 1 item 1</rma:dispositionAuthority>
|
||||
<rma:cutoffPeriod>/cm:generalclassifiable/cm:Records_x0020_Categories/cm:Review_x0020_Period/cm:Quarterly</rma:cutoffPeriod>
|
||||
<rma:defaultMediaType>/cm:generalclassifiable/cm:Records_x0020_Categories/cm:Media_x0020_Types/cm:Electronic</rma:defaultMediaType>
|
||||
<rma:recordCounter>1</rma:recordCounter>
|
||||
<rma:processTransfer>false</rma:processTransfer>
|
||||
<cm:created>2006-09-02T09:21:51.750+01:00</cm:created>
|
||||
<rma:cutoffOnsuperseded>false</rma:cutoffOnsuperseded>
|
||||
<rma:accessionLocation>NARA</rma:accessionLocation>
|
||||
<rma:transferBlockSize>1.0</rma:transferBlockSize>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<rma:containsRecordFolders>false</rma:containsRecordFolders>
|
||||
<rma:processDestruction>false</rma:processDestruction>
|
||||
<rma:discretionaryHold>false</rma:discretionaryHold>
|
||||
<rma:eventTrigger>Obsolete or Superseded</rma:eventTrigger>
|
||||
<cm:name>File Plan</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
<rma:vitalRecordReviewPeriod>/cm:generalclassifiable/cm:Records_x0020_Categories/cm:Review_x0020_Period/cm:Quarterly</rma:vitalRecordReviewPeriod>
|
||||
<cm:description>File Plan Template for Records Management</cm:description>
|
||||
<sys:node-dbid>458</sys:node-dbid>
|
||||
<cm:title>File Plan Template</cm:title>
|
||||
<rma:cutoffOnObsolete>false</rma:cutoffOnObsolete>
|
||||
<rma:accessionBlockSize>5.0</rma:accessionBlockSize>
|
||||
<rma:processCutoff>false</rma:processCutoff>
|
||||
<rma:defaultMarkingList>/cm:generalclassifiable/cm:Records_x0020_Categories/cm:Markings/cm:NONE</rma:defaultMarkingList>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<rma:recordFolders></rma:recordFolders>
|
||||
<rma:permanentRecordIndicator>false</rma:permanentRecordIndicator>
|
||||
<cm:modified>2006-09-02T09:53:17.750+01:00</cm:modified>
|
||||
<rma:dispositionInstructions>Destroy/delete when superseded by a like survey or study, or when no longer needed, whichever is later.</rma:dispositionInstructions>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<rma:recordCategoryIdentifier>0000-00</rma:recordCategoryIdentifier>
|
||||
<rma:destructionLocation></rma:destructionLocation>
|
||||
<rma:defaultOriginatingOrganization>Defense Information Systems Agency</rma:defaultOriginatingOrganization>
|
||||
<rma:processHold>false</rma:processHold>
|
||||
<rma:holdPeriod>2.0</rma:holdPeriod>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<rule:ruleFolder>
|
||||
<cm:systemfolder view:childName="rule:ruleFolder">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<cm:modified>2006-09-02T09:41:28.718+01:00</cm:modified>
|
||||
<sys:node-uuid>7836ac9c-3a5d-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<sys:node-dbid>459</sys:node-dbid>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>7836ac9c-3a5d-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
<cm:created>2006-09-02T09:31:46.093+01:00</cm:created>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<cm:contains>
|
||||
<rule:rule view:childName="rule:rules783b678d-3a5d-11db-ae95-09a9ea11d246">
|
||||
<view:aspects>
|
||||
<cm:titled></cm:titled>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<cm:description>Add Email Aspect</cm:description>
|
||||
<sys:node-uuid>783b678e-3a5d-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<sys:node-dbid>460</sys:node-dbid>
|
||||
<cm:title>Email Handling</cm:title>
|
||||
<cm:created>2006-09-02T09:31:46.109+01:00</cm:created>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<rule:disabled>false</rule:disabled>
|
||||
<cm:modified>2006-09-02T09:31:46.250+01:00</cm:modified>
|
||||
<rule:applyToChildren>true</rule:applyToChildren>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<rule:executeAsynchronously>false</rule:executeAsynchronously>
|
||||
<rule:ruleType>
|
||||
<view:values>
|
||||
<view:value>inbound</view:value>
|
||||
</view:values>
|
||||
</rule:ruleType>
|
||||
<cm:name>783b678e-3a5d-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<rule:action>
|
||||
<act:compositeaction view:childName="rule:action">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:executeAsynchronously>false</act:executeAsynchronously>
|
||||
<act:actionDescription>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionDescription>
|
||||
<sys:node-uuid>78343b97-3a5d-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<sys:node-dbid>461</sys:node-dbid>
|
||||
<cm:created>2006-09-02T09:31:46.140+01:00</cm:created>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<cm:modified>2006-09-02T09:31:46.250+01:00</cm:modified>
|
||||
<act:actionTitle>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionTitle>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<act:definitionName>composite-action</act:definitionName>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>78343b97-3a5d-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<act:conditions>
|
||||
<act:actioncondition view:childName="act:conditions">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<cm:modified>2006-09-02T09:31:46.250+01:00</cm:modified>
|
||||
<sys:node-uuid>78343b98-3a5d-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<sys:node-dbid>462</sys:node-dbid>
|
||||
<act:definitionName>compare-mime-type</act:definitionName>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<act:invert>false</act:invert>
|
||||
<cm:name>78343b98-3a5d-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
<cm:created>2006-09-02T09:31:46.171+01:00</cm:created>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<act:parameters>
|
||||
<act:actionparameter view:childName="act:parameters">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:parameterValue>
|
||||
<view:value view:datatype="d:text">message/rfc822</view:value>
|
||||
</act:parameterValue>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<act:parameterName>value</act:parameterName>
|
||||
<cm:modified>2006-09-02T09:31:46.250+01:00</cm:modified>
|
||||
<sys:node-uuid>78474e6f-3a5d-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<sys:node-dbid>463</sys:node-dbid>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>78474e6f-3a5d-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
<cm:created>2006-09-02T09:31:46.187+01:00</cm:created>
|
||||
</view:properties>
|
||||
<view:associations></view:associations>
|
||||
</act:actionparameter>
|
||||
</act:parameters>
|
||||
</view:associations>
|
||||
</act:actioncondition>
|
||||
</act:conditions>
|
||||
<act:actions>
|
||||
<act:action view:childName="act:actions">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:executeAsynchronously>false</act:executeAsynchronously>
|
||||
<act:actionDescription>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionDescription>
|
||||
<sys:node-uuid>78343b99-3a5d-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<sys:node-dbid>464</sys:node-dbid>
|
||||
<cm:created>2006-09-02T09:31:46.203+01:00</cm:created>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<cm:modified>2006-09-02T09:31:46.250+01:00</cm:modified>
|
||||
<act:actionTitle>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionTitle>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<act:definitionName>add-features</act:definitionName>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>78343b99-3a5d-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<act:parameters>
|
||||
<act:actionparameter view:childName="act:parameters">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:parameterValue>
|
||||
<view:value view:datatype="d:qname">{http://www.alfresco.org/model/content/1.0}emailed</view:value>
|
||||
</act:parameterValue>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<act:parameterName>aspect-name</act:parameterName>
|
||||
<cm:modified>2006-09-02T09:31:46.250+01:00</cm:modified>
|
||||
<sys:node-uuid>784c0960-3a5d-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<sys:node-dbid>465</sys:node-dbid>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>784c0960-3a5d-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
<cm:created>2006-09-02T09:31:46.234+01:00</cm:created>
|
||||
</view:properties>
|
||||
<view:associations></view:associations>
|
||||
</act:actionparameter>
|
||||
</act:parameters>
|
||||
</view:associations>
|
||||
</act:action>
|
||||
</act:actions>
|
||||
</view:associations>
|
||||
</act:compositeaction>
|
||||
</rule:action>
|
||||
</view:associations>
|
||||
</rule:rule>
|
||||
<rule:rule view:childName="rule:rulesd08ef27c-3a5d-11db-ae95-09a9ea11d246">
|
||||
<view:aspects>
|
||||
<cm:titled></cm:titled>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<cm:description>Add record aspect and set up record data</cm:description>
|
||||
<sys:node-uuid>d091637d-3a5d-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<sys:node-dbid>466</sys:node-dbid>
|
||||
<cm:title>Record Set-up</cm:title>
|
||||
<cm:created>2006-09-02T09:34:14.312+01:00</cm:created>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<rule:disabled>false</rule:disabled>
|
||||
<cm:modified>2006-09-02T09:34:14.546+01:00</cm:modified>
|
||||
<rule:applyToChildren>true</rule:applyToChildren>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<rule:executeAsynchronously>false</rule:executeAsynchronously>
|
||||
<rule:ruleType>
|
||||
<view:values>
|
||||
<view:value>inbound</view:value>
|
||||
</view:values>
|
||||
</rule:ruleType>
|
||||
<cm:name>d091637d-3a5d-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<rule:action>
|
||||
<act:compositeaction view:childName="rule:action">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:executeAsynchronously>false</act:executeAsynchronously>
|
||||
<act:actionDescription>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionDescription>
|
||||
<sys:node-uuid>d08ca886-3a5d-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<sys:node-dbid>467</sys:node-dbid>
|
||||
<cm:created>2006-09-02T09:34:14.343+01:00</cm:created>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<cm:modified>2006-09-02T09:34:14.546+01:00</cm:modified>
|
||||
<act:actionTitle>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionTitle>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<act:definitionName>composite-action</act:definitionName>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>d08ca886-3a5d-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<act:conditions>
|
||||
<act:actioncondition view:childName="act:conditions">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<cm:modified>2006-09-02T09:34:14.546+01:00</cm:modified>
|
||||
<sys:node-uuid>d08ca887-3a5d-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<sys:node-dbid>468</sys:node-dbid>
|
||||
<act:definitionName>is-subtype</act:definitionName>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<act:invert>false</act:invert>
|
||||
<cm:name>d08ca887-3a5d-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
<cm:created>2006-09-02T09:34:14.375+01:00</cm:created>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<act:parameters>
|
||||
<act:actionparameter view:childName="act:parameters">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:parameterValue>
|
||||
<view:value view:datatype="d:qname">{http://www.alfresco.org/model/content/1.0}content</view:value>
|
||||
</act:parameterValue>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<act:parameterName>type</act:parameterName>
|
||||
<cm:modified>2006-09-02T09:34:14.546+01:00</cm:modified>
|
||||
<sys:node-uuid>d09d4a5f-3a5d-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<sys:node-dbid>469</sys:node-dbid>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>d09d4a5f-3a5d-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
<cm:created>2006-09-02T09:34:14.390+01:00</cm:created>
|
||||
</view:properties>
|
||||
<view:associations></view:associations>
|
||||
</act:actionparameter>
|
||||
</act:parameters>
|
||||
</view:associations>
|
||||
</act:actioncondition>
|
||||
</act:conditions>
|
||||
<act:actions>
|
||||
<act:action view:childName="act:actions">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:executeAsynchronously>false</act:executeAsynchronously>
|
||||
<act:actionDescription>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionDescription>
|
||||
<sys:node-uuid>d08ca888-3a5d-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<sys:node-dbid>470</sys:node-dbid>
|
||||
<cm:created>2006-09-02T09:34:14.421+01:00</cm:created>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<cm:modified>2006-09-02T09:34:14.546+01:00</cm:modified>
|
||||
<act:actionTitle>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionTitle>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<act:definitionName>add-features</act:definitionName>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>d08ca888-3a5d-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<act:parameters>
|
||||
<act:actionparameter view:childName="act:parameters">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:parameterValue>
|
||||
<view:value view:datatype="d:qname">{http://www.alfresco.org/model/record/1.0}record</view:value>
|
||||
</act:parameterValue>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<act:parameterName>aspect-name</act:parameterName>
|
||||
<cm:modified>2006-09-02T09:34:14.546+01:00</cm:modified>
|
||||
<sys:node-uuid>d0a47550-3a5d-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<sys:node-dbid>471</sys:node-dbid>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>d0a47550-3a5d-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
<cm:created>2006-09-02T09:34:14.453+01:00</cm:created>
|
||||
</view:properties>
|
||||
<view:associations></view:associations>
|
||||
</act:actionparameter>
|
||||
</act:parameters>
|
||||
</view:associations>
|
||||
</act:action>
|
||||
<act:action view:childName="act:actions">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:executeAsynchronously>false</act:executeAsynchronously>
|
||||
<act:actionDescription>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionDescription>
|
||||
<sys:node-uuid>d08ca889-3a5d-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<sys:node-dbid>472</sys:node-dbid>
|
||||
<cm:created>2006-09-02T09:34:14.484+01:00</cm:created>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<cm:modified>2006-09-02T09:34:14.546+01:00</cm:modified>
|
||||
<act:actionTitle>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionTitle>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<act:definitionName>extract-metadata</act:definitionName>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>d08ca889-3a5d-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
</view:properties>
|
||||
<view:associations></view:associations>
|
||||
</act:action>
|
||||
<act:action view:childName="act:actions">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:executeAsynchronously>false</act:executeAsynchronously>
|
||||
<act:actionDescription>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionDescription>
|
||||
<sys:node-uuid>d08ca88a-3a5d-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<sys:node-dbid>473</sys:node-dbid>
|
||||
<cm:created>2006-09-02T09:34:14.515+01:00</cm:created>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<cm:modified>2006-09-02T09:34:14.546+01:00</cm:modified>
|
||||
<act:actionTitle>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionTitle>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<act:definitionName>script</act:definitionName>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>d08ca88a-3a5d-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<act:parameters>
|
||||
<act:actionparameter view:childName="act:parameters">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:parameterValue>
|
||||
<view:value view:datatype="d:category">/app:company_home/app:dictionary/app:scripts/cm:record_setup.js</view:value>
|
||||
</act:parameterValue>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<act:parameterName>script-ref</act:parameterName>
|
||||
<cm:modified>2006-09-02T09:34:14.546+01:00</cm:modified>
|
||||
<sys:node-uuid>d0b2cd31-3a5d-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<sys:node-dbid>474</sys:node-dbid>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>d0b2cd31-3a5d-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
<cm:created>2006-09-02T09:34:14.531+01:00</cm:created>
|
||||
</view:properties>
|
||||
<view:associations></view:associations>
|
||||
</act:actionparameter>
|
||||
</act:parameters>
|
||||
</view:associations>
|
||||
</act:action>
|
||||
</act:actions>
|
||||
</view:associations>
|
||||
</act:compositeaction>
|
||||
</rule:action>
|
||||
</view:associations>
|
||||
</rule:rule>
|
||||
<rule:rule view:childName="rule:rules96342c64-3a5e-11db-ae95-09a9ea11d246">
|
||||
<view:aspects>
|
||||
<cm:titled></cm:titled>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<cm:description>Set up record folder</cm:description>
|
||||
<sys:node-uuid>96342c65-3a5e-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<sys:node-dbid>475</sys:node-dbid>
|
||||
<cm:title>Records Folder</cm:title>
|
||||
<cm:created>2006-09-02T09:39:45.906+01:00</cm:created>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<rule:disabled>false</rule:disabled>
|
||||
<cm:modified>2006-09-02T09:39:46.093+01:00</cm:modified>
|
||||
<rule:applyToChildren>true</rule:applyToChildren>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<rule:executeAsynchronously>false</rule:executeAsynchronously>
|
||||
<rule:ruleType>
|
||||
<view:values>
|
||||
<view:value>inbound</view:value>
|
||||
</view:values>
|
||||
</rule:ruleType>
|
||||
<cm:name>96342c65-3a5e-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<rule:action>
|
||||
<act:compositeaction view:childName="rule:action">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:executeAsynchronously>false</act:executeAsynchronously>
|
||||
<act:actionDescription>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionDescription>
|
||||
<sys:node-uuid>9631e26f-3a5e-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<sys:node-dbid>476</sys:node-dbid>
|
||||
<cm:created>2006-09-02T09:39:45.921+01:00</cm:created>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<cm:modified>2006-09-02T09:39:46.093+01:00</cm:modified>
|
||||
<act:actionTitle>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionTitle>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<act:definitionName>composite-action</act:definitionName>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>9631e26f-3a5e-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<act:conditions>
|
||||
<act:actioncondition view:childName="act:conditions">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<cm:modified>2006-09-02T09:39:46.093+01:00</cm:modified>
|
||||
<sys:node-uuid>9631e270-3a5e-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<sys:node-dbid>477</sys:node-dbid>
|
||||
<act:definitionName>is-subtype</act:definitionName>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<act:invert>false</act:invert>
|
||||
<cm:name>9631e270-3a5e-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
<cm:created>2006-09-02T09:39:45.953+01:00</cm:created>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<act:parameters>
|
||||
<act:actionparameter view:childName="act:parameters">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:parameterValue>
|
||||
<view:value view:datatype="d:qname">{http://www.alfresco.org/model/content/1.0}folder</view:value>
|
||||
</act:parameterValue>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<act:parameterName>type</act:parameterName>
|
||||
<cm:modified>2006-09-02T09:39:46.093+01:00</cm:modified>
|
||||
<sys:node-uuid>96428447-3a5e-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<sys:node-dbid>478</sys:node-dbid>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>96428447-3a5e-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
<cm:created>2006-09-02T09:39:45.984+01:00</cm:created>
|
||||
</view:properties>
|
||||
<view:associations></view:associations>
|
||||
</act:actionparameter>
|
||||
</act:parameters>
|
||||
</view:associations>
|
||||
</act:actioncondition>
|
||||
</act:conditions>
|
||||
<act:actions>
|
||||
<act:action view:childName="act:actions">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:executeAsynchronously>false</act:executeAsynchronously>
|
||||
<act:actionDescription>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionDescription>
|
||||
<sys:node-uuid>9631e271-3a5e-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<sys:node-dbid>479</sys:node-dbid>
|
||||
<cm:created>2006-09-02T09:39:46.000+01:00</cm:created>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<cm:modified>2006-09-02T09:39:46.093+01:00</cm:modified>
|
||||
<act:actionTitle>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionTitle>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<act:definitionName>add-features</act:definitionName>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>9631e271-3a5e-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<act:parameters>
|
||||
<act:actionparameter view:childName="act:parameters">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:parameterValue>
|
||||
<view:value view:datatype="d:qname">{http://www.alfresco.org/model/record/1.0}record</view:value>
|
||||
</act:parameterValue>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<act:parameterName>aspect-name</act:parameterName>
|
||||
<cm:modified>2006-09-02T09:39:46.093+01:00</cm:modified>
|
||||
<sys:node-uuid>9649b038-3a5e-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<sys:node-dbid>480</sys:node-dbid>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>9649b038-3a5e-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
<cm:created>2006-09-02T09:39:46.031+01:00</cm:created>
|
||||
</view:properties>
|
||||
<view:associations></view:associations>
|
||||
</act:actionparameter>
|
||||
</act:parameters>
|
||||
</view:associations>
|
||||
</act:action>
|
||||
<act:action view:childName="act:actions">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:executeAsynchronously>false</act:executeAsynchronously>
|
||||
<act:actionDescription>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionDescription>
|
||||
<sys:node-uuid>9631e272-3a5e-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<sys:node-dbid>481</sys:node-dbid>
|
||||
<cm:created>2006-09-02T09:39:46.046+01:00</cm:created>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<cm:modified>2006-09-02T09:39:46.093+01:00</cm:modified>
|
||||
<act:actionTitle>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionTitle>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<act:definitionName>script</act:definitionName>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>9631e272-3a5e-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<act:parameters>
|
||||
<act:actionparameter view:childName="act:parameters">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:parameterValue>
|
||||
<view:value view:datatype="d:category">/app:company_home/app:dictionary/app:scripts/cm:record_folder.js</view:value>
|
||||
</act:parameterValue>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<act:parameterName>script-ref</act:parameterName>
|
||||
<cm:modified>2006-09-02T09:39:46.093+01:00</cm:modified>
|
||||
<sys:node-uuid>964e6b29-3a5e-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<sys:node-dbid>482</sys:node-dbid>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>964e6b29-3a5e-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
<cm:created>2006-09-02T09:39:46.078+01:00</cm:created>
|
||||
</view:properties>
|
||||
<view:associations></view:associations>
|
||||
</act:actionparameter>
|
||||
</act:parameters>
|
||||
</view:associations>
|
||||
</act:action>
|
||||
</act:actions>
|
||||
</view:associations>
|
||||
</act:compositeaction>
|
||||
</rule:action>
|
||||
</view:associations>
|
||||
</rule:rule>
|
||||
<rule:rule view:childName="rule:rulesd36b6896-3a5e-11db-ae95-09a9ea11d246">
|
||||
<view:aspects>
|
||||
<cm:titled></cm:titled>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<cm:description>Process record lifecycle based upon the file plan</cm:description>
|
||||
<sys:node-uuid>d36b6897-3a5e-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<sys:node-dbid>483</sys:node-dbid>
|
||||
<cm:title>Record Lifecycle</cm:title>
|
||||
<cm:created>2006-09-02T09:41:28.609+01:00</cm:created>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<rule:disabled>false</rule:disabled>
|
||||
<cm:modified>2006-09-02T09:41:28.718+01:00</cm:modified>
|
||||
<rule:applyToChildren>true</rule:applyToChildren>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<rule:executeAsynchronously>false</rule:executeAsynchronously>
|
||||
<rule:ruleType>
|
||||
<view:values>
|
||||
<view:value>update</view:value>
|
||||
</view:values>
|
||||
</rule:ruleType>
|
||||
<cm:name>d36b6897-3a5e-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<rule:action>
|
||||
<act:compositeaction view:childName="rule:action">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:executeAsynchronously>false</act:executeAsynchronously>
|
||||
<act:actionDescription>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionDescription>
|
||||
<sys:node-uuid>d36b6892-3a5e-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<sys:node-dbid>484</sys:node-dbid>
|
||||
<cm:created>2006-09-02T09:41:28.640+01:00</cm:created>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<cm:modified>2006-09-02T09:41:28.734+01:00</cm:modified>
|
||||
<act:actionTitle>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionTitle>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<act:definitionName>composite-action</act:definitionName>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>d36b6892-3a5e-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<act:conditions>
|
||||
<act:actioncondition view:childName="act:conditions">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<cm:modified>2006-09-02T09:41:28.734+01:00</cm:modified>
|
||||
<sys:node-uuid>d36b6893-3a5e-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<sys:node-dbid>485</sys:node-dbid>
|
||||
<act:definitionName>no-condition</act:definitionName>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<act:invert>false</act:invert>
|
||||
<cm:name>d36b6893-3a5e-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
<cm:created>2006-09-02T09:41:28.656+01:00</cm:created>
|
||||
</view:properties>
|
||||
<view:associations></view:associations>
|
||||
</act:actioncondition>
|
||||
</act:conditions>
|
||||
<act:actions>
|
||||
<act:action view:childName="act:actions">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:executeAsynchronously>false</act:executeAsynchronously>
|
||||
<act:actionDescription>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionDescription>
|
||||
<sys:node-uuid>d36b6894-3a5e-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<sys:node-dbid>486</sys:node-dbid>
|
||||
<cm:created>2006-09-02T09:41:28.687+01:00</cm:created>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<cm:modified>2006-09-02T09:41:28.734+01:00</cm:modified>
|
||||
<act:actionTitle>
|
||||
<view:value view:isNull="true"></view:value>
|
||||
</act:actionTitle>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<act:definitionName>script</act:definitionName>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>d36b6894-3a5e-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<act:parameters>
|
||||
<act:actionparameter view:childName="act:parameters">
|
||||
<view:aspects>
|
||||
<cm:auditable></cm:auditable>
|
||||
<sys:referenceable></sys:referenceable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<act:parameterValue>
|
||||
<view:value view:datatype="d:category">/app:company_home/app:dictionary/app:scripts/cm:record_lifecycle.js</view:value>
|
||||
</act:parameterValue>
|
||||
<cm:modifier>admin</cm:modifier>
|
||||
<act:parameterName>script-ref</act:parameterName>
|
||||
<cm:modified>2006-09-02T09:41:28.734+01:00</cm:modified>
|
||||
<sys:node-uuid>d37c3179-3a5e-11db-ae95-09a9ea11d246</sys:node-uuid>
|
||||
<cm:creator>admin</cm:creator>
|
||||
<sys:node-dbid>487</sys:node-dbid>
|
||||
<sys:store-protocol>workspace</sys:store-protocol>
|
||||
<cm:name>d37c3179-3a5e-11db-ae95-09a9ea11d246</cm:name>
|
||||
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||
<cm:created>2006-09-02T09:41:28.703+01:00</cm:created>
|
||||
</view:properties>
|
||||
<view:associations></view:associations>
|
||||
</act:actionparameter>
|
||||
</act:parameters>
|
||||
</view:associations>
|
||||
</act:action>
|
||||
</act:actions>
|
||||
</view:associations>
|
||||
</act:compositeaction>
|
||||
</rule:action>
|
||||
</view:associations>
|
||||
</rule:rule>
|
||||
</cm:contains>
|
||||
</view:associations>
|
||||
</cm:systemfolder>
|
||||
</rule:ruleFolder>
|
||||
</view:associations>
|
||||
</cm:folder>
|
||||
</view:view>
|
@@ -23,30 +23,27 @@
|
||||
</bean>
|
||||
|
||||
<!-- Datasource bean -->
|
||||
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
|
||||
<property name="driverClass">
|
||||
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
|
||||
<property name="driverClassName">
|
||||
<value>${db.driver}</value>
|
||||
</property>
|
||||
<property name="jdbcUrl">
|
||||
<property name="url">
|
||||
<value>${db.url}</value>
|
||||
</property>
|
||||
<property name="user">
|
||||
<property name="username">
|
||||
<value>${db.username}</value>
|
||||
</property>
|
||||
<property name="password">
|
||||
<value>${db.password}</value>
|
||||
</property>
|
||||
<property name="initialPoolSize" >
|
||||
<property name="initialSize" >
|
||||
<value>${db.pool.initial}</value>
|
||||
</property>
|
||||
<property name="maxPoolSize" >
|
||||
<property name="maxActive" >
|
||||
<value>${db.pool.max}</value>
|
||||
</property>
|
||||
<property name="maxIdleTime" >
|
||||
<value>${db.pool.maxIdleTime}</value>
|
||||
</property>
|
||||
<property name="numHelperThreads" >
|
||||
<value>1</value>
|
||||
<property name="defaultAutoCommit" >
|
||||
<value>false</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
@@ -78,6 +75,7 @@
|
||||
<value>alfresco.messages.patch-service</value>
|
||||
<value>alfresco.messages.schema-update</value>
|
||||
<value>alfresco.messages.webdav-messages</value>
|
||||
<value>alfresco.messages.copy-service</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
@@ -421,7 +419,6 @@
|
||||
<value>alfresco/model/wcmModel.xml</value>
|
||||
<value>alfresco/model/applicationModel.xml</value>
|
||||
<value>alfresco/model/forumModel.xml</value>
|
||||
<value>alfresco/model/recordsModel.xml</value>
|
||||
|
||||
<!-- Implementation models -->
|
||||
<value>org/alfresco/repo/security/authentication/userModel.xml</value>
|
||||
@@ -497,6 +494,9 @@
|
||||
<property name="authenticationService">
|
||||
<ref bean="AuthenticationService" />
|
||||
</property>
|
||||
<property name="internalNodeService">
|
||||
<ref bean="nodeService" />
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- -->
|
||||
|
@@ -0,0 +1,3 @@
|
||||
--
|
||||
-- Add post-creation indexes. (Generic Schema 1.4)
|
||||
--
|
@@ -0,0 +1,30 @@
|
||||
--
|
||||
-- Add post-creation indexes. (Oracle Schema 1.4)
|
||||
--
|
||||
CREATE INDEX FKFFF41F9960601995 ON alf_access_control_entry (permission_id);
|
||||
CREATE INDEX FKFFF41F99B25A50BF ON alf_access_control_entry (authority_id);
|
||||
CREATE INDEX FKFFF41F99B9553F6C ON alf_access_control_entry (acl_id);
|
||||
CREATE INDEX FK8A749A657B7FDE43 ON alf_auth_ext_keys (id);
|
||||
CREATE INDEX FKFFC5468E74173FF4 ON alf_child_assoc (child_node_id);
|
||||
CREATE INDEX FKFFC5468E8E50E582 ON alf_child_assoc (parent_node_id);
|
||||
CREATE INDEX FK60EFB626B9553F6C ON alf_node (acl_id);
|
||||
CREATE INDEX FK60EFB626D24ADD25 ON alf_node (protocol, identifier);
|
||||
CREATE INDEX FK7D4CF8EC7F2C8017 ON alf_node_properties (node_id);
|
||||
CREATE INDEX FKD654E027F2C8017 ON alf_node_aspects (node_id);
|
||||
CREATE INDEX FKE1A550BCB69C43F3 ON alf_node_assoc (source_node_id);
|
||||
CREATE INDEX FKE1A550BCA8FC7769 ON alf_node_assoc (target_node_id);
|
||||
CREATE INDEX FK71C2002B7F2C8017 ON alf_node_status (node_id);
|
||||
CREATE INDEX FKBD4FF53D22DBA5BA ON alf_store (root_node_id);
|
||||
|
||||
--
|
||||
-- Transaction tables
|
||||
--
|
||||
CREATE INDEX FK71C2002B9E57C13D ON alf_node_status (transaction_id);
|
||||
CREATE INDEX FKB8761A3A9AE340B7 ON alf_transaction (server_id);
|
||||
|
||||
--
|
||||
-- New audit tables
|
||||
--
|
||||
CREATE INDEX FKEAD1817484342E39 ON alf_audit_fact (audit_date_id);
|
||||
CREATE INDEX FKEAD18174A0F9B8D9 ON alf_audit_fact (audit_source_id);
|
||||
CREATE INDEX FKEAD18174F524CFD7 ON alf_audit_fact (audit_conf_id);
|
@@ -0,0 +1,30 @@
|
||||
--
|
||||
-- Add post-creation indexes. (SQL Server Schema 1.4)
|
||||
--
|
||||
CREATE INDEX FKFFF41F9960601995 ON alf_access_control_entry (permission_id);
|
||||
CREATE INDEX FKFFF41F99B25A50BF ON alf_access_control_entry (authority_id);
|
||||
CREATE INDEX FKFFF41F99B9553F6C ON alf_access_control_entry (acl_id);
|
||||
CREATE INDEX FK8A749A657B7FDE43 ON alf_auth_ext_keys (id);
|
||||
CREATE INDEX FKFFC5468E74173FF4 ON alf_child_assoc (child_node_id);
|
||||
CREATE INDEX FKFFC5468E8E50E582 ON alf_child_assoc (parent_node_id);
|
||||
CREATE INDEX FK60EFB626B9553F6C ON alf_node (acl_id);
|
||||
CREATE INDEX FK60EFB626D24ADD25 ON alf_node (protocol, identifier);
|
||||
CREATE INDEX FK7D4CF8EC7F2C8017 ON alf_node_properties (node_id);
|
||||
CREATE INDEX FKD654E027F2C8017 ON alf_node_aspects (node_id);
|
||||
CREATE INDEX FKE1A550BCB69C43F3 ON alf_node_assoc (source_node_id);
|
||||
CREATE INDEX FKE1A550BCA8FC7769 ON alf_node_assoc (target_node_id);
|
||||
CREATE INDEX FK71C2002B7F2C8017 ON alf_node_status (node_id);
|
||||
CREATE INDEX FKBD4FF53D22DBA5BA ON alf_store (root_node_id);
|
||||
|
||||
--
|
||||
-- Transaction tables
|
||||
--
|
||||
CREATE INDEX FK71C2002B9E57C13D ON alf_node_status (transaction_id);
|
||||
CREATE INDEX FKB8761A3A9AE340B7 ON alf_transaction (server_id);
|
||||
|
||||
--
|
||||
-- New audit tables
|
||||
--
|
||||
CREATE INDEX FKEAD1817484342E39 ON alf_audit_fact (audit_date_id);
|
||||
CREATE INDEX FKEAD18174A0F9B8D9 ON alf_audit_fact (audit_source_id);
|
||||
CREATE INDEX FKEAD18174F524CFD7 ON alf_audit_fact (audit_conf_id);
|
@@ -1,5 +1,5 @@
|
||||
-- ------------------------------------------------------
|
||||
-- Alfresco Schema conversion V1.3 to V1.4 Part 1
|
||||
-- Alfresco Schema conversion V1.3 to V1.4 Part 1 (MySQL)
|
||||
--
|
||||
-- Adds the columns required to enforce the duplicate name detection
|
||||
--
|
||||
@@ -25,6 +25,11 @@ DROP TABLE IF EXISTS T_permission;
|
||||
DROP TABLE IF EXISTS T_store;
|
||||
DROP TABLE IF EXISTS T_version_count;
|
||||
|
||||
--
|
||||
-- Upgrades to 1.3 of MyIsam tables could have missed the applied_patch table InnoDB
|
||||
--
|
||||
ALTER TABLE applied_patch ENGINE = InnoDB;
|
||||
|
||||
--
|
||||
-- Unique name constraint
|
||||
--
|
||||
@@ -47,20 +52,70 @@ ALTER TABLE node_assoc
|
||||
--
|
||||
-- Rename tables to give 'alf_' prefix
|
||||
--
|
||||
ALTER TABLE access_control_entry RENAME TO alf_access_control_entry;
|
||||
ALTER TABLE access_control_list RENAME TO alf_access_control_list;
|
||||
ALTER TABLE applied_patch RENAME TO alf_applied_patch;
|
||||
ALTER TABLE auth_ext_keys RENAME TO alf_auth_ext_keys;
|
||||
ALTER TABLE authority RENAME TO alf_authority;
|
||||
ALTER TABLE child_assoc RENAME TO alf_child_assoc;
|
||||
ALTER TABLE node RENAME TO alf_node;
|
||||
ALTER TABLE node_aspects RENAME TO alf_node_aspects;
|
||||
ALTER TABLE node_assoc RENAME TO alf_node_assoc;
|
||||
ALTER TABLE node_properties RENAME TO alf_node_properties;
|
||||
ALTER TABLE node_status RENAME TO alf_node_status;
|
||||
ALTER TABLE permission RENAME TO alf_permission;
|
||||
ALTER TABLE store RENAME TO alf_store;
|
||||
ALTER TABLE version_count RENAME TO alf_version_count;
|
||||
ALTER TABLE access_control_entry RENAME TO alf_access_control_entry;
|
||||
ALTER TABLE access_control_list RENAME TO alf_access_control_list;
|
||||
ALTER TABLE applied_patch RENAME TO alf_applied_patch;
|
||||
ALTER TABLE auth_ext_keys RENAME TO alf_auth_ext_keys;
|
||||
ALTER TABLE authority RENAME TO alf_authority;
|
||||
ALTER TABLE child_assoc RENAME TO alf_child_assoc;
|
||||
ALTER TABLE node RENAME TO alf_node;
|
||||
ALTER TABLE node_aspects RENAME TO alf_node_aspects;
|
||||
ALTER TABLE node_assoc RENAME TO alf_node_assoc;
|
||||
ALTER TABLE node_properties RENAME TO alf_node_properties;
|
||||
ALTER TABLE node_status RENAME TO alf_node_status;
|
||||
ALTER TABLE permission RENAME TO alf_permission;
|
||||
ALTER TABLE store RENAME TO alf_store;
|
||||
ALTER TABLE version_count RENAME TO alf_version_count;
|
||||
|
||||
--
|
||||
-- The table renames will cause Hibernate to rehash the FK constraint names.
|
||||
-- For MySQL, Hibernate will generate scripts to add the appropriate constraints
|
||||
-- and indexes.
|
||||
--
|
||||
ALTER TABLE alf_access_control_entry
|
||||
DROP FOREIGN KEY FKF064DF7560601995,
|
||||
DROP INDEX FKF064DF7560601995,
|
||||
DROP FOREIGN KEY FKF064DF75B25A50BF,
|
||||
DROP INDEX FKF064DF75B25A50BF,
|
||||
DROP FOREIGN KEY FKF064DF75B9553F6C,
|
||||
DROP INDEX FKF064DF75B9553F6C;
|
||||
ALTER TABLE alf_auth_ext_keys
|
||||
DROP FOREIGN KEY FK31D3BA097B7FDE43,
|
||||
DROP INDEX FK31D3BA097B7FDE43;
|
||||
ALTER TABLE alf_child_assoc
|
||||
DROP FOREIGN KEY FKC6EFFF3274173FF4,
|
||||
DROP INDEX FKC6EFFF3274173FF4,
|
||||
DROP FOREIGN KEY FKC6EFFF328E50E582,
|
||||
DROP INDEX FKC6EFFF328E50E582;(optional)
|
||||
ALTER TABLE alf_child_assoc
|
||||
DROP FOREIGN KEY FKFFC5468E74173FF4,
|
||||
DROP INDEX FKFFC5468E74173FF4,
|
||||
DROP FOREIGN KEY FKFFC5468E8E50E582,
|
||||
DROP INDEX FKFFC5468E8E50E582;(optional)
|
||||
ALTER TABLE alf_node
|
||||
DROP FOREIGN KEY FK33AE02B9553F6C,
|
||||
DROP INDEX FK33AE02B9553F6C;
|
||||
ALTER TABLE alf_node
|
||||
DROP FOREIGN KEY FK33AE02D24ADD25,
|
||||
DROP INDEX FK33AE02D24ADD25;
|
||||
ALTER TABLE alf_node_properties
|
||||
DROP FOREIGN KEY FKC962BF907F2C8017,
|
||||
DROP INDEX FKC962BF907F2C8017;
|
||||
ALTER TABLE alf_node_aspects
|
||||
DROP FOREIGN KEY FK2B91A9DE7F2C8017,
|
||||
DROP INDEX FK2B91A9DE7F2C8017;
|
||||
ALTER TABLE alf_node_assoc
|
||||
DROP FOREIGN KEY FK5BAEF398B69C43F3,
|
||||
DROP INDEX FK5BAEF398B69C43F3;
|
||||
ALTER TABLE alf_node_assoc
|
||||
DROP FOREIGN KEY FK5BAEF398A8FC7769,
|
||||
DROP INDEX FK5BAEF398A8FC7769;
|
||||
ALTER TABLE alf_node_status
|
||||
DROP FOREIGN KEY FK38ECB8CF7F2C8017,
|
||||
DROP INDEX FK38ECB8CF7F2C8017;
|
||||
ALTER TABLE alf_store
|
||||
DROP FOREIGN KEY FK68AF8E122DBA5BA,
|
||||
DROP INDEX FK68AF8E122DBA5BA;
|
||||
|
||||
--
|
||||
-- Record script finish
|
||||
|
@@ -1,5 +1,5 @@
|
||||
-- ------------------------------------------------------
|
||||
-- Alfresco Schema conversion V1.3 to V1.4 Part 2
|
||||
-- Alfresco Schema conversion V1.3 to V1.4 Part 2 (MySQL)
|
||||
--
|
||||
-- Adds the alf_transaction and alf_server tables to keep track of the sources
|
||||
-- of transactions.
|
||||
@@ -25,7 +25,6 @@ CREATE TABLE alf_transaction (
|
||||
change_txn_id varchar(56) NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
KEY FKB8761A3A9AE340B7 (server_id),
|
||||
KEY IDX_CHANGE_TXN (change_txn_id),
|
||||
CONSTRAINT FKB8761A3A9AE340B7 FOREIGN KEY (server_id) REFERENCES alf_server (id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
insert into alf_transaction
|
||||
@@ -44,7 +43,11 @@ UPDATE alf_node_status ns SET ns.transaction_id =
|
||||
);
|
||||
ALTER TABLE alf_node_status
|
||||
DROP COLUMN change_txn_id,
|
||||
ADD CONSTRAINT FK71C2002B9E57C13D FOREIGN KEY (transaction_id) REFERENCES alf_transaction (id);
|
||||
ADD CONSTRAINT FK71C2002B9E57C13D FOREIGN KEY (transaction_id) REFERENCES alf_transaction (id),
|
||||
ADD INDEX FK71C2002B9E57C13D (transaction_id);
|
||||
ALTER TABLE alf_node_status
|
||||
DROP COLUMN deleted
|
||||
;(optional)
|
||||
|
||||
--
|
||||
-- Record script finish
|
||||
|
@@ -0,0 +1,92 @@
|
||||
-- ------------------------------------------------------
|
||||
-- Alfresco Schema conversion V1.3 to V1.4 Part 1 (Oracle)
|
||||
--
|
||||
-- Adds the columns required to enforce the duplicate name detection
|
||||
--
|
||||
-- Author: Derek Hulley
|
||||
-- ------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Unique name constraint
|
||||
--
|
||||
|
||||
-- Apply new schema changes to child assoc table
|
||||
ALTER TABLE child_assoc ADD
|
||||
(
|
||||
child_node_name VARCHAR2(50 CHAR) DEFAULT 'V1.4 upgrade' NOT NULL,
|
||||
child_node_name_crc NUMBER(19,0) DEFAULT -1 NOT NULL
|
||||
);
|
||||
|
||||
UPDATE child_assoc
|
||||
SET child_node_name_crc = id * -1;
|
||||
|
||||
CREATE UNIQUE INDEX IDX_CHILD_NAMECRC ON child_assoc (parent_node_id, type_qname, child_node_name, child_node_name_crc);
|
||||
|
||||
-- Apply unique index for node associations
|
||||
CREATE UNIQUE INDEX IDX_ASSOC ON node_assoc (source_node_id, type_qname, target_node_id);
|
||||
|
||||
--
|
||||
-- Rename tables to give 'alf_' prefix
|
||||
--
|
||||
ALTER TABLE access_control_entry RENAME TO alf_access_control_entry;
|
||||
ALTER TABLE access_control_list RENAME TO alf_access_control_list;
|
||||
ALTER TABLE applied_patch RENAME TO alf_applied_patch;
|
||||
ALTER TABLE auth_ext_keys RENAME TO alf_auth_ext_keys;
|
||||
ALTER TABLE authority RENAME TO alf_authority;
|
||||
ALTER TABLE child_assoc RENAME TO alf_child_assoc;
|
||||
ALTER TABLE node RENAME TO alf_node;
|
||||
ALTER TABLE node_aspects RENAME TO alf_node_aspects;
|
||||
ALTER TABLE node_assoc RENAME TO alf_node_assoc;
|
||||
ALTER TABLE node_properties RENAME TO alf_node_properties;
|
||||
ALTER TABLE node_status RENAME TO alf_node_status;
|
||||
ALTER TABLE permission RENAME TO alf_permission;
|
||||
ALTER TABLE store RENAME TO alf_store;
|
||||
ALTER TABLE version_count RENAME TO alf_version_count;
|
||||
|
||||
--
|
||||
-- The table renames will cause Hibernate to rehash the FK constraint names
|
||||
--
|
||||
ALTER TABLE alf_access_control_entry RENAME CONSTRAINT FKF064DF7560601995 TO FKFFF41F9960601995;
|
||||
ALTER TABLE alf_access_control_entry RENAME CONSTRAINT FKF064DF75B25A50BF TO FKFFF41F99B25A50BF;
|
||||
ALTER TABLE alf_access_control_entry RENAME CONSTRAINT FKF064DF75B9553F6C TO FKFFF41F99B9553F6C;
|
||||
ALTER TABLE alf_auth_ext_keys RENAME CONSTRAINT FK31D3BA097B7FDE43 TO FK8A749A657B7FDE43;
|
||||
ALTER TABLE alf_child_assoc RENAME CONSTRAINT FKC6EFFF3274173FF4 TO FKFFC5468E74173FF4;
|
||||
ALTER TABLE alf_child_assoc RENAME CONSTRAINT FKC6EFFF328E50E582 TO FKFFC5468E8E50E582;
|
||||
ALTER TABLE alf_node RENAME CONSTRAINT FK33AE02B9553F6C TO FK60EFB626B9553F6C;
|
||||
ALTER TABLE alf_node RENAME CONSTRAINT FK33AE02D24ADD25 TO FK60EFB626D24ADD25;
|
||||
ALTER TABLE alf_node_properties RENAME CONSTRAINT FKC962BF907F2C8017 TO FK7D4CF8EC7F2C8017;
|
||||
ALTER TABLE alf_node_aspects RENAME CONSTRAINT FK2B91A9DE7F2C8017 TO FKD654E027F2C8017;
|
||||
ALTER TABLE alf_node_assoc RENAME CONSTRAINT FK5BAEF398B69C43F3 TO FKE1A550BCB69C43F3;
|
||||
ALTER TABLE alf_node_assoc RENAME CONSTRAINT FK5BAEF398A8FC7769 TO FKE1A550BCA8FC7769;
|
||||
ALTER TABLE alf_node_status RENAME CONSTRAINT FK38ECB8CF7F2C8017 TO FK71C2002B7F2C8017;
|
||||
ALTER TABLE alf_store RENAME CONSTRAINT FK68AF8E122DBA5BA TO FKBD4FF53D22DBA5BA;
|
||||
|
||||
--
|
||||
-- Rename the indexes to keep in synch with the new table names. For Oracle, Hibernate doesn't create or add these
|
||||
--
|
||||
ALTER INDEX FKF064DF7560601995 RENAME TO FKFFF41F9960601995;
|
||||
ALTER INDEX FKF064DF75B25A50BF RENAME TO FKFFF41F99B25A50BF;
|
||||
ALTER INDEX FKF064DF75B9553F6C RENAME TO FKFFF41F99B9553F6C;
|
||||
ALTER INDEX FK31D3BA097B7FDE43 RENAME TO FK8A749A657B7FDE43;
|
||||
ALTER INDEX FKC6EFFF3274173FF4 RENAME TO FKFFC5468E74173FF4;
|
||||
ALTER INDEX FKC6EFFF328E50E582 RENAME TO FKFFC5468E8E50E582;
|
||||
ALTER INDEX FK33AE02B9553F6C RENAME TO FK60EFB626B9553F6C;
|
||||
ALTER INDEX FK33AE02D24ADD25 RENAME TO FK60EFB626D24ADD25;
|
||||
ALTER INDEX FKC962BF907F2C8017 RENAME TO FK7D4CF8EC7F2C8017;
|
||||
ALTER INDEX FK2B91A9DE7F2C8017 RENAME TO FKD654E027F2C8017;
|
||||
ALTER INDEX FK5BAEF398B69C43F3 RENAME TO FKE1A550BCB69C43F3;
|
||||
ALTER INDEX FK5BAEF398A8FC7769 RENAME TO FKE1A550BCA8FC7769;
|
||||
ALTER INDEX FK38ECB8CF7F2C8017 RENAME TO FK71C2002B7F2C8017;
|
||||
ALTER INDEX FK68AF8E122DBA5BA RENAME TO FKBD4FF53D22DBA5BA;
|
||||
|
||||
--
|
||||
-- Record script finish
|
||||
--
|
||||
delete from alf_applied_patch where id = 'patch.schemaUpdateScript-V1.4-1';
|
||||
insert into alf_applied_patch
|
||||
(id, description, fixes_from_schema, fixes_to_schema, applied_to_schema, target_schema, applied_on_date, applied_to_server, was_executed, succeeded, report)
|
||||
values
|
||||
(
|
||||
'patch.schemaUpdateScript-V1.4-1', 'Manually execute script upgrade V1.4 part 1',
|
||||
0, 19, -1, 20, sysdate, 'UNKOWN', 1, 1, 'Script completed'
|
||||
);
|
@@ -0,0 +1,69 @@
|
||||
-- ------------------------------------------------------
|
||||
-- Alfresco Schema conversion V1.3 to V1.4 Part 2 (Oracle)
|
||||
--
|
||||
-- Adds the alf_transaction and alf_server tables to keep track of the sources
|
||||
-- of transactions.
|
||||
--
|
||||
-- Author: Derek Hulley
|
||||
-- ------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Create server and transaction tables
|
||||
--
|
||||
|
||||
create table alf_server
|
||||
(
|
||||
id number(19,0) not null,
|
||||
ip_address varchar2(15 char) not null,
|
||||
primary key (id),
|
||||
unique (ip_address)
|
||||
);
|
||||
insert into alf_server (id, ip_address) values (0, '0.0.0.0');
|
||||
|
||||
create table alf_transaction
|
||||
(
|
||||
id number(19,0) not null,
|
||||
server_id number(19,0),
|
||||
change_txn_id varchar2(56 char) not null,
|
||||
primary key (id)
|
||||
);
|
||||
alter table alf_transaction add constraint FKB8761A3A9AE340B7 foreign key (server_id) references alf_server;
|
||||
create index FKB8761A3A9AE340B7 on alf_transaction (server_id);
|
||||
|
||||
insert into alf_transaction
|
||||
(
|
||||
id, server_id, change_txn_id
|
||||
)
|
||||
select
|
||||
hibernate_sequence.nextval,
|
||||
(select max(id) from alf_server),
|
||||
change_txn_id
|
||||
from alf_node_status;
|
||||
|
||||
-- Alter node status
|
||||
alter table alf_node_status add
|
||||
(
|
||||
transaction_id number(19,0) DEFAULT 0 NOT NULL
|
||||
);
|
||||
-- Update FK column
|
||||
update alf_node_status ns SET ns.transaction_id =
|
||||
(
|
||||
select t.id from alf_transaction t
|
||||
where t.change_txn_id = ns.change_txn_id and rownum = 1
|
||||
);
|
||||
alter table alf_node_status DROP COLUMN change_txn_id;
|
||||
alter table alf_node_status ADD CONSTRAINT FK71C2002B9E57C13D FOREIGN KEY (transaction_id) REFERENCES alf_transaction (id);
|
||||
create index FK71C2002B9E57C13D on alf_node_status (transaction_id);
|
||||
alter table alf_node_status DROP COLUMN deleted;(optional)
|
||||
|
||||
--
|
||||
-- Record script finish
|
||||
--
|
||||
delete from alf_applied_patch where id = 'patch.schemaUpdateScript-V1.4-2';
|
||||
insert into alf_applied_patch
|
||||
(id, description, fixes_from_schema, fixes_to_schema, applied_to_schema, target_schema, applied_on_date, applied_to_server, was_executed, succeeded, report)
|
||||
values
|
||||
(
|
||||
'patch.schemaUpdateScript-V1.4-2', 'Manually execute script upgrade V1.4 part 2',
|
||||
0, 20, -1, 21, sysdate, 'UNKOWN', 1, 1, 'Script completed'
|
||||
);
|
Binary file not shown.
26
config/alfresco/desktop/showDetails.js
Normal file
26
config/alfresco/desktop/showDetails.js
Normal file
@@ -0,0 +1,26 @@
|
||||
// Main action
|
||||
|
||||
function runAction()
|
||||
{
|
||||
var urlStr = webURL + "navigate/showDocDetails/workspace/SpacesStore/" + deskParams.getTarget(0).getNode().getId() +
|
||||
"?ticket=" + deskParams.getTicket();
|
||||
|
||||
return urlStr;
|
||||
}
|
||||
|
||||
// Run the action
|
||||
//
|
||||
// Response :-
|
||||
// Success - no return or return 0, or "0,<message>"
|
||||
// For error or control response then return a string :-
|
||||
// Error - "1,<error message>"
|
||||
// FileNotFound - "2,<message>"
|
||||
// AccessDenied - "3,<message>"
|
||||
// BadParameter - "4,<message>
|
||||
// NotWorkingCopy - "5,<message>"
|
||||
// NoSuchAction - "6,<message>
|
||||
// LaunchURL - "7,<URL>"
|
||||
// CommandLine - "8,<commandline>"
|
||||
|
||||
var response = "7," + runAction();
|
||||
response;
|
29
config/alfresco/desktop/urlLink.js
Normal file
29
config/alfresco/desktop/urlLink.js
Normal file
@@ -0,0 +1,29 @@
|
||||
// Main action
|
||||
|
||||
function runAction()
|
||||
{
|
||||
out.println("URL link to " + deskParams.getFolder());
|
||||
|
||||
var urlStr = webURL + "navigate/browse/workspace/SpacesStore/" + deskParams.getFolderNode().getId() +
|
||||
"?ticket=" + deskParams.getTicket();
|
||||
out.println( " url=" + urlStr);
|
||||
|
||||
return urlStr;
|
||||
}
|
||||
|
||||
// Run the action
|
||||
//
|
||||
// Response :-
|
||||
// Success - no return or return 0, or "0,<message>"
|
||||
// For error or control response then return a string :-
|
||||
// Error - "1,<error message>"
|
||||
// FileNotFound - "2,<message>"
|
||||
// AccessDenied - "3,<message>"
|
||||
// BadParameter - "4,<message>
|
||||
// NotWorkingCopy - "5,<message>"
|
||||
// NoSuchAction - "6,<message>
|
||||
// LaunchURL - "7,<URL>"
|
||||
// CommandLine - "8,<commandline>"
|
||||
|
||||
var response = "7," + runAction();
|
||||
response;
|
@@ -4,7 +4,6 @@
|
||||
hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect
|
||||
|
||||
hibernate.jdbc.use_streams_for_binary=true
|
||||
hibernate.hbm2ddl.auto=update
|
||||
hibernate.show_sql=false
|
||||
hibernate.cache.use_query_cache=true
|
||||
hibernate.max_fetch_depth=10
|
||||
|
@@ -0,0 +1,57 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||
|
||||
<!--
|
||||
An example of how to override the dataSource bean.
|
||||
If an alternative pool is desired, such as C3P0, then it can be referenced by
|
||||
changing the 'class' attribute and adding or removing the required properties.
|
||||
The required libraries can be dropped into the servers extension lib folders.
|
||||
-->
|
||||
<beans>
|
||||
|
||||
<!-- Datasource bean -->
|
||||
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
|
||||
<!-- connection settings -->
|
||||
<property name="driverClassName">
|
||||
<value>${db.driver}</value>
|
||||
</property>
|
||||
<property name="url">
|
||||
<value>${db.url}</value>
|
||||
</property>
|
||||
<property name="username">
|
||||
<value>${db.username}</value>
|
||||
</property>
|
||||
<property name="password">
|
||||
<value>${db.password}</value>
|
||||
</property>
|
||||
<property name="defaultAutoCommit" >
|
||||
<value>false</value>
|
||||
</property>
|
||||
<!-- pool settings -->
|
||||
<property name="initialSize" >
|
||||
<value>${db.pool.initial}</value>
|
||||
</property>
|
||||
<property name="maxActive" >
|
||||
<value>${db.pool.max}</value>
|
||||
</property>
|
||||
<property name="timeBetweenEvictionRunsMillis" >
|
||||
<value>300000</value>
|
||||
</property>
|
||||
<property name="minEvictableIdleTimeMillis" >
|
||||
<value>-1</value>
|
||||
</property>
|
||||
<property name="testOnBorrow" >
|
||||
<value>false</value>
|
||||
</property>
|
||||
<property name="maxWait" >
|
||||
<value>50000</value>
|
||||
</property>
|
||||
<property name="testWhileIdle" >
|
||||
<value>true</value>
|
||||
</property>
|
||||
<property name="validationQuery" >
|
||||
<value>select 1</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
@@ -9,7 +9,13 @@
|
||||
#db.pool.max=100
|
||||
|
||||
#
|
||||
# MySQL connection (This is default and requires mysql-connector-java-3.1.12-bin.jar, which ships with the Alfresco server)
|
||||
# HSQL connection
|
||||
#
|
||||
#db.driver=org.hsqldb.jdbcDriver
|
||||
#db.url=jdbc:hsqldb:file:alf_data/hsql_data/alfresco;ifexists=true;shutdown=true;
|
||||
|
||||
#
|
||||
# MySQL connection (This is default and requires mysql-connector-java-5.0.3-bin.jar, which ships with the Alfresco server)
|
||||
#
|
||||
#db.driver=org.gjt.mm.mysql.Driver
|
||||
#db.url=jdbc:mysql://localhost/alfresco
|
||||
|
@@ -7,6 +7,11 @@
|
||||
# For a full list: http://www.hibernate.org/hib_docs/v3/reference/en/html_single/#configuration-optional-dialects
|
||||
#
|
||||
|
||||
#
|
||||
# HSQL dialect
|
||||
#
|
||||
#hibernate.dialect=org.hibernate.dialect.HSQLDialect
|
||||
|
||||
#
|
||||
# MySQL dialect (default)
|
||||
#
|
||||
|
55
config/alfresco/extension/file-servers-custom.xml
Normal file
55
config/alfresco/extension/file-servers-custom.xml
Normal file
@@ -0,0 +1,55 @@
|
||||
<alfresco-config area="file-servers">
|
||||
|
||||
<!-- To override the default Alfresco filesystem use replace="true", to -->
|
||||
<!-- add additional filesystems remove the replace="true" attribute -->
|
||||
|
||||
<config evaluator="string-compare" condition="Filesystems" replace="true">
|
||||
<filesystems>
|
||||
|
||||
<filesystem name="Alfresco">
|
||||
<store>workspace://SpacesStore</store>
|
||||
<rootPath>/app:company_home</rootPath>
|
||||
|
||||
<!-- Add a URL file to each folder that links back to the web client -->
|
||||
<urlFile>
|
||||
<filename>__Alfresco.url</filename>
|
||||
<webpath>http://${localname}:8080/alfresco/</webpath>
|
||||
</urlFile>
|
||||
|
||||
<!-- Mark locked files as offline -->
|
||||
<offlineFiles/>
|
||||
|
||||
<!-- Desktop actions -->
|
||||
|
||||
<desktopActions>
|
||||
<global>
|
||||
<path>alfresco/desktop/Alfresco.exe</path>
|
||||
<webpath>http://${localname}:8080/alfresco/</webpath>
|
||||
</global>
|
||||
<action>
|
||||
<class>org.alfresco.filesys.smb.server.repo.desk.CheckInOutDesktopAction</class>
|
||||
<name>CheckInOut</name>
|
||||
<filename>__CheckInOut.exe</filename>
|
||||
</action>
|
||||
<action>
|
||||
<class>org.alfresco.filesys.smb.server.repo.desk.JavaScriptDesktopAction</class>
|
||||
<name>JavaScriptURL</name>
|
||||
<filename>__ShowDetails.exe</filename>
|
||||
<script>alfresco/desktop/showDetails.js</script>
|
||||
<attributes>anyFiles</attributes>
|
||||
<preprocess>copyToTarget</preprocess>
|
||||
</action>
|
||||
|
||||
</desktopActions>
|
||||
|
||||
<!--
|
||||
<accessControl default="Write">
|
||||
<user name="admin" access="Write"/>
|
||||
<address subnet="90.1.0.0" mask="255.255.0.0" access="Write"/>
|
||||
</accessControl>
|
||||
-->
|
||||
</filesystem>
|
||||
</filesystems>
|
||||
</config>
|
||||
|
||||
</alfresco-config>
|
71
config/alfresco/extension/index-tracking-context.xml.sample
Normal file
71
config/alfresco/extension/index-tracking-context.xml.sample
Normal file
@@ -0,0 +1,71 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- Schedule index tracking every 30s -->
|
||||
<bean id="indexTrackerTrigger" class="org.alfresco.util.CronTriggerBean">
|
||||
<property name="jobDetail">
|
||||
<bean class="org.springframework.scheduling.quartz.JobDetailBean">
|
||||
<property name="jobClass">
|
||||
<value>org.alfresco.repo.node.index.IndexRecoveryJob</value>
|
||||
</property>
|
||||
<property name="jobDataAsMap">
|
||||
<map>
|
||||
<entry key="indexRecoveryComponent">
|
||||
<ref bean="indexTrackerComponent" />
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="scheduler">
|
||||
<ref bean="schedulerFactory" />
|
||||
</property>
|
||||
<property name="cronExpression">
|
||||
<value>0,30 * * * * ?</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean
|
||||
id="indexTrackerComponent"
|
||||
class="org.alfresco.repo.node.index.IndexRemoteTransactionTracker"
|
||||
parent="indexRecoveryComponentBase">
|
||||
<property name="remoteOnly">
|
||||
<value>true</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Forces the reindexing of nodes where content may have been missing before -->
|
||||
<!--
|
||||
This component can be triggered at intervals where asynchronous content sharing
|
||||
between clustered servers has been set up.
|
||||
-->
|
||||
<bean id="missingContentReindexTrigger" class="org.alfresco.util.TriggerBean">
|
||||
<property name="jobDetail">
|
||||
<bean class="org.springframework.scheduling.quartz.JobDetailBean">
|
||||
<property name="jobClass">
|
||||
<value>org.alfresco.repo.node.index.IndexRecoveryJob</value>
|
||||
</property>
|
||||
<property name="jobDataAsMap">
|
||||
<map>
|
||||
<entry key="indexRecoveryComponent">
|
||||
<ref bean="missingContentReindexComponent" />
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="scheduler">
|
||||
<ref bean="schedulerFactory" />
|
||||
</property>
|
||||
<!-- Give the server 5 minutes and then check for missing content -->
|
||||
<property name="startDelayMinutes">
|
||||
<value>5</value>
|
||||
</property>
|
||||
<property name="repeatCount">
|
||||
<value>0</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
@@ -38,25 +38,28 @@
|
||||
<!-- Add a URL file to each folder that links back to the web client -->
|
||||
<urlFile>
|
||||
<filename>__AlfrescoClient.url</filename>
|
||||
<webpath>http://localhost:8080/alfresco/</webpath>
|
||||
<webpath>http://${localname}:8080/alfresco/</webpath>
|
||||
</urlFile>
|
||||
|
||||
<!-- Mark locked files as offline -->
|
||||
<offlineFiles/>
|
||||
|
||||
<!-- Desktop actions -->
|
||||
<!-- Uses a client-side application to trigger a server-side action -->
|
||||
<!-- Echo - displays a message echoed from the server -->
|
||||
<!-- URL - launches a URL via the Windows shell -->
|
||||
<!-- CmdLine - launches the Notepad application -->
|
||||
<!-- CheckInOut - checks files in/out, drag and drop files onto the application -->
|
||||
<!-- JavaScript - run a server-side script -->
|
||||
<!-- Uses a client-side application to trigger a server-side action -->
|
||||
<!-- Echo - displays a message echoed from the server -->
|
||||
<!-- URL - launches a URL via the Windows shell -->
|
||||
<!-- CmdLine - launches the Notepad application -->
|
||||
<!-- CheckInOut - checks files in/out, drag and drop files onto the application -->
|
||||
<!-- JavaScript - run a server-side script -->
|
||||
<!-- JavaScriptURL - server-side script that generates a URL to the folder using a ticket -->
|
||||
<!-- to avoid having to logon -->
|
||||
|
||||
<!--
|
||||
<desktopActions>
|
||||
<global>
|
||||
<path>alfresco/desktop/Alfresco.exe</path>
|
||||
<webpath>http://${localname}:8080/alfresco/</webpath>
|
||||
</global>
|
||||
|
||||
<action>
|
||||
<class>org.alfresco.filesys.smb.server.repo.desk.EchoDesktopAction</class>
|
||||
<name>Echo</name>
|
||||
@@ -85,6 +88,14 @@
|
||||
<attributes>anyFiles, multiplePaths , allowNoParams</attributes>
|
||||
<preprocess>confirm, copyToTarget</preprocess>
|
||||
</action>
|
||||
<action>
|
||||
<class>org.alfresco.filesys.smb.server.repo.desk.JavaScriptDesktopAction</class>
|
||||
<name>JavaScriptURL</name>
|
||||
<filename>__AlfrescoDetails.exe</filename>
|
||||
<script>alfresco/desktop/showDetails.js</script>
|
||||
<attributes>anyFiles</attributes>
|
||||
<preprocess>copyToTarget</preprocess>
|
||||
</action>
|
||||
|
||||
</desktopActions>
|
||||
-->
|
||||
|
@@ -171,8 +171,8 @@
|
||||
<property name="patchDao">
|
||||
<ref bean="patchDaoComponent" />
|
||||
</property>
|
||||
<property name="versionDao">
|
||||
<ref bean="versionCounterDaoComponent" />
|
||||
<property name="versionCounterService">
|
||||
<ref bean="versionCounterService" />
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
@@ -227,6 +227,9 @@
|
||||
-->
|
||||
</bean>
|
||||
|
||||
<bean id="storeImporterViews" class="org.alfresco.repo.importer.ImporterBootstrapViews" abstract="true">
|
||||
</bean>
|
||||
|
||||
|
||||
<!-- -->
|
||||
<!-- Store specific Importers -->
|
||||
|
@@ -4,8 +4,8 @@ bpm_businessprocessmodel.title=Business Process Model
|
||||
bpm_businessprocessmodel.description=Base definitions of all Business Processes
|
||||
|
||||
# Default transition
|
||||
bpm_businessprocessmodel.transition.title=Done
|
||||
bpm_businessprocessmodel.transition.description=Done
|
||||
bpm_businessprocessmodel.transition.title=Task Done
|
||||
bpm_businessprocessmodel.transition.description=Task Done
|
||||
|
||||
# Base Task
|
||||
bpm_businessprocessmodel.type.bpm_task.title=Task
|
||||
|
3
config/alfresco/messages/copy-service.properties
Normal file
3
config/alfresco/messages/copy-service.properties
Normal file
@@ -0,0 +1,3 @@
|
||||
# copy service externalised display strings
|
||||
|
||||
copy_service.copy_of_label=Copy of {0}
|
@@ -27,8 +27,8 @@ patch.savedSearchesPermission.description=Sets required permissions on 'Saved Se
|
||||
patch.savedSearchesPermission.result.applied=Granted CONTRIBUTOR role to EVERYONE on ''Saved Searches'' folder: {0}.
|
||||
patch.savedSearchesPermission.err.not_found='Saved Searches' folder could not be found.
|
||||
|
||||
patch.updatePermissionData.description=Update permission entries from 'folder' to 'cmobject'.
|
||||
patch.updatePermissionData.upgrade=Please follow an upgrade path via server version 1.2.1
|
||||
patch.updatePermissionData.description=Update permissions from 'folder' to 'cmobject' [JIRA: AR-344].
|
||||
patch.updatePermissionData.result=Changed {0} 'folder' access control entries to 'cmobject'.
|
||||
|
||||
patch.authoritiesFolder.description=Ensures the existence of the user authorities folder [JIRA: AR-497].
|
||||
|
||||
@@ -39,7 +39,7 @@ patch.fixNodeSerializableValues.description=Ensure that property values are not
|
||||
patch.fixNodeSerializableValues.result=Fixed {0} node property serialized values
|
||||
|
||||
patch.updateGuestPermission.description=Rename guest permission from 'Guest' to 'Consumer'
|
||||
patch.updateGuestPermission.upgrade=Please follow an upgrade path via server version 1.2.1
|
||||
patch.updateGuestPermission.result=Changed {0} 'Guest' access control entries to 'Consumer'.
|
||||
|
||||
patch.categoryRootPermission.description=Sets required permissions on 'Category Root' folder.
|
||||
patch.categoryRootPermission.result=Granted CONSUMER role to GUEST on ''Category Root'' folder: {0}.
|
||||
@@ -52,7 +52,7 @@ patch.spacesRootPermission.description=Change Spaces store root permission from
|
||||
patch.spacesRootPermission.result=Updated Spaces store root permission from 'Consumer' to 'Read'
|
||||
|
||||
patch.contentPermission.description=Update permission entries from 'cm:content' to 'sys:base'.
|
||||
patch.contentPermission.upgrade=Please follow an upgrade path via server version 1.2.1
|
||||
patch.contentPermission.result=Changed {0} 'cm:content' access control entries to 'sys:base'.
|
||||
|
||||
patch.forumsIcons.description=Updates forums icon references
|
||||
patch.forumsIcons.result=Updated {0} icon references
|
||||
@@ -96,6 +96,6 @@ patch.schemaUpgradeScript.description=Ensures that the database upgrade script h
|
||||
patch.schemaUpgradeScript.err.not_executed=The schema upgrade script, ''{0}'', has not been run against this database.
|
||||
|
||||
patch.uniqueChildName.description=Checks and renames duplicate children.
|
||||
patch.uniqueChildName.copyOf=({0})
|
||||
patch.uniqueChildName.copyOf=({0}-{1})
|
||||
patch.uniqueChildName.result=Checked {0} associations and fixed {1} duplicates. See file {2} for details.
|
||||
|
||||
patch.uniqueChildName.err.unable_to_fix=Auto-fixing of duplicate names failed. See file {0} for details.
|
||||
|
@@ -1,6 +1,8 @@
|
||||
# Schema update messages
|
||||
|
||||
schema.update.msg.executing_script=Executing database script: {0}
|
||||
schema.update.msg.optional_statement_failed=Optional statement execution failed:\n SQL: {0}\n Error: {1}\n File: {2}\n Line: {3}
|
||||
schema.update.err.statement_failed=Statement execution failed:\n SQL: {0}\n Error: {1}\n File: {2}\n Line: {3}
|
||||
schema.update.err.update_failed=Schema auto-update failed
|
||||
schema.update.err.validation_failed=Schema validation failed
|
||||
schema.update.err.update_script_not_run=The following schema upgrade script needs to be executed manually: {0}
|
||||
|
@@ -0,0 +1 @@
|
||||
workflow_console.help=alfresco/messages/workflow-interpreter-help.txt
|
174
config/alfresco/messages/workflow-interpreter-help.txt
Normal file
174
config/alfresco/messages/workflow-interpreter-help.txt
Normal file
@@ -0,0 +1,174 @@
|
||||
##
|
||||
## Meta commands
|
||||
##
|
||||
|
||||
ok> help
|
||||
|
||||
List this help.
|
||||
|
||||
ok> r
|
||||
|
||||
Repeat last command.
|
||||
|
||||
ok> user [<userName>]
|
||||
|
||||
Switch to specified <userName>. If <userName> is omitted, the currently
|
||||
selected user is shown.
|
||||
|
||||
ok> use
|
||||
|
||||
Show current workflow context.
|
||||
|
||||
##
|
||||
## Workflow Definition Commands
|
||||
##
|
||||
|
||||
ok> deploy <definitionClassPath>
|
||||
|
||||
Deploy workflow definition to Alfresco server.
|
||||
|
||||
<definitionClassPath> class path to workflow definition.
|
||||
|
||||
ok> redeploy
|
||||
|
||||
Redeploy the last workflow definition.
|
||||
|
||||
ok> show definitions
|
||||
|
||||
List all deployed workflow definitions.
|
||||
|
||||
ok> use definition [<workflowDefId>]
|
||||
|
||||
Switch to use the workflow definition identified by <workflowDefId>. If
|
||||
<workflowDefId> is ommited, the currently selected workflow definition
|
||||
is shown.
|
||||
|
||||
##
|
||||
## Variable Commands
|
||||
##
|
||||
|
||||
ok> var
|
||||
|
||||
Show all defined variables.
|
||||
|
||||
ok> var <varName>[*]=<varValue>
|
||||
|
||||
Define or update a variable.
|
||||
|
||||
<varName> variable name
|
||||
[*] if specified, define a collection
|
||||
<varValue> variable value (comma-seperate to specify a list of values)
|
||||
|
||||
e.g.
|
||||
|
||||
set bpm:assignee*=admin,fred
|
||||
set wf:notifyMe=true
|
||||
|
||||
ok> var <varName>[*] person <varValue>
|
||||
|
||||
Define or update a (cm:person) node ref variable.
|
||||
|
||||
<varName> variable name
|
||||
[*] if specified, define a collection
|
||||
<varValue> variable value (comma-seperate to specify a list of values)
|
||||
|
||||
e.g.
|
||||
|
||||
set bpm:assignee* person admin,fred
|
||||
|
||||
ok> var <varName>=
|
||||
|
||||
Delete an existing variable.
|
||||
|
||||
<varName> variable name
|
||||
|
||||
##
|
||||
## Workflow Commands
|
||||
##
|
||||
|
||||
ok> start [<varName[=varValue>]]*
|
||||
|
||||
Start a new workflow using the currently selected workflow definition. Start
|
||||
Task parameters are provided as name/value pairs or references to pre-defined
|
||||
variables.
|
||||
|
||||
e.g.
|
||||
|
||||
start bpm:assignee=david wf:predefined
|
||||
|
||||
ok> show workflows
|
||||
|
||||
Display the list of active workflows for the currently selected workflow
|
||||
definition.
|
||||
|
||||
ok> use workflow <workflowId>
|
||||
|
||||
Use the specified <workflowId>.
|
||||
|
||||
ok> show paths [<workflowId>]
|
||||
|
||||
Display the workflow paths for the specified <workflowId>. If <workflowId>
|
||||
is omitted, the paths for the currently started workflow are shown.
|
||||
|
||||
ok> show transitions [<workflowId>]
|
||||
|
||||
Display all available transitions for the specified <workflowId>. If
|
||||
<workflowId> is omitted, the transitions for the currently started workflow
|
||||
are shown.
|
||||
|
||||
ok> signal <pathId> [<transitionName>]
|
||||
|
||||
Signal transition on specified <pathId>. If <transitionName> is omitted, the
|
||||
default transition is taken.
|
||||
|
||||
ok> desc workflow <workflowId>
|
||||
|
||||
Describe the specified <workflowId>.
|
||||
|
||||
ok> end workflow <workflowId>
|
||||
|
||||
End (cancel) the specified <workflowId>.
|
||||
|
||||
##
|
||||
## Task Commands
|
||||
##
|
||||
|
||||
ok> show my tasks
|
||||
|
||||
List tasks assigned to the currently selected user.
|
||||
|
||||
ok> show my completed
|
||||
|
||||
List tasks completed by the currently selected user.
|
||||
|
||||
ok> show tasks [<pathId>]
|
||||
|
||||
List tasks associated with the specified workflow <pathId>. If <pathId> is
|
||||
omitted, the tasks associated with the currently selected workflow path are
|
||||
shown.
|
||||
|
||||
ok> desc task <taskId>
|
||||
|
||||
Describe the task identified by <taskId>.
|
||||
|
||||
ok> update task <taskid> [<varName[=varValue>]]*
|
||||
|
||||
Update the state of the specified <taskId>. Task properties are provided as
|
||||
name/value pairs or references to pre-defined variables.
|
||||
|
||||
<varName> variable name
|
||||
[*] if specified, define a collection
|
||||
<varValue> variable value (comma-seperate to specify a list of values)
|
||||
|
||||
e.g.
|
||||
|
||||
update task jbpm$122 bpm:assignee=fred wf:notifyMe=false
|
||||
|
||||
ok> end task <taskId> [<transitionName>]
|
||||
|
||||
End the task identified by <taskId>. If <transitionName> is omitted, the
|
||||
default transition is taken.
|
||||
|
||||
##
|
||||
## end
|
||||
##
|
@@ -57,6 +57,7 @@
|
||||
<property name="contentService"><ref bean="ContentService" /></property>
|
||||
<property name="permissionService"><ref bean="permissionService"/></property>
|
||||
<property name="authenticationComponent"><ref bean="authenticationComponent"/></property>
|
||||
<property name="authenticationService"><ref bean="authenticationService"/></property>
|
||||
<property name="serviceRegistry"><ref bean="ServiceRegistry"/></property>
|
||||
</bean>
|
||||
|
||||
|
@@ -80,6 +80,9 @@
|
||||
|
||||
<!-- Namespace Service -->
|
||||
|
||||
<alias name="namespaceService" alias="NamespaceService"/>
|
||||
|
||||
<!--
|
||||
<bean id="NamespaceService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces">
|
||||
<value>org.alfresco.service.namespace.NamespaceService</value>
|
||||
@@ -97,6 +100,7 @@
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
-->
|
||||
|
||||
<bean id="NamespaceService_transaction" class="org.springframework.transaction.interceptor.TransactionInterceptor">
|
||||
<property name="transactionManager">
|
||||
@@ -124,6 +128,9 @@
|
||||
|
||||
<!-- Dictionary Service -->
|
||||
|
||||
<alias name="dictionaryService" alias="DictionaryService"/>
|
||||
|
||||
<!--
|
||||
<bean id="DictionaryService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces">
|
||||
<value>org.alfresco.service.cmr.dictionary.DictionaryService</value>
|
||||
@@ -141,6 +148,7 @@
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
-->
|
||||
|
||||
<bean id="DictionaryService_transaction" class="org.springframework.transaction.interceptor.TransactionInterceptor">
|
||||
<property name="transactionManager">
|
||||
|
@@ -325,7 +325,7 @@
|
||||
<value>
|
||||
org.alfresco.service.cmr.repository.NodeService.getStores=AFTER_ACL_NODE.sys:base.Read
|
||||
org.alfresco.service.cmr.repository.NodeService.createStore=ACL_METHOD.ROLE_ADMINISTRATOR
|
||||
org.alfresco.service.cmr.repository.NodeService.exists=ACL_NODE.0.sys:base.Read
|
||||
org.alfresco.service.cmr.repository.NodeService.exists=ACL_ALLOW
|
||||
org.alfresco.service.cmr.repository.NodeService.getNodeStatus=ACL_NODE.0.sys:base.Read
|
||||
org.alfresco.service.cmr.repository.NodeService.getRootNode=ACL_NODE.0.sys:base.Read
|
||||
org.alfresco.service.cmr.repository.NodeService.createNode=ACL_NODE.0.sys:base.CreateChildren
|
||||
@@ -374,7 +374,7 @@
|
||||
org.alfresco.service.cmr.model.FileFolderService.listFolders=ACL_NODE.0.sys:base.ReadChildren,AFTER_ACL_NODE.sys:base.Read
|
||||
org.alfresco.service.cmr.model.FileFolderService.search=ACL_NODE.0.sys:base.ReadChildren,AFTER_ACL_NODE.sys:base.Read
|
||||
org.alfresco.service.cmr.model.FileFolderService.searchSimple=ACL_NODE.0.sys:base.ReadChildren,AFTER_ACL_NODE.sys:base.Read
|
||||
org.alfresco.service.cmr.model.FileFolderService.rename=ACL_PARENT.0.sys:base.CreateChildren,AFTER_ACL_NODE.sys:base.WriteProperties
|
||||
org.alfresco.service.cmr.model.FileFolderService.rename=AFTER_ACL_NODE.sys:base.WriteProperties
|
||||
org.alfresco.service.cmr.model.FileFolderService.move=ACL_NODE.0.sys:base.DeleteNode,ACL_NODE.1.sys:base.CreateChildren
|
||||
org.alfresco.service.cmr.model.FileFolderService.copy=ACL_NODE.0.sys:base.Read,ACL_NODE.1.sys:base.CreateChildren
|
||||
org.alfresco.service.cmr.model.FileFolderService.create=ACL_NODE.0.sys:base.CreateChildren
|
||||
|
@@ -65,7 +65,6 @@ db.username=alfresco
|
||||
db.password=alfresco
|
||||
db.pool.initial=10
|
||||
db.pool.max=20
|
||||
db.pool.maxIdleTime=120
|
||||
|
||||
# Email configuration
|
||||
|
||||
|
@@ -21,6 +21,9 @@
|
||||
<property name="dictionaryService">
|
||||
<ref bean="dictionaryService"/>
|
||||
</property>
|
||||
<property name="permissionService">
|
||||
<ref bean="permissionService"/>
|
||||
</property>
|
||||
<property name="rulesDisabled">
|
||||
<value>false</value>
|
||||
</property>
|
||||
|
@@ -2,9 +2,38 @@
|
||||
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||
|
||||
<beans>
|
||||
|
||||
<bean id="scriptService" class="org.alfresco.repo.jscript.RhinoScriptService">
|
||||
<property name="serviceRegistry">
|
||||
<ref bean="ServiceRegistry"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="baseScriptImplementation" abstract="true" init-method="register">
|
||||
<property name="scriptService">
|
||||
<ref bean="scriptService"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="loggerScript" parent="baseScriptImplementation" class="org.alfresco.repo.jscript.ScriptLogger">
|
||||
<property name="scriptName">
|
||||
<value>logger</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="utilsScript" parent="baseScriptImplementation" class="org.alfresco.repo.jscript.ScriptUtils">
|
||||
<property name="scriptName">
|
||||
<value>utils</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="actionsScript" parent="baseScriptImplementation" class="org.alfresco.repo.jscript.Actions">
|
||||
<property name="scriptName">
|
||||
<value>actions</value>
|
||||
</property>
|
||||
<property name="serviceRegistry">
|
||||
<ref bean="ServiceRegistry"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
173
config/alfresco/templates/content/examples/show_audit.ftl
Normal file
173
config/alfresco/templates/content/examples/show_audit.ftl
Normal file
@@ -0,0 +1,173 @@
|
||||
<#-- Shows some general audit info about the current document -->
|
||||
<#if document?exists>
|
||||
<h4>Current Docuement Audit Info</h4>
|
||||
<b>Name:</b> ${document.name}<br>
|
||||
<table border="1" cellspacing="0" cellpadding="4">
|
||||
<tr>
|
||||
<th>User Name</th>
|
||||
<th>Application</th>
|
||||
<th>Service</th>
|
||||
<th>Method</th>
|
||||
<th>Timestamp</th>
|
||||
<th>Failed</th>
|
||||
<th>Message</th>
|
||||
<th>Arg 1</th>
|
||||
<th>Arg 2</th>
|
||||
<th>Arg 3</th>
|
||||
<th>Arg 4</th>
|
||||
<th>Arg 5</th>
|
||||
<th>Return</th>
|
||||
<th>Thowable</th>
|
||||
<th>TX</th>
|
||||
</tr>
|
||||
<#list document.auditTrail as t>
|
||||
<tr>
|
||||
<td>${t.userIdentifier}</td>
|
||||
<td>${t.auditApplication}</td>
|
||||
<#if t.auditService?exists>
|
||||
<td>${t.auditService}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<#if t.auditMethod?exists>
|
||||
<td>${t.auditMethod}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<td>${t.date}</td>
|
||||
<#if t.fail?exists>
|
||||
<td>${t.fail?string("FAILED", "OK")}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<#if t.message?exists>
|
||||
<td>${t.message}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<#if t.methodArgumentsAsStrings[0]?exists>
|
||||
<td>${t.methodArgumentsAsStrings[0]}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<#if t.methodArgumentsAsStrings[1]?exists>
|
||||
<td>${t.methodArgumentsAsStrings[1]}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<#if t.methodArgumentsAsStrings[2]?exists>
|
||||
<td>${t.methodArgumentsAsStrings[2]}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<#if t.methodArgumentsAsStrings[3]?exists>
|
||||
<td>${t.methodArgumentsAsStrings[3]}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<#if t.methodArgumentsAsStrings[4]?exists>
|
||||
<td>${t.methodArgumentsAsStrings[4]}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<#if t.returnObjectAsString?exists>
|
||||
<td>${t.returnObjectAsString}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<#if t.throwableAsString?exists>
|
||||
<td>${t.throwableAsString}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<td>${t.txId}</td>
|
||||
</tr>
|
||||
</#list>
|
||||
</table>
|
||||
<#elseif space?exists>
|
||||
<h4>Current Space Audit Info:</h4>
|
||||
<b>Name:</b> ${space.name}<br>
|
||||
<table border="1" cellspacing="0" cellpadding="4">
|
||||
<tr>
|
||||
<th>User Name</th>
|
||||
<th>Application</th>
|
||||
<th>Service</th>
|
||||
<th>Method</th>
|
||||
<th>Timestamp</th>
|
||||
<th>Failed</th>
|
||||
<th>Message</th>
|
||||
<th>Arg 1</th>
|
||||
<th>Arg 2</th>
|
||||
<th>Arg 3</th>
|
||||
<th>Arg 4</th>
|
||||
<th>Arg 5</th>
|
||||
<th>Return</th>
|
||||
<th>Thowable</th>
|
||||
<th>TX</th>
|
||||
</tr>
|
||||
|
||||
<#list space.auditTrail as t>
|
||||
<tr>
|
||||
<td>${t.userIdentifier}</td>
|
||||
<td>${t.auditApplication}</td>
|
||||
<#if t.auditService?exists>
|
||||
<td>${t.auditService}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<#if t.auditMethod?exists>
|
||||
<td>${t.auditMethod}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<td>${t.date}</td>
|
||||
<#if t.fail?exists>
|
||||
<td>${t.fail?string("FAILED", "OK")}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<#if t.message?exists>
|
||||
<td>${t.message}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<#if t.methodArgumentsAsStrings[0]?exists>
|
||||
<td>${t.methodArgumentsAsStrings[0]}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<#if t.methodArgumentsAsStrings[1]?exists>
|
||||
<td>${t.methodArgumentsAsStrings[1]}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<#if t.methodArgumentsAsStrings[2]?exists>
|
||||
<td>${t.methodArgumentsAsStrings[2]}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<#if t.methodArgumentsAsStrings[3]?exists>
|
||||
<td>${t.methodArgumentsAsStrings[3]}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<#if t.methodArgumentsAsStrings[4]?exists>
|
||||
<td>${t.methodArgumentsAsStrings[4]}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<#if t.returnObjectAsString?exists>
|
||||
<td>${t.returnObjectAsString}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<#if t.throwableAsString?exists>
|
||||
<td>${t.throwableAsString}</td>
|
||||
<#else>
|
||||
<td> </td>
|
||||
</#if>
|
||||
<td>${t.txId}</td>
|
||||
</tr>
|
||||
</#list>
|
||||
</table>
|
||||
</#if>
|
@@ -126,17 +126,17 @@
|
||||
</view:properties>
|
||||
<view:associations></view:associations>
|
||||
</cm:content>
|
||||
<cm:content xmlns:alf="http://www.alfresco.org" xmlns:d="http://www.alfresco.org/model/dictionary/1.0" xmlns:view="http://www.alfresco.org/view/repository/1.0" xmlns:sys="http://www.alfresco.org/model/system/1.0" xmlns:act="http://www.alfresco.org/model/action/1.0" xmlns:rule="http://www.alfresco.org/model/rule/1.0" xmlns:fm="http://www.alfresco.org/model/forum/1.0" xmlns:app="http://www.alfresco.org/model/application/1.0" xmlns:usr="http://www.alfresco.org/model/user/1.0" xmlns:ver="http://www.alfresco.org/model/versionstore/1.0" xmlns:cm="http://www.alfresco.org/model/content/1.0" xmlns="" view:childName="cm:records_report.ftl">
|
||||
<cm:content xmlns:alf="http://www.alfresco.org" xmlns:d="http://www.alfresco.org/model/dictionary/1.0" xmlns:view="http://www.alfresco.org/view/repository/1.0" xmlns:sys="http://www.alfresco.org/model/system/1.0" xmlns:act="http://www.alfresco.org/model/action/1.0" xmlns:rule="http://www.alfresco.org/model/rule/1.0" xmlns:fm="http://www.alfresco.org/model/forum/1.0" xmlns:app="http://www.alfresco.org/model/application/1.0" xmlns:usr="http://www.alfresco.org/model/user/1.0" xmlns:ver="http://www.alfresco.org/model/versionstore/1.0" xmlns:cm="http://www.alfresco.org/model/content/1.0" xmlns="" view:childName="cm:show_audit.ftl">
|
||||
<view:aspects>
|
||||
<cm:titled></cm:titled>
|
||||
<app:inlineeditable></app:inlineeditable>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<app:editInline>true</app:editInline>
|
||||
<cm:description>Displays the current state of records in a file plan space or a space containing a file plan.</cm:description>
|
||||
<cm:content>contentUrl=classpath:alfresco/templates/content/examples/records_report.ftl|mimetype=text/plain|size=6134|encoding=UTF-8</cm:content>
|
||||
<cm:title>records_report.ftl</cm:title>
|
||||
<cm:name>records_report.ftl</cm:name>
|
||||
<cm:description>Displays the audit trail for an object.</cm:description>
|
||||
<cm:content>contentUrl=classpath:alfresco/templates/content/examples/show_audit.ftl|mimetype=text/plain|size=6134|encoding=UTF-8</cm:content>
|
||||
<cm:title>show_audit.ftl</cm:title>
|
||||
<cm:name>show_audit.ftl</cm:name>
|
||||
</view:properties>
|
||||
<view:associations></view:associations>
|
||||
</cm:content>
|
||||
|
@@ -7,7 +7,7 @@
|
||||
version.major=1
|
||||
version.minor=4
|
||||
version.revision=0
|
||||
version.label=RC1
|
||||
version.label=
|
||||
|
||||
# Edition label
|
||||
|
||||
|
@@ -23,26 +23,33 @@
|
||||
<property name="importerBootstrap" ref="spacesBootstrap"/>
|
||||
<property name="searchService" ref="searchService"/>
|
||||
<property name="nodeService" ref="nodeService"/>
|
||||
<property name="permissionService" ref="permissionService"/>
|
||||
<property name="namespaceService" ref="namespaceService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="workflowInterpreter" class="org.alfresco.repo.workflow.WorkflowInterpreter">
|
||||
<property name="workflowService" ref="WorkflowService"/>
|
||||
<property name="namespaceService" ref="namespaceService"/>
|
||||
<property name="personService" ref="PersonService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="workflowInterpreterHelp" class="org.alfresco.i18n.ResourceBundleBootstrapComponent">
|
||||
<property name="resourceBundles">
|
||||
<list>
|
||||
<value>alfresco.messages.workflow-interpreter-help</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- -->
|
||||
<!-- Workflow Action -->
|
||||
<!-- -->
|
||||
|
||||
<bean id="start-workflow" class="org.alfresco.repo.workflow.StartWorkflowActionExecuter" parent="action-executer">
|
||||
<property name="publicAction">
|
||||
<value>true</value>
|
||||
</property>
|
||||
<property name="namespaceService">
|
||||
<ref bean="NamespaceService" />
|
||||
</property>
|
||||
<property name="nodeService">
|
||||
<ref bean="NodeService" />
|
||||
</property>
|
||||
<property name="workflowService">
|
||||
<ref bean="WorkflowService" />
|
||||
</property>
|
||||
<property name="publicAction"><value>true</value></property>
|
||||
<property name="namespaceService" ref="NamespaceService"/>
|
||||
<property name="nodeService" ref="NodeService"/>
|
||||
<property name="workflowService" ref="WorkflowService"/>
|
||||
</bean>
|
||||
|
||||
<!-- -->
|
||||
@@ -73,7 +80,7 @@
|
||||
<property name="engineId" value="jbpm"/>
|
||||
<property name="JBPMTemplate" ref="jbpm_template"/>
|
||||
<property name="dictionaryService" ref="DictionaryService"/>
|
||||
<property name="namespaceService" ref="NamespaceService"/>
|
||||
<property name="namespaceService" ref="namespaceService"/>
|
||||
<property name="nodeService" ref="nodeService"/>
|
||||
<property name="personService" ref="personService"/>
|
||||
<property name="serviceRegistry" ref="ServiceRegistry"/>
|
||||
|
@@ -309,7 +309,7 @@ DesktopResponse AlfrescoInterface::runAction(AlfrescoActionInfo& action, Desktop
|
||||
// Build the run action I/O control request
|
||||
|
||||
DataBuffer reqbuf( 1024);
|
||||
DataBuffer respbuf( 256);
|
||||
DataBuffer respbuf( 4096);
|
||||
|
||||
reqbuf.putFixedString( IOSignature, IOSignatureLen);
|
||||
reqbuf.putString( action.getName());
|
||||
|
@@ -26,12 +26,11 @@ import org.alfresco.filesys.netbios.server.NetBIOSNameServer;
|
||||
import org.alfresco.filesys.server.NetworkServer;
|
||||
import org.alfresco.filesys.server.config.ServerConfiguration;
|
||||
import org.alfresco.filesys.smb.server.SMBServer;
|
||||
import org.alfresco.util.AbstractLifecycleBean;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
@@ -41,7 +40,7 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
*
|
||||
* @author GKSpencer
|
||||
*/
|
||||
public class CIFSServer implements ApplicationListener
|
||||
public class CIFSServer extends AbstractLifecycleBean
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog("org.alfresco.smb.server");
|
||||
|
||||
@@ -81,29 +80,6 @@ public class CIFSServer implements ApplicationListener
|
||||
return (filesysConfig != null && filesysConfig.isSMBServerEnabled());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
public void onApplicationEvent(ApplicationEvent event)
|
||||
{
|
||||
if (event instanceof ContextRefreshedEvent)
|
||||
{
|
||||
try
|
||||
{
|
||||
startServer();
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to start CIFS server", e);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to start CIFS server", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the CIFS server components
|
||||
*
|
||||
@@ -264,5 +240,27 @@ public class CIFSServer implements ApplicationListener
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent event)
|
||||
{
|
||||
try
|
||||
{
|
||||
startServer();
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to start CIFS server", e);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to start CIFS server", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShutdown(ApplicationEvent event)
|
||||
{
|
||||
stopServer();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -24,11 +24,11 @@ import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.filesys.ftp.FTPNetworkServer;
|
||||
import org.alfresco.filesys.server.NetworkServer;
|
||||
import org.alfresco.filesys.server.config.ServerConfiguration;
|
||||
import org.alfresco.util.AbstractLifecycleBean;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
@@ -39,7 +39,7 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
*
|
||||
* @author GKSpencer
|
||||
*/
|
||||
public class FTPServer implements ApplicationListener
|
||||
public class FTPServer extends AbstractLifecycleBean
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog("org.alfresco.ftp.server");
|
||||
|
||||
@@ -79,29 +79,6 @@ public class FTPServer implements ApplicationListener
|
||||
return (filesysConfig != null && filesysConfig.isFTPServerEnabled());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
public void onApplicationEvent(ApplicationEvent event)
|
||||
{
|
||||
if (event instanceof ContextRefreshedEvent)
|
||||
{
|
||||
try
|
||||
{
|
||||
startServer();
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to start FTP server", e);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to start FTP server", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the FTP server components
|
||||
*
|
||||
@@ -251,4 +228,28 @@ public class FTPServer implements ApplicationListener
|
||||
}
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent event)
|
||||
{
|
||||
try
|
||||
{
|
||||
startServer();
|
||||
}
|
||||
catch (SocketException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to start FTP server", e);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to start FTP server", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShutdown(ApplicationEvent event)
|
||||
{
|
||||
stopServer();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -852,7 +852,7 @@ public class FTPSrvSession extends SrvSession implements Runnable
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Logon failed", ex);
|
||||
logger.debug("Logon failed for user " + cInfo.getUserName());
|
||||
}
|
||||
|
||||
// Check if the logon was successful
|
||||
|
@@ -17,10 +17,17 @@
|
||||
package org.alfresco.filesys.server.auth;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
|
||||
import org.alfresco.filesys.server.SrvSession;
|
||||
import org.alfresco.filesys.server.auth.AuthContext;
|
||||
import org.alfresco.filesys.server.auth.CifsAuthenticator;
|
||||
import org.alfresco.filesys.server.auth.ClientInfo;
|
||||
import org.alfresco.filesys.server.auth.NTLanManAuthContext;
|
||||
import org.alfresco.filesys.smb.server.SMBSrvSession;
|
||||
import org.alfresco.filesys.util.HexDump;
|
||||
import org.alfresco.repo.security.authentication.NTLMMode;
|
||||
import org.alfresco.repo.security.authentication.ntlm.NTLMPassthruToken;
|
||||
|
||||
/**
|
||||
* Alfresco Authenticator Class
|
||||
@@ -88,10 +95,7 @@ public class AlfrescoAuthenticator extends CifsAuthenticator
|
||||
{
|
||||
// Use the existing authentication token
|
||||
|
||||
if ( client.isGuest())
|
||||
m_authComponent.setGuestUserAsCurrentUser();
|
||||
else
|
||||
m_authComponent.setCurrentUser(mapUserNameToPerson(client.getUserName()));
|
||||
m_authComponent.setCurrentUser(client.getUserName());
|
||||
|
||||
// Debug
|
||||
|
||||
@@ -107,7 +111,7 @@ public class AlfrescoAuthenticator extends CifsAuthenticator
|
||||
|
||||
int authSts = AUTH_DISALLOW;
|
||||
|
||||
if ( client.isGuest() || client.getUserName().equalsIgnoreCase(GUEST_USERNAME))
|
||||
if ( client.isGuest() || client.getUserName().equalsIgnoreCase(getGuestUserName()))
|
||||
{
|
||||
// Check if guest logons are allowed
|
||||
|
||||
@@ -140,6 +144,12 @@ public class AlfrescoAuthenticator extends CifsAuthenticator
|
||||
|
||||
authSts = doMD4UserAuthentication(client, sess, alg);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Perform passthru authentication password check
|
||||
|
||||
authSts = doPassthruUserAuthentication(client, sess, alg);
|
||||
}
|
||||
|
||||
// Check if the logon status indicates a guest logon
|
||||
|
||||
@@ -172,6 +182,64 @@ public class AlfrescoAuthenticator extends CifsAuthenticator
|
||||
return authSts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an authentication context for the new session
|
||||
*
|
||||
* @return AuthContext
|
||||
*/
|
||||
public AuthContext getAuthContext( SMBSrvSession sess)
|
||||
{
|
||||
// Check if the client is already authenticated, and it is not a null logon
|
||||
|
||||
AuthContext authCtx = null;
|
||||
|
||||
if ( sess.hasAuthenticationContext() && sess.hasAuthenticationToken() &&
|
||||
sess.getClientInformation().getLogonType() != ClientInfo.LogonNull)
|
||||
{
|
||||
// Return the previous challenge, user is already authenticated
|
||||
|
||||
authCtx = (NTLanManAuthContext) sess.getAuthenticationContext();
|
||||
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Re-using existing challenge, already authenticated");
|
||||
}
|
||||
else if ( m_authComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER)
|
||||
{
|
||||
// Create a new authentication context for the session
|
||||
|
||||
authCtx = new NTLanManAuthContext();
|
||||
sess.setAuthenticationContext( authCtx);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create an authentication token for the session
|
||||
|
||||
NTLMPassthruToken authToken = new NTLMPassthruToken();
|
||||
|
||||
// Run the first stage of the passthru authentication to get the challenge
|
||||
|
||||
m_authComponent.authenticate( authToken);
|
||||
|
||||
// Save the authentication token for the second stage of the authentication
|
||||
|
||||
sess.setAuthenticationToken(authToken);
|
||||
|
||||
// Get the challenge from the token
|
||||
|
||||
if ( authToken.getChallenge() != null)
|
||||
{
|
||||
authCtx = new NTLanManAuthContext( authToken.getChallenge().getBytes());
|
||||
sess.setAuthenticationContext( authCtx);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the authentication context
|
||||
|
||||
return authCtx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform MD4 user authentication
|
||||
*
|
||||
@@ -217,6 +285,20 @@ public class AlfrescoAuthenticator extends CifsAuthenticator
|
||||
// Validate the password
|
||||
|
||||
byte[] clientHash = client.getPassword();
|
||||
if ( clientHash == null || clientHash.length != 24)
|
||||
{
|
||||
// Use the secondary password hash from the client
|
||||
|
||||
clientHash = client.getANSIPassword();
|
||||
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug( "Using secondary password hash - " + HexDump.hexString(clientHash));
|
||||
logger.debug( " Local hash - " + HexDump.hexString( localHash));
|
||||
}
|
||||
}
|
||||
|
||||
if ( clientHash == null || clientHash.length != localHash.length)
|
||||
return CifsAuthenticator.AUTH_BADPASSWORD;
|
||||
@@ -229,7 +311,7 @@ public class AlfrescoAuthenticator extends CifsAuthenticator
|
||||
|
||||
// Set the current user to be authenticated, save the authentication token
|
||||
|
||||
client.setAuthenticationToken( m_authComponent.setCurrentUser(mapUserNameToPerson(client.getUserName())));
|
||||
client.setAuthenticationToken( m_authComponent.setCurrentUser(client.getUserName()));
|
||||
|
||||
// Get the users home folder node, if available
|
||||
|
||||
@@ -259,4 +341,101 @@ public class AlfrescoAuthenticator extends CifsAuthenticator
|
||||
|
||||
return allowGuest() ? CifsAuthenticator.AUTH_GUEST : CifsAuthenticator.AUTH_DISALLOW;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform passthru user authentication
|
||||
*
|
||||
* @param client Client information
|
||||
* @param sess Server session
|
||||
* @param alg Encryption algorithm
|
||||
* @return int
|
||||
*/
|
||||
private final int doPassthruUserAuthentication(ClientInfo client, SrvSession sess, int alg)
|
||||
{
|
||||
// Get the authentication token for the session
|
||||
|
||||
NTLMPassthruToken authToken = (NTLMPassthruToken) sess.getAuthenticationToken();
|
||||
|
||||
if ( authToken == null)
|
||||
return CifsAuthenticator.AUTH_DISALLOW;
|
||||
|
||||
// Get the appropriate hashed password for the algorithm
|
||||
|
||||
int authSts = CifsAuthenticator.AUTH_DISALLOW;
|
||||
byte[] hashedPassword = null;
|
||||
|
||||
if ( alg == NTLM1)
|
||||
hashedPassword = client.getPassword();
|
||||
else if ( alg == LANMAN)
|
||||
hashedPassword = client.getANSIPassword();
|
||||
else
|
||||
{
|
||||
// Invalid/unsupported algorithm specified
|
||||
|
||||
return CifsAuthenticator.AUTH_DISALLOW;
|
||||
}
|
||||
|
||||
// Set the username and hashed password in the authentication token
|
||||
|
||||
authToken.setUserAndPassword( client.getUserName(), hashedPassword, alg);
|
||||
|
||||
// Authenticate the user
|
||||
|
||||
Authentication genAuthToken = null;
|
||||
|
||||
try
|
||||
{
|
||||
// Run the second stage of the passthru authentication
|
||||
|
||||
genAuthToken = m_authComponent.authenticate( authToken);
|
||||
|
||||
// Check if the user has been logged on as a guest
|
||||
|
||||
if (authToken.isGuestLogon())
|
||||
{
|
||||
|
||||
// Check if the local server allows guest access
|
||||
|
||||
if (allowGuest() == true)
|
||||
{
|
||||
|
||||
// Allow the user access as a guest
|
||||
|
||||
authSts = CifsAuthenticator.AUTH_GUEST;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Allow the user full access to the server
|
||||
|
||||
authSts = CifsAuthenticator.AUTH_ALLOW;
|
||||
}
|
||||
|
||||
// Set the current user to be authenticated, save the authentication token
|
||||
|
||||
client.setAuthenticationToken( genAuthToken);
|
||||
|
||||
// Get the users home folder node, if available
|
||||
|
||||
getHomeFolderForUser( client);
|
||||
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Auth token " + genAuthToken);
|
||||
}
|
||||
catch ( Exception ex)
|
||||
{
|
||||
logger.error("Error during passthru authentication", ex);
|
||||
}
|
||||
|
||||
// Clear the authentication token
|
||||
|
||||
sess.setAuthenticationToken(null);
|
||||
|
||||
// Return the authentication status
|
||||
|
||||
return authSts;
|
||||
}
|
||||
}
|
@@ -470,7 +470,7 @@ public abstract class CifsAuthenticator
|
||||
// Store the client maximum buffer size, maximum multiplexed requests count and client
|
||||
// capability flags
|
||||
|
||||
sess.setClientMaximumBufferSize(maxBufSize);
|
||||
sess.setClientMaximumBufferSize(maxBufSize != 0 ? maxBufSize : SMBSrvSession.DefaultBufferSize);
|
||||
sess.setClientMaximumMultiplex(maxMpx);
|
||||
sess.setClientCapabilities(capabs);
|
||||
|
||||
|
@@ -71,6 +71,10 @@ public class ClientInfo
|
||||
|
||||
private Authentication m_authToken;
|
||||
|
||||
// Authentication ticket, used for web access without having to re-authenticate
|
||||
|
||||
private String m_authTicket;
|
||||
|
||||
// Home folder node
|
||||
|
||||
private NodeRef m_homeNode;
|
||||
@@ -287,6 +291,26 @@ public class ClientInfo
|
||||
return m_authToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the client has an authentication ticket
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean hasAuthenticationTicket()
|
||||
{
|
||||
return m_authTicket != null ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the authentication ticket
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public final String getAuthenticationTicket()
|
||||
{
|
||||
return m_authTicket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the client has a home folder node
|
||||
*
|
||||
@@ -410,6 +434,16 @@ public class ClientInfo
|
||||
m_authToken = token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the authentication ticket
|
||||
*
|
||||
* @param ticket String
|
||||
*/
|
||||
public final void setAuthenticationTicket(String ticket)
|
||||
{
|
||||
m_authTicket = ticket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the home folder node
|
||||
*
|
||||
@@ -449,6 +483,12 @@ public class ClientInfo
|
||||
str.append(getAuthenticationToken());
|
||||
}
|
||||
|
||||
if ( hasAuthenticationTicket())
|
||||
{
|
||||
str.append(",ticket=");
|
||||
str.append(getAuthenticationTicket());
|
||||
}
|
||||
|
||||
if (isGuest())
|
||||
str.append(",Guest");
|
||||
str.append("]");
|
||||
|
@@ -584,7 +584,7 @@ public class EnterpriseCifsAuthenticator extends CifsAuthenticator implements Ca
|
||||
|
||||
// Store the client maximum buffer size, maximum multiplexed requests count and client capability flags
|
||||
|
||||
sess.setClientMaximumBufferSize(maxBufSize);
|
||||
sess.setClientMaximumBufferSize(maxBufSize != 0 ? maxBufSize : SMBSrvSession.DefaultBufferSize);
|
||||
sess.setClientMaximumMultiplex(maxMpx);
|
||||
sess.setClientCapabilities(capabs);
|
||||
|
||||
|
@@ -1,427 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2006 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* 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.filesys.server.auth.ntlm;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
|
||||
import org.alfresco.filesys.server.SrvSession;
|
||||
import org.alfresco.filesys.server.auth.AuthContext;
|
||||
import org.alfresco.filesys.server.auth.CifsAuthenticator;
|
||||
import org.alfresco.filesys.server.auth.ClientInfo;
|
||||
import org.alfresco.filesys.server.auth.NTLanManAuthContext;
|
||||
import org.alfresco.filesys.smb.server.SMBSrvSession;
|
||||
import org.alfresco.filesys.util.DataPacker;
|
||||
import org.alfresco.repo.security.authentication.NTLMMode;
|
||||
import org.alfresco.repo.security.authentication.ntlm.NTLMPassthruToken;
|
||||
|
||||
/**
|
||||
* Alfresco Authenticator Class
|
||||
*
|
||||
* <p>The Alfresco authenticator implementation enables user level security mode using the Alfresco authentication
|
||||
* component.
|
||||
*
|
||||
* <p>Note: Switching off encrypted password support will cause later NT4 service pack releases and
|
||||
* Win2000 to refuse to connect to the server without a registry update on the client.
|
||||
*
|
||||
* @author GKSpencer
|
||||
*/
|
||||
public class AlfrescoAuthenticator extends CifsAuthenticator
|
||||
{
|
||||
/**
|
||||
* Default Constructor
|
||||
*
|
||||
* <p>Default to user mode security with encrypted password support.
|
||||
*/
|
||||
public AlfrescoAuthenticator()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the authentication component supports the required mode
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected boolean validateAuthenticationMode()
|
||||
{
|
||||
// Make sure the authentication component supports MD4 hashed passwords or passthru mode
|
||||
|
||||
if ( m_authComponent.getNTLMMode() != NTLMMode.MD4_PROVIDER &&
|
||||
m_authComponent.getNTLMMode() != NTLMMode.PASS_THROUGH)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate a user
|
||||
*
|
||||
* @param client Client information
|
||||
* @param sess Server session
|
||||
* @param alg Encryption algorithm
|
||||
*/
|
||||
public int authenticateUser(ClientInfo client, SrvSession sess, int alg)
|
||||
{
|
||||
// Check if this is an SMB/CIFS null session logon.
|
||||
//
|
||||
// The null session will only be allowed to connect to the IPC$ named pipe share.
|
||||
|
||||
if (client.isNullSession() && sess instanceof SMBSrvSession)
|
||||
{
|
||||
// Debug
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Null CIFS logon allowed");
|
||||
|
||||
return CifsAuthenticator.AUTH_ALLOW;
|
||||
}
|
||||
|
||||
// Check if the client is already authenticated, and it is not a null logon
|
||||
|
||||
if ( client.getAuthenticationToken() != null && client.getLogonType() != ClientInfo.LogonNull)
|
||||
{
|
||||
// Use the existing authentication token
|
||||
|
||||
m_authComponent.setCurrentUser(client.getUserName());
|
||||
|
||||
// Debug
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Re-using existing authentication token");
|
||||
|
||||
// Return the authentication status
|
||||
|
||||
return client.getLogonType() != ClientInfo.LogonGuest ? AUTH_ALLOW : AUTH_GUEST;
|
||||
}
|
||||
|
||||
// Check if this is a guest logon
|
||||
|
||||
int authSts = AUTH_DISALLOW;
|
||||
|
||||
if ( client.isGuest() || client.getUserName().equalsIgnoreCase(getGuestUserName()))
|
||||
{
|
||||
// Check if guest logons are allowed
|
||||
|
||||
if ( allowGuest() == false)
|
||||
return AUTH_DISALLOW;
|
||||
|
||||
// Get a guest authentication token
|
||||
|
||||
doGuestLogon( client, sess);
|
||||
|
||||
// Indicate logged on as guest
|
||||
|
||||
authSts = AUTH_GUEST;
|
||||
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Authenticated user " + client.getUserName() + " sts=" + getStatusAsString(authSts));
|
||||
|
||||
// Return the guest status
|
||||
|
||||
return authSts;
|
||||
}
|
||||
|
||||
// Check if MD4 or passthru mode is configured
|
||||
|
||||
else if ( m_authComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER)
|
||||
{
|
||||
// Perform local MD4 password check
|
||||
|
||||
authSts = doMD4UserAuthentication(client, sess, alg);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Perform passthru authentication password check
|
||||
|
||||
authSts = doPassthruUserAuthentication(client, sess, alg);
|
||||
}
|
||||
|
||||
// Check if the logon status indicates a guest logon
|
||||
|
||||
if ( authSts == AUTH_GUEST)
|
||||
{
|
||||
// Only allow the guest logon if user mapping is enabled
|
||||
|
||||
if ( mapUnknownUserToGuest())
|
||||
{
|
||||
// Logon as guest, setup the security context
|
||||
|
||||
doGuestLogon( client, sess);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do not allow the guest logon
|
||||
|
||||
authSts = AUTH_DISALLOW;
|
||||
}
|
||||
}
|
||||
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Authenticated user " + client.getUserName() + " sts=" + getStatusAsString(authSts) +
|
||||
" via " + (m_authComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER ? "MD4" : "Passthru"));
|
||||
|
||||
// Return the authentication status
|
||||
|
||||
return authSts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an authentication context for the new session
|
||||
*
|
||||
* @return AuthContext
|
||||
*/
|
||||
public AuthContext getAuthContext( SMBSrvSession sess)
|
||||
{
|
||||
// Check if the client is already authenticated, and it is not a null logon
|
||||
|
||||
AuthContext authCtx = null;
|
||||
|
||||
if ( sess.hasAuthenticationContext() && sess.hasAuthenticationToken() &&
|
||||
sess.getClientInformation().getLogonType() != ClientInfo.LogonNull)
|
||||
{
|
||||
// Return the previous challenge, user is already authenticated
|
||||
|
||||
authCtx = (NTLanManAuthContext) sess.getAuthenticationContext();
|
||||
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Re-using existing challenge, already authenticated");
|
||||
}
|
||||
else if ( m_authComponent.getNTLMMode() == NTLMMode.MD4_PROVIDER)
|
||||
{
|
||||
// Create a new authentication context for the session
|
||||
|
||||
authCtx = new NTLanManAuthContext();
|
||||
sess.setAuthenticationContext( authCtx);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create an authentication token for the session
|
||||
|
||||
NTLMPassthruToken authToken = new NTLMPassthruToken();
|
||||
|
||||
// Run the first stage of the passthru authentication to get the challenge
|
||||
|
||||
m_authComponent.authenticate( authToken);
|
||||
|
||||
// Save the authentication token for the second stage of the authentication
|
||||
|
||||
sess.setAuthenticationToken(authToken);
|
||||
|
||||
// Get the challenge from the token
|
||||
|
||||
if ( authToken.getChallenge() != null)
|
||||
{
|
||||
authCtx = new NTLanManAuthContext( authToken.getChallenge().getBytes());
|
||||
sess.setAuthenticationContext( authCtx);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the authentication context
|
||||
|
||||
return authCtx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform MD4 user authentication
|
||||
*
|
||||
* @param client Client information
|
||||
* @param sess Server session
|
||||
* @param alg Encryption algorithm
|
||||
* @return int
|
||||
*/
|
||||
private final int doMD4UserAuthentication(ClientInfo client, SrvSession sess, int alg)
|
||||
{
|
||||
// Get the stored MD4 hashed password for the user, or null if the user does not exist
|
||||
|
||||
String md4hash = m_authComponent.getMD4HashedPassword(client.getUserName());
|
||||
|
||||
if ( md4hash != null)
|
||||
{
|
||||
// Check if the client has supplied an NTLM hashed password, if not then do not allow access
|
||||
|
||||
if ( client.getPassword() == null)
|
||||
return CifsAuthenticator.AUTH_BADPASSWORD;
|
||||
|
||||
try
|
||||
{
|
||||
// Generate the local encrypted password using the challenge that was sent to the client
|
||||
|
||||
byte[] p21 = new byte[21];
|
||||
byte[] md4byts = m_md4Encoder.decodeHash(md4hash);
|
||||
System.arraycopy(md4byts, 0, p21, 0, 16);
|
||||
|
||||
// Get the challenge that was sent to the client
|
||||
|
||||
NTLanManAuthContext authCtx = null;
|
||||
|
||||
if ( sess.hasAuthenticationContext() && sess.getAuthenticationContext() instanceof NTLanManAuthContext)
|
||||
authCtx = (NTLanManAuthContext) sess.getAuthenticationContext();
|
||||
else
|
||||
return CifsAuthenticator.AUTH_DISALLOW;
|
||||
|
||||
// Generate the local hash of the password using the same challenge
|
||||
|
||||
byte[] localHash = getEncryptor().doNTLM1Encryption(p21, authCtx.getChallenge());
|
||||
|
||||
// Validate the password
|
||||
|
||||
byte[] clientHash = client.getPassword();
|
||||
|
||||
if ( clientHash == null || clientHash.length != localHash.length)
|
||||
return CifsAuthenticator.AUTH_BADPASSWORD;
|
||||
|
||||
for ( int i = 0; i < clientHash.length; i++)
|
||||
{
|
||||
if ( clientHash[i] != localHash[i])
|
||||
return CifsAuthenticator.AUTH_BADPASSWORD;
|
||||
}
|
||||
|
||||
// Set the current user to be authenticated, save the authentication token
|
||||
|
||||
client.setAuthenticationToken( m_authComponent.setCurrentUser(client.getUserName()));
|
||||
|
||||
// Get the users home folder node, if available
|
||||
|
||||
getHomeFolderForUser( client);
|
||||
|
||||
// Passwords match, grant access
|
||||
|
||||
return CifsAuthenticator.AUTH_ALLOW;
|
||||
}
|
||||
catch (NoSuchAlgorithmException ex)
|
||||
{
|
||||
}
|
||||
|
||||
// Error during password check, do not allow access
|
||||
|
||||
return CifsAuthenticator.AUTH_DISALLOW;
|
||||
}
|
||||
|
||||
// Check if this is an SMB/CIFS null session logon.
|
||||
//
|
||||
// The null session will only be allowed to connect to the IPC$ named pipe share.
|
||||
|
||||
if (client.isNullSession() && sess instanceof SMBSrvSession)
|
||||
return CifsAuthenticator.AUTH_ALLOW;
|
||||
|
||||
// User does not exist, check if guest access is allowed
|
||||
|
||||
return allowGuest() ? CifsAuthenticator.AUTH_GUEST : CifsAuthenticator.AUTH_DISALLOW;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform passthru user authentication
|
||||
*
|
||||
* @param client Client information
|
||||
* @param sess Server session
|
||||
* @param alg Encryption algorithm
|
||||
* @return int
|
||||
*/
|
||||
private final int doPassthruUserAuthentication(ClientInfo client, SrvSession sess, int alg)
|
||||
{
|
||||
// Get the authentication token for the session
|
||||
|
||||
NTLMPassthruToken authToken = (NTLMPassthruToken) sess.getAuthenticationToken();
|
||||
|
||||
if ( authToken == null)
|
||||
return CifsAuthenticator.AUTH_DISALLOW;
|
||||
|
||||
// Get the appropriate hashed password for the algorithm
|
||||
|
||||
int authSts = CifsAuthenticator.AUTH_DISALLOW;
|
||||
byte[] hashedPassword = null;
|
||||
|
||||
if ( alg == NTLM1)
|
||||
hashedPassword = client.getPassword();
|
||||
else if ( alg == LANMAN)
|
||||
hashedPassword = client.getANSIPassword();
|
||||
else
|
||||
{
|
||||
// Invalid/unsupported algorithm specified
|
||||
|
||||
return CifsAuthenticator.AUTH_DISALLOW;
|
||||
}
|
||||
|
||||
// Set the username and hashed password in the authentication token
|
||||
|
||||
authToken.setUserAndPassword( client.getUserName(), hashedPassword, alg);
|
||||
|
||||
// Authenticate the user
|
||||
|
||||
Authentication genAuthToken = null;
|
||||
|
||||
try
|
||||
{
|
||||
// Run the second stage of the passthru authentication
|
||||
|
||||
genAuthToken = m_authComponent.authenticate( authToken);
|
||||
|
||||
// Check if the user has been logged on as a guest
|
||||
|
||||
if (authToken.isGuestLogon())
|
||||
{
|
||||
|
||||
// Check if the local server allows guest access
|
||||
|
||||
if (allowGuest() == true)
|
||||
{
|
||||
|
||||
// Allow the user access as a guest
|
||||
|
||||
authSts = CifsAuthenticator.AUTH_GUEST;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Allow the user full access to the server
|
||||
|
||||
authSts = CifsAuthenticator.AUTH_ALLOW;
|
||||
}
|
||||
|
||||
// Set the current user to be authenticated, save the authentication token
|
||||
|
||||
client.setAuthenticationToken( genAuthToken);
|
||||
|
||||
// Get the users home folder node, if available
|
||||
|
||||
getHomeFolderForUser( client);
|
||||
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Auth token " + genAuthToken);
|
||||
}
|
||||
catch ( Exception ex)
|
||||
{
|
||||
logger.error("Error during passthru authentication", ex);
|
||||
}
|
||||
|
||||
// Clear the authentication token
|
||||
|
||||
sess.setAuthenticationToken(null);
|
||||
|
||||
// Return the authentication status
|
||||
|
||||
return authSts;
|
||||
}
|
||||
}
|
@@ -39,6 +39,10 @@ public class NTLMLogonDetails
|
||||
|
||||
private String m_authSrvAddr;
|
||||
|
||||
// Date/time authentication was started
|
||||
|
||||
private long m_createTime;
|
||||
|
||||
// Date/time the user was authenticated
|
||||
|
||||
private long m_authTime;
|
||||
@@ -61,6 +65,7 @@ public class NTLMLogonDetails
|
||||
*/
|
||||
public NTLMLogonDetails()
|
||||
{
|
||||
m_createTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,6 +79,8 @@ public class NTLMLogonDetails
|
||||
*/
|
||||
public NTLMLogonDetails(String user, String wks, String domain, boolean guest, String authSrv)
|
||||
{
|
||||
m_createTime = System.currentTimeMillis();
|
||||
|
||||
setDetails(user, wks, domain, guest, authSrv);
|
||||
}
|
||||
|
||||
@@ -117,6 +124,16 @@ public class NTLMLogonDetails
|
||||
return m_authSrvAddr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the date/time the authentication was started
|
||||
*
|
||||
* @return long
|
||||
*/
|
||||
public final long createdAt()
|
||||
{
|
||||
return m_createTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the date/time the user was authenticated
|
||||
*
|
||||
|
@@ -81,11 +81,10 @@ import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.AbstractLifecycleBean;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -93,7 +92,7 @@ import org.springframework.context.event.ContextRefreshedEvent;
|
||||
*
|
||||
* @author Gary K. Spencer
|
||||
*/
|
||||
public class ServerConfiguration implements ApplicationListener
|
||||
public class ServerConfiguration extends AbstractLifecycleBean
|
||||
{
|
||||
// Debug logging
|
||||
|
||||
@@ -425,18 +424,6 @@ public class ServerConfiguration implements ApplicationListener
|
||||
return initialised;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
public void onApplicationEvent(ApplicationEvent event)
|
||||
{
|
||||
if (event instanceof ContextRefreshedEvent)
|
||||
{
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the configuration using the configuration service
|
||||
*/
|
||||
@@ -1791,9 +1778,7 @@ public class ServerConfiguration implements ApplicationListener
|
||||
|
||||
// Load the Alfresco authenticator dynamically
|
||||
|
||||
auth = loadAuthenticatorClass("org.alfresco.filesys.server.auth.ntlm.AlfrescoAuthenticator");
|
||||
if ( auth == null)
|
||||
auth = loadAuthenticatorClass("org.alfresco.filesys.server.auth.AlfrescoAuthenticator");
|
||||
auth = loadAuthenticatorClass("org.alfresco.filesys.server.auth.AlfrescoAuthenticator");
|
||||
|
||||
if ( auth == null)
|
||||
throw new AlfrescoRuntimeException("Failed to load Alfresco authenticator");
|
||||
@@ -3359,4 +3344,17 @@ public class ServerConfiguration implements ApplicationListener
|
||||
|
||||
return srvAuth;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent event)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShutdown(ApplicationEvent event)
|
||||
{
|
||||
// NO-OP
|
||||
}
|
||||
|
||||
}
|
@@ -18,6 +18,7 @@ package org.alfresco.filesys.smb.server.repo;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.util.List;
|
||||
|
||||
import javax.transaction.UserTransaction;
|
||||
@@ -58,7 +59,6 @@ import org.alfresco.filesys.util.WildCard;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
|
||||
import org.alfresco.service.cmr.lock.NodeLockedException;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@@ -66,6 +66,7 @@ import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
@@ -91,6 +92,10 @@ public class ContentDiskDriver implements DiskInterface, IOCtlInterface
|
||||
private static final String KEY_ROOT_PATH = "rootPath";
|
||||
private static final String KEY_RELATIVE_PATH = "relativePath";
|
||||
|
||||
// Token name to substitute current servers DNS name or TCP/IP address into the webapp URL
|
||||
|
||||
private static final String TokenLocalName = "${localname}";
|
||||
|
||||
// Services and helpers
|
||||
|
||||
private CifsHelper cifsHelper;
|
||||
@@ -102,6 +107,7 @@ public class ContentDiskDriver implements DiskInterface, IOCtlInterface
|
||||
private PermissionService permissionService;
|
||||
|
||||
private AuthenticationComponent authComponent;
|
||||
private AuthenticationService authService;
|
||||
|
||||
// Service registry for desktop actions
|
||||
|
||||
@@ -127,6 +133,16 @@ public class ContentDiskDriver implements DiskInterface, IOCtlInterface
|
||||
return this.cifsHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the authentication service
|
||||
*
|
||||
* @return AuthenticationService
|
||||
*/
|
||||
public final AuthenticationService getAuthenticationService()
|
||||
{
|
||||
return authService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the transaction service
|
||||
*
|
||||
@@ -256,6 +272,16 @@ public class ContentDiskDriver implements DiskInterface, IOCtlInterface
|
||||
this.authComponent = authComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the authentication service
|
||||
*
|
||||
* @param authService AuthenticationService
|
||||
*/
|
||||
public void setAuthenticationService(AuthenticationService authService)
|
||||
{
|
||||
this.authService = authService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse and validate the parameter string and create a device context object for this instance
|
||||
* of the shared device. The same DeviceInterface implementation may be used for multiple
|
||||
@@ -418,7 +444,39 @@ public class ContentDiskDriver implements DiskInterface, IOCtlInterface
|
||||
if ( pseudoName.getValue().endsWith(".url") == false)
|
||||
throw new DeviceContextException("URL link file must end with .url, " + pseudoName.getValue());
|
||||
|
||||
// Set the URL link file name and web path
|
||||
// Check if the URL path name contains the local name token
|
||||
|
||||
int pos = path.indexOf(TokenLocalName);
|
||||
if (pos != -1)
|
||||
{
|
||||
|
||||
// Get the local server name
|
||||
|
||||
String srvName = "localhost";
|
||||
|
||||
try
|
||||
{
|
||||
srvName = InetAddress.getLocalHost().getHostName();
|
||||
}
|
||||
catch ( Exception ex)
|
||||
{
|
||||
}
|
||||
|
||||
// Rebuild the host name substituting the token with the local server name
|
||||
|
||||
StringBuilder hostStr = new StringBuilder();
|
||||
|
||||
hostStr.append( path.substring(0, pos));
|
||||
hostStr.append(srvName);
|
||||
|
||||
pos += TokenLocalName.length();
|
||||
if (pos < path.length())
|
||||
hostStr.append( path.substring(pos));
|
||||
|
||||
path = hostStr.toString();
|
||||
}
|
||||
|
||||
// Set the URL link file name and web path
|
||||
|
||||
context.setURLFileName( pseudoName.getValue());
|
||||
context.setURLPrefix( path);
|
||||
|
@@ -19,6 +19,7 @@ package org.alfresco.filesys.smb.server.repo;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
import org.alfresco.filesys.server.SrvSession;
|
||||
import org.alfresco.filesys.server.auth.ClientInfo;
|
||||
import org.alfresco.filesys.server.filesys.IOControlNotImplementedException;
|
||||
import org.alfresco.filesys.server.filesys.NetworkFile;
|
||||
import org.alfresco.filesys.server.filesys.TreeConnection;
|
||||
@@ -30,10 +31,12 @@ import org.alfresco.filesys.smb.server.repo.ContentDiskDriver;
|
||||
import org.alfresco.filesys.smb.server.repo.IOControlHandler;
|
||||
import org.alfresco.filesys.util.DataBuffer;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
import org.alfresco.service.cmr.lock.LockType;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -85,6 +88,16 @@ public class ContentIOControlHandler implements IOControlHandler
|
||||
return contentDriver.getCifsHelper();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the authentication service
|
||||
*
|
||||
* @return AuthenticationService
|
||||
*/
|
||||
public final AuthenticationService getAuthenticationService()
|
||||
{
|
||||
return contentDriver.getAuthenticationService();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the transaction service
|
||||
*
|
||||
@@ -512,6 +525,11 @@ public class ContentIOControlHandler implements IOControlHandler
|
||||
|
||||
sess.beginTransaction( getTransactionService(), true);
|
||||
|
||||
// Get an authentication ticket for the client, or validate the existing ticket. The ticket can be used when
|
||||
// generating URLs for the client-side application so that the user does not have to re-authenticate
|
||||
|
||||
getTicketForClient( sess);
|
||||
|
||||
// Get the list of targets for the action
|
||||
|
||||
int targetCnt = reqBuf.getInt();
|
||||
@@ -624,4 +642,65 @@ public class ContentIOControlHandler implements IOControlHandler
|
||||
|
||||
return respBuf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get, or validate, an authentication ticket for the client
|
||||
*
|
||||
* @param sess SrvSession
|
||||
*/
|
||||
private final void getTicketForClient(SrvSession sess)
|
||||
{
|
||||
// Get the client information and check if there is a ticket allocated
|
||||
|
||||
ClientInfo cInfo = sess.getClientInformation();
|
||||
if ( cInfo == null)
|
||||
return;
|
||||
|
||||
boolean needTicket = true;
|
||||
|
||||
if ( cInfo.hasAuthenticationTicket())
|
||||
{
|
||||
// Validate the existing ticket, it may have expired
|
||||
|
||||
try
|
||||
{
|
||||
// Validate the existing ticket
|
||||
|
||||
getAuthenticationService().validate( cInfo.getAuthenticationTicket());
|
||||
needTicket = false;
|
||||
}
|
||||
catch ( AuthenticationException ex)
|
||||
{
|
||||
// Invalidate the current ticket
|
||||
|
||||
try
|
||||
{
|
||||
getAuthenticationService().invalidateTicket( cInfo.getAuthenticationTicket());
|
||||
cInfo.setAuthenticationTicket( null);
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Error during invalidate ticket", ex2);
|
||||
}
|
||||
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Auth ticket expired or invalid");
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a ticket needs to be allocated
|
||||
|
||||
if ( needTicket == true)
|
||||
{
|
||||
// Allocate a new ticket and store in the client information for this session
|
||||
|
||||
String ticket = getAuthenticationService().getCurrentTicket();
|
||||
cInfo.setAuthenticationTicket( ticket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -19,10 +19,12 @@ package org.alfresco.filesys.smb.server.repo;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
|
||||
import org.alfresco.config.ConfigElement;
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.filesys.server.filesys.DiskSharedDevice;
|
||||
import org.alfresco.filesys.smb.server.repo.pseudo.LocalPseudoFile;
|
||||
import org.alfresco.filesys.smb.server.repo.pseudo.PseudoFile;
|
||||
@@ -88,7 +90,11 @@ public abstract class DesktopAction {
|
||||
public static final int StsLaunchURL = 7;
|
||||
public static final int StsCommandLine = 8;
|
||||
|
||||
// Action name
|
||||
// Token name to substitute current servers DNS name or TCP/IP address into the webapp URL
|
||||
|
||||
private static final String TokenLocalName = "${localname}";
|
||||
|
||||
// Action name
|
||||
|
||||
private String m_name;
|
||||
|
||||
@@ -109,6 +115,10 @@ public abstract class DesktopAction {
|
||||
private ContentDiskDriver m_contentDriver;
|
||||
private ContentContext m_contentContext;
|
||||
|
||||
// Webapp URL
|
||||
|
||||
private String m_webappURL;
|
||||
|
||||
// Debug enable flag
|
||||
|
||||
private boolean m_debug;
|
||||
@@ -254,6 +264,26 @@ public abstract class DesktopAction {
|
||||
return m_debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the webapp URL is set
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean hasWebappURL()
|
||||
{
|
||||
return m_webappURL != null ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the webapp URL
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public final String getWebappURL()
|
||||
{
|
||||
return m_webappURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the desktop action
|
||||
*
|
||||
@@ -349,6 +379,49 @@ public abstract class DesktopAction {
|
||||
if ( findConfigElement("noConfirm", global, config) != null && hasPreProcessAction(PreConfirmAction))
|
||||
setPreProcessActions(getPreProcessActions() - PreConfirmAction);
|
||||
|
||||
// Check if the webapp URL has been specified
|
||||
|
||||
ConfigElement webURL = findConfigElement("webpath", global, config);
|
||||
if ( webURL != null)
|
||||
{
|
||||
// Check if the path name contains the local name token
|
||||
|
||||
String webPath = webURL.getValue();
|
||||
if ( webPath.endsWith("/") == false)
|
||||
webPath = webPath + "/";
|
||||
|
||||
int pos = webPath.indexOf(TokenLocalName);
|
||||
if (pos != -1)
|
||||
{
|
||||
|
||||
// Get the local server name
|
||||
|
||||
String srvName = "localhost";
|
||||
|
||||
try
|
||||
{
|
||||
srvName = InetAddress.getLocalHost().getHostName();
|
||||
}
|
||||
catch ( Exception ex)
|
||||
{
|
||||
}
|
||||
|
||||
// Rebuild the host name substituting the token with the local server name
|
||||
|
||||
StringBuilder hostStr = new StringBuilder();
|
||||
|
||||
hostStr.append(webPath.substring(0, pos));
|
||||
hostStr.append(srvName);
|
||||
|
||||
pos += TokenLocalName.length();
|
||||
if (pos < webPath.length())
|
||||
hostStr.append(webPath.substring(pos));
|
||||
|
||||
webPath = hostStr.toString();
|
||||
setWebappURL( webPath);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if debug output is enabled for the action
|
||||
|
||||
ConfigElement debug = findConfigElement("debug", global, config);
|
||||
@@ -511,6 +584,16 @@ public abstract class DesktopAction {
|
||||
m_debug = ena;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the webapp URL
|
||||
*
|
||||
* @param urlStr String
|
||||
*/
|
||||
public final void setWebappURL(String urlStr)
|
||||
{
|
||||
m_webappURL = urlStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equality check
|
||||
*
|
||||
|
@@ -20,6 +20,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.filesys.server.SrvSession;
|
||||
import org.alfresco.filesys.server.auth.ClientInfo;
|
||||
import org.alfresco.filesys.server.filesys.NetworkFile;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
@@ -89,6 +90,19 @@ public class DesktopParams {
|
||||
return m_session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the authentication ticket for the user/session
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public final String getTicket()
|
||||
{
|
||||
ClientInfo cInfo = m_session.getClientInformation();
|
||||
if ( cInfo != null)
|
||||
return cInfo.getAuthenticationTicket();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the working directory node
|
||||
*
|
||||
|
@@ -284,6 +284,11 @@ public class JavaScriptDesktopAction extends DesktopAction {
|
||||
model.put("deskParams", params);
|
||||
model.put("out", System.out);
|
||||
|
||||
// Add the webapp URL, if valid
|
||||
|
||||
if ( hasWebappURL())
|
||||
model.put("webURL", getWebappURL());
|
||||
|
||||
// Start a transaction
|
||||
|
||||
params.getSession().beginTransaction(getTransactionService(), false);
|
||||
|
@@ -16,6 +16,9 @@
|
||||
*/
|
||||
package org.alfresco.filesys.smb.server.repo.desk;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import org.alfresco.filesys.smb.server.repo.DesktopAction;
|
||||
import org.alfresco.filesys.smb.server.repo.DesktopParams;
|
||||
import org.alfresco.filesys.smb.server.repo.DesktopResponse;
|
||||
@@ -45,8 +48,29 @@ public class URLDesktopAction extends DesktopAction {
|
||||
@Override
|
||||
public DesktopResponse runAction(DesktopParams params) {
|
||||
|
||||
// Return a URL in the status message
|
||||
// Get the local IP address
|
||||
|
||||
return new DesktopResponse(StsLaunchURL, "http://www.alfresco.com");
|
||||
String ipAddr = null;
|
||||
|
||||
try
|
||||
{
|
||||
ipAddr = InetAddress.getLocalHost().getHostAddress();
|
||||
}
|
||||
catch (UnknownHostException ex)
|
||||
{
|
||||
}
|
||||
|
||||
// Return a URL in the status message to browse to the folder node
|
||||
|
||||
StringBuilder urlStr = new StringBuilder();
|
||||
|
||||
urlStr.append( "http://");
|
||||
urlStr.append(ipAddr);
|
||||
urlStr.append(":8080/alfresco/navigate/browse/workspace/SpacesStore/");
|
||||
urlStr.append( params.getFolderNode().getId());
|
||||
urlStr.append("?ticket=");
|
||||
urlStr.append(params.getTicket());
|
||||
|
||||
return new DesktopResponse(StsLaunchURL, urlStr.toString());
|
||||
}
|
||||
}
|
||||
|
@@ -19,7 +19,6 @@ package org.alfresco.filesys.smb.server.repo.pseudo;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.alfresco.filesys.server.filesys.AccessDeniedException;
|
||||
import org.alfresco.filesys.server.filesys.FileInfo;
|
||||
import org.alfresco.filesys.server.filesys.NetworkFile;
|
||||
import org.alfresco.filesys.smb.SeekType;
|
||||
@@ -222,9 +221,7 @@ public class MemoryNetworkFile extends NetworkFile
|
||||
*/
|
||||
public void truncateFile(long siz) throws IOException
|
||||
{
|
||||
// Do not allow the file to be written to
|
||||
|
||||
throw new AccessDeniedException("Cannot truncate pseudo file");
|
||||
// Allow the truncate, do not alter the pseduo file data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,9 +233,7 @@ public class MemoryNetworkFile extends NetworkFile
|
||||
*/
|
||||
public void writeFile(byte[] buf, int len, int pos) throws java.io.IOException
|
||||
{
|
||||
// Do not allow the file to be written to
|
||||
|
||||
throw new AccessDeniedException("Cannot write to pseudo file");
|
||||
// Allow the write, just do not do anything
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -252,8 +247,6 @@ public class MemoryNetworkFile extends NetworkFile
|
||||
*/
|
||||
public void writeFile(byte[] buf, int len, int pos, long offset) throws java.io.IOException
|
||||
{
|
||||
// Do not allow the file to be written to
|
||||
|
||||
throw new AccessDeniedException("Cannot write to pseudo file");
|
||||
// Allow the write, just do not do anything
|
||||
}
|
||||
}
|
||||
|
@@ -21,7 +21,6 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
import org.alfresco.filesys.server.filesys.AccessDeniedException;
|
||||
import org.alfresco.filesys.server.filesys.NetworkFile;
|
||||
import org.alfresco.filesys.smb.SeekType;
|
||||
|
||||
@@ -272,9 +271,7 @@ public class PseudoNetworkFile extends NetworkFile
|
||||
*/
|
||||
public void truncateFile(long siz) throws IOException
|
||||
{
|
||||
// Do not allow the file to be written to
|
||||
|
||||
throw new AccessDeniedException("Cannot truncate pseudo file");
|
||||
// Allow the truncate, just do not do anything
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -286,9 +283,7 @@ public class PseudoNetworkFile extends NetworkFile
|
||||
*/
|
||||
public void writeFile(byte[] buf, int len, int pos) throws java.io.IOException
|
||||
{
|
||||
// Do not allow the file to be written to
|
||||
|
||||
throw new AccessDeniedException("Cannot write to pseudo file");
|
||||
// Allow the write, just do not do anything
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,8 +297,6 @@ public class PseudoNetworkFile extends NetworkFile
|
||||
*/
|
||||
public void writeFile(byte[] buf, int len, int pos, long offset) throws java.io.IOException
|
||||
{
|
||||
// Do not allow the file to be written to
|
||||
|
||||
throw new AccessDeniedException("Cannot write to pseudo file");
|
||||
// Allow the write, just do not do anything
|
||||
}
|
||||
}
|
||||
|
@@ -178,7 +178,7 @@ public class JCRSystemXMLExporter implements Exporter
|
||||
Value[] mixinValues = mixinTypes.getValues();
|
||||
for (int i = 0; i < mixinValues.length; i++)
|
||||
{
|
||||
value(nodeRef, JCRMixinTypesProperty.PROPERTY_NAME, mixinValues[i], i);
|
||||
value(nodeRef, JCRMixinTypesProperty.PROPERTY_NAME, mixinValues[i].getString(), i);
|
||||
}
|
||||
endProperty(nodeRef, JCRMixinTypesProperty.PROPERTY_NAME);
|
||||
|
||||
|
@@ -162,7 +162,7 @@ public class CopyActionExecuter extends ActionExecuterAbstractBase
|
||||
else
|
||||
{
|
||||
// Create a new copy of the node
|
||||
this.copyService.copy(
|
||||
this.copyService.copyAndRename(
|
||||
actionedUponNodeRef,
|
||||
destinationParent,
|
||||
destinationAssocTypeQName,
|
||||
|
@@ -22,6 +22,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.node.integrity.IntegrityChecker;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.transaction.TransactionUtil;
|
||||
import org.alfresco.repo.transaction.TransactionUtil.TransactionWork;
|
||||
@@ -329,6 +330,9 @@ public abstract class AbstractPatch implements Patch
|
||||
{
|
||||
public String doWork() throws Exception
|
||||
{
|
||||
// downgrade integrity checking
|
||||
IntegrityChecker.setWarnInTransaction();
|
||||
|
||||
String report = applyInternal();
|
||||
// done
|
||||
return report;
|
||||
@@ -389,7 +393,8 @@ public abstract class AbstractPatch implements Patch
|
||||
|
||||
/**
|
||||
* This method does the work. All transactions and thread-safety will be taken care of by this class.
|
||||
* Any exception will result in the transaction being rolled back.
|
||||
* Any exception will result in the transaction being rolled back. Integrity checks are downgraded
|
||||
* for the duration of the transaction.
|
||||
*
|
||||
* @return Returns the report (only success messages).
|
||||
* @see #apply()
|
||||
|
@@ -21,11 +21,10 @@ import java.util.List;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.util.AbstractLifecycleBean;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
|
||||
/**
|
||||
* This component is responsible for ensuring that patches are applied
|
||||
@@ -33,7 +32,7 @@ import org.springframework.context.event.ContextRefreshedEvent;
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class PatchExecuter implements ApplicationListener
|
||||
public class PatchExecuter extends AbstractLifecycleBean
|
||||
{
|
||||
private static final String MSG_CHECKING = "patch.executer.checking";
|
||||
private static final String MSG_NO_PATCHES_REQUIRED = "patch.executer.no_patches_required";
|
||||
@@ -101,16 +100,16 @@ public class PatchExecuter implements ApplicationListener
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
public void onApplicationEvent(ApplicationEvent event)
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent event)
|
||||
{
|
||||
if (event instanceof ContextRefreshedEvent)
|
||||
{
|
||||
applyOutstandingPatches();
|
||||
}
|
||||
applyOutstandingPatches();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShutdown(ApplicationEvent event)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* 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.admin.patch.impl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.admin.patch.AbstractPatch;
|
||||
import org.alfresco.repo.domain.DbAccessControlEntry;
|
||||
import org.alfresco.repo.domain.DbPermission;
|
||||
import org.alfresco.repo.domain.hibernate.DbPermissionImpl;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.springframework.orm.hibernate3.HibernateCallback;
|
||||
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
|
||||
|
||||
/**
|
||||
* Provides common functionality to change a permission type and/or name.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public abstract class AbstractPermissionChangePatch extends AbstractPatch
|
||||
{
|
||||
private HibernateHelper helper;
|
||||
|
||||
public AbstractPermissionChangePatch()
|
||||
{
|
||||
helper = new HibernateHelper();
|
||||
}
|
||||
|
||||
public void setSessionFactory(SessionFactory sessionFactory)
|
||||
{
|
||||
this.helper.setSessionFactory(sessionFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to rename (move) a permission. This involves checking for the existence of the
|
||||
* new permission and then moving all the entries to point to the new permission.
|
||||
*
|
||||
* @param oldTypeQName the old permission type
|
||||
* @param oldName the old permission name
|
||||
* @param newTypeQName the new permission type
|
||||
* @param newName the new permission name
|
||||
* @return Returns the number of permission entries modified
|
||||
*/
|
||||
protected int renamePermission(QName oldTypeQName, String oldName, QName newTypeQName, String newName)
|
||||
{
|
||||
return helper.createAndUpdatePermission(oldTypeQName, oldName, newTypeQName, newName);
|
||||
}
|
||||
|
||||
/** Helper to get a permission entity */
|
||||
private static class GetPermissionCallback implements HibernateCallback
|
||||
{
|
||||
private QName typeQName;
|
||||
private String name;
|
||||
public GetPermissionCallback(QName typeQName, String name)
|
||||
{
|
||||
this.typeQName = typeQName;
|
||||
this.name = name;
|
||||
}
|
||||
public Object doInHibernate(Session session)
|
||||
{
|
||||
// flush any outstanding entities
|
||||
session.flush();
|
||||
|
||||
Query query = session.getNamedQuery(HibernateHelper.QUERY_GET_PERMISSION);
|
||||
query.setParameter("permissionTypeQName", typeQName)
|
||||
.setString("permissionName", name);
|
||||
return query.uniqueResult();
|
||||
}
|
||||
}
|
||||
|
||||
private static class HibernateHelper extends HibernateDaoSupport
|
||||
{
|
||||
private static final String QUERY_GET_PERMISSION = "permission.GetPermission";
|
||||
private static final String QUERY_GET_ENTRIES_TO_CHANGE = "permission.patch.GetAccessControlEntriesToChangePermissionOn";
|
||||
|
||||
public int createAndUpdatePermission(
|
||||
final QName oldTypeQName,
|
||||
final String oldName,
|
||||
final QName newTypeQName,
|
||||
final String newName)
|
||||
{
|
||||
if (oldTypeQName.equals(newTypeQName) && oldName.equals(newName))
|
||||
{
|
||||
throw new IllegalArgumentException("Cannot move permission to itself: " + oldTypeQName + "-" + oldName);
|
||||
}
|
||||
|
||||
HibernateCallback getNewPermissionCallback = new GetPermissionCallback(newTypeQName, newName);
|
||||
DbPermission permission = (DbPermission) getHibernateTemplate().execute(getNewPermissionCallback);
|
||||
if (permission == null)
|
||||
{
|
||||
// create the permission
|
||||
permission = new DbPermissionImpl();
|
||||
permission.setTypeQname(newTypeQName);
|
||||
permission.setName(newName);
|
||||
// save
|
||||
getHibernateTemplate().save(permission);
|
||||
}
|
||||
final DbPermission newPermission = permission;
|
||||
// now update all entries that refer to the old permission
|
||||
HibernateCallback updateEntriesCallback = new HibernateCallback()
|
||||
{
|
||||
private static final int MAX_RESULTS = 1000;
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object doInHibernate(Session session)
|
||||
{
|
||||
int count = 0;
|
||||
while (true)
|
||||
{
|
||||
// flush any outstanding entities
|
||||
session.flush();
|
||||
|
||||
Query query = session.getNamedQuery(HibernateHelper.QUERY_GET_ENTRIES_TO_CHANGE);
|
||||
query.setParameter("oldTypeQName", oldTypeQName)
|
||||
.setParameter("oldName", oldName)
|
||||
.setMaxResults(MAX_RESULTS);
|
||||
List<DbAccessControlEntry> entries = (List<DbAccessControlEntry>) query.list();
|
||||
// if there are no results, then we're done
|
||||
if (entries.size() == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
for (DbAccessControlEntry entry : entries)
|
||||
{
|
||||
entry.setPermission(newPermission);
|
||||
count++;
|
||||
session.evict(entry);
|
||||
}
|
||||
// flush and evict all the entries
|
||||
session.flush();
|
||||
for (DbAccessControlEntry entry : entries)
|
||||
{
|
||||
session.evict(entry);
|
||||
}
|
||||
// next set of results
|
||||
}
|
||||
// done
|
||||
return count;
|
||||
}
|
||||
};
|
||||
int updateCount = (Integer) getHibernateTemplate().execute(updateEntriesCallback);
|
||||
// now delete the old permission
|
||||
HibernateCallback getOldPermissionCallback = new GetPermissionCallback(oldTypeQName, oldName);
|
||||
DbPermission oldPermission = (DbPermission) getHibernateTemplate().execute(getOldPermissionCallback);
|
||||
if (oldPermission != null)
|
||||
{
|
||||
getHibernateTemplate().delete(oldPermission);
|
||||
}
|
||||
// done
|
||||
return updateCount;
|
||||
}
|
||||
}
|
||||
}
|
@@ -54,6 +54,10 @@ public class ActionRuleDecouplingPatch extends AbstractPatch
|
||||
for (NodeRef origRuleNodeRef : resultSet.getNodeRefs())
|
||||
{
|
||||
// Check that this rule need updated
|
||||
if (!this.nodeService.exists(origRuleNodeRef))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Map<QName, Serializable> origProperties = this.nodeService.getProperties(origRuleNodeRef);
|
||||
if (origProperties.containsKey(RuleModel.PROP_EXECUTE_ASYNC) == false)
|
||||
{
|
||||
@@ -79,21 +83,21 @@ public class ActionRuleDecouplingPatch extends AbstractPatch
|
||||
Map<QName, Serializable> newProperties = this.nodeService.getProperties(newRuleNodeRef);
|
||||
|
||||
// Set the rule type, execute async and applyToChildren properties on the rule
|
||||
String ruleType = (String)origProperties.get(RuleModel.PROP_RULE_TYPE);
|
||||
Serializable ruleType = origProperties.get(RuleModel.PROP_RULE_TYPE);
|
||||
origProperties.remove(RuleModel.PROP_RULE_TYPE);
|
||||
newProperties.put(RuleModel.PROP_RULE_TYPE, ruleType);
|
||||
Boolean executeAsync = (Boolean)origProperties.get(ActionModel.PROP_EXECUTE_ASYNCHRONOUSLY);
|
||||
Serializable executeAsync = origProperties.get(ActionModel.PROP_EXECUTE_ASYNCHRONOUSLY);
|
||||
origProperties.remove(ActionModel.PROP_EXECUTE_ASYNCHRONOUSLY);
|
||||
newProperties.put(RuleModel.PROP_EXECUTE_ASYNC, executeAsync);
|
||||
Boolean applyToChildren = (Boolean)origProperties.get(RuleModel.PROP_APPLY_TO_CHILDREN);
|
||||
Serializable applyToChildren = origProperties.get(RuleModel.PROP_APPLY_TO_CHILDREN);
|
||||
origProperties.remove(RuleModel.PROP_APPLY_TO_CHILDREN);
|
||||
newProperties.put(RuleModel.PROP_APPLY_TO_CHILDREN, applyToChildren);
|
||||
origProperties.remove(QName.createQName(RuleModel.RULE_MODEL_URI, "owningNodeRef"));
|
||||
|
||||
// Move the action and description values from the composite action onto the rule
|
||||
String title = (String)origProperties.get(ActionModel.PROP_ACTION_TITLE);
|
||||
Serializable title = origProperties.get(ActionModel.PROP_ACTION_TITLE);
|
||||
origProperties.remove(ActionModel.PROP_ACTION_TITLE);
|
||||
String description = (String)origProperties.get(ActionModel.PROP_ACTION_DESCRIPTION);
|
||||
Serializable description = origProperties.get(ActionModel.PROP_ACTION_DESCRIPTION);
|
||||
origProperties.remove(ActionModel.PROP_ACTION_DESCRIPTION);
|
||||
newProperties.put(ContentModel.PROP_TITLE, title);
|
||||
newProperties.put(ContentModel.PROP_DESCRIPTION, description);
|
||||
|
@@ -16,33 +16,40 @@
|
||||
*/
|
||||
package org.alfresco.repo.admin.patch.impl;
|
||||
|
||||
import org.alfresco.repo.admin.patch.AbstractPatch;
|
||||
import org.alfresco.service.cmr.admin.PatchException;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Roles defined in permissionsDefinition.xml moved from <b>cm:content</b> to <b>sys:base</b>.
|
||||
* This effects the data stored in the <b>node_perm_entry</b> table.
|
||||
* <p>
|
||||
* <b>WILL NOT EXECUTE ANYMORE</b>
|
||||
* This effects the data stored in the <b>permission</b> table.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class ContentPermissionPatch extends AbstractPatch
|
||||
public class ContentPermissionPatch extends AbstractPermissionChangePatch
|
||||
{
|
||||
private static final String MSG_UPGRADE = "patch.contentPermission.upgrade";
|
||||
private static final String MSG_SUCCESS = "patch.contentPermission.result";
|
||||
|
||||
public ContentPermissionPatch()
|
||||
{
|
||||
}
|
||||
|
||||
public void setSessionFactory(SessionFactory sessionFactory)
|
||||
{
|
||||
}
|
||||
private static final QName TYPE_QNAME_OLD = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "content");
|
||||
private static final QName TYPE_QNAME_NEW = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "base");
|
||||
private static final String[] NAMES = new String[] {"Execute", "ReadContent", "WriteContent", "ExecuteContent"};
|
||||
|
||||
@Override
|
||||
protected String applyInternal() throws Exception
|
||||
{
|
||||
throw new PatchException(MSG_UPGRADE);
|
||||
int updateCount = 0;
|
||||
for (String permissionName : NAMES)
|
||||
{
|
||||
updateCount += super.renamePermission(
|
||||
ContentPermissionPatch.TYPE_QNAME_OLD,
|
||||
permissionName,
|
||||
ContentPermissionPatch.TYPE_QNAME_NEW,
|
||||
permissionName);
|
||||
}
|
||||
|
||||
// build the result message
|
||||
String msg = I18NUtil.getMessage(MSG_SUCCESS, updateCount);
|
||||
// done
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
@@ -16,35 +16,42 @@
|
||||
*/
|
||||
package org.alfresco.repo.admin.patch.impl;
|
||||
|
||||
import org.alfresco.repo.admin.patch.AbstractPatch;
|
||||
import org.alfresco.service.cmr.admin.PatchException;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* The roles defined in permissionsDefinition.xml moved from <b>cm:folder</b> to <b>cm:cmobject</b>.
|
||||
* This effects the data stored in the <b>node_perm_entry</b> table.
|
||||
* This effects the data stored in the <b>permission</b> table.
|
||||
* <p>
|
||||
* JIRA: {@link http://www.alfresco.org/jira/browse/AR-344 AR-344}
|
||||
* <p>
|
||||
* <b>WILL NOT EXECUTE ANYMORE</b>
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class PermissionDataPatch extends AbstractPatch
|
||||
public class PermissionDataPatch extends AbstractPermissionChangePatch
|
||||
{
|
||||
private static final String MSG_UPGRADE = "patch.updatePermissionData.upgrade";
|
||||
private static final String MSG_SUCCESS = "patch.updatePermissionData.result";
|
||||
|
||||
public PermissionDataPatch()
|
||||
{
|
||||
}
|
||||
|
||||
public void setSessionFactory(SessionFactory sessionFactory)
|
||||
{
|
||||
}
|
||||
private static final QName TYPE_QNAME_OLD = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "folder");
|
||||
private static final QName TYPE_QNAME_NEW = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "cmobject");
|
||||
private static final String[] NAMES = new String[] {"Coordinator", "Contributor", "Editor", "Guest"};
|
||||
|
||||
@Override
|
||||
protected String applyInternal() throws Exception
|
||||
{
|
||||
throw new PatchException(MSG_UPGRADE);
|
||||
int updateCount = 0;
|
||||
for (String permissionName : NAMES)
|
||||
{
|
||||
updateCount += super.renamePermission(
|
||||
PermissionDataPatch.TYPE_QNAME_OLD,
|
||||
permissionName,
|
||||
PermissionDataPatch.TYPE_QNAME_NEW,
|
||||
permissionName);
|
||||
}
|
||||
|
||||
// build the result message
|
||||
String msg = I18NUtil.getMessage(MSG_SUCCESS, updateCount);
|
||||
// done
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@ import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@@ -30,6 +31,7 @@ import org.alfresco.repo.admin.patch.AbstractPatch;
|
||||
import org.alfresco.repo.domain.ChildAssoc;
|
||||
import org.alfresco.repo.domain.Node;
|
||||
import org.alfresco.repo.node.db.NodeDaoService;
|
||||
import org.alfresco.service.cmr.admin.PatchException;
|
||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
@@ -51,6 +53,7 @@ import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
|
||||
public class UniqueChildNamePatch extends AbstractPatch
|
||||
{
|
||||
private static final String MSG_SUCCESS = "patch.uniqueChildName.result";
|
||||
private static final String ERR_UNABLE_TO_FIX = "patch.uniqueChildName.err.unable_to_fix";
|
||||
private static final String MSG_COPY_OF = "patch.uniqueChildName.copyOf";
|
||||
/** the number of associations to process at a time */
|
||||
private static final int MAX_RESULTS = 1000;
|
||||
@@ -143,6 +146,7 @@ public class UniqueChildNamePatch extends AbstractPatch
|
||||
@SuppressWarnings("unused")
|
||||
List<QName> assocTypeQNames = getUsedAssocQNames();
|
||||
|
||||
boolean unableToFix = false;
|
||||
int fixed = 0;
|
||||
int processed = 0;
|
||||
// check loop through all associations, looking for duplicates
|
||||
@@ -185,8 +189,10 @@ public class UniqueChildNamePatch extends AbstractPatch
|
||||
String usedChildName = childName;
|
||||
processed++;
|
||||
boolean duplicate = false;
|
||||
int duplicateNumber = 0;
|
||||
while(true)
|
||||
{
|
||||
duplicateNumber++;
|
||||
try
|
||||
{
|
||||
// push the name back to the node
|
||||
@@ -195,11 +201,46 @@ public class UniqueChildNamePatch extends AbstractPatch
|
||||
}
|
||||
catch (DuplicateChildNodeNameException e)
|
||||
{
|
||||
// there was a duplicate, so adjust the name and change the node property
|
||||
duplicate = true;
|
||||
// assign a new name
|
||||
usedChildName = childName + I18NUtil.getMessage(MSG_COPY_OF, processed);
|
||||
// try again
|
||||
if (duplicateNumber == 10)
|
||||
{
|
||||
// Try removing the secondary parent associations
|
||||
writeLine(" Removing secondary parents of node " + childNode.getId());
|
||||
Collection<ChildAssoc> parentAssocs = childNode.getParentAssocs();
|
||||
for (ChildAssoc parentAssoc : parentAssocs)
|
||||
{
|
||||
if (!parentAssoc.getIsPrimary())
|
||||
{
|
||||
write(" - ").writeLine(parentAssoc);
|
||||
// remove it
|
||||
getSession().delete(parentAssoc);
|
||||
}
|
||||
}
|
||||
// flush to ensure the database gets the changes
|
||||
getSession().flush();
|
||||
// try again to be sure
|
||||
continue;
|
||||
}
|
||||
else if (duplicateNumber > 10)
|
||||
{
|
||||
// after 10 attempts, we have to admit defeat. Perhaps there is a larger issue.
|
||||
Collection<ChildAssoc> parentAssocs = childNode.getParentAssocs();
|
||||
write(" Unable to set child name '" + usedChildName + "' for node " + childNode.getId());
|
||||
writeLine(" with parent associations:");
|
||||
for (ChildAssoc parentAssoc : parentAssocs)
|
||||
{
|
||||
write(" - ").writeLine(parentAssoc);
|
||||
}
|
||||
duplicate = false;
|
||||
unableToFix = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// there was a duplicate, so adjust the name and change the node property
|
||||
duplicate = true;
|
||||
// assign a new name
|
||||
usedChildName = childName + I18NUtil.getMessage(MSG_COPY_OF, processed, duplicateNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
// if duplicated, report it
|
||||
@@ -209,11 +250,11 @@ public class UniqueChildNamePatch extends AbstractPatch
|
||||
// get the node path
|
||||
NodeRef parentNodeRef = childAssoc.getParent().getNodeRef();
|
||||
Path path = nodeService.getPath(parentNodeRef);
|
||||
writeLine(" Changed duplicated child name:");
|
||||
writeLine(" Parent: " + parentNodeRef);
|
||||
writeLine(" Parent path: " + path);
|
||||
writeLine(" Duplicate name: " + childName);
|
||||
writeLine(" Replaced with: " + usedChildName);
|
||||
writeLine(" Changed duplicated child name:");
|
||||
writeLine(" Parent: " + parentNodeRef);
|
||||
writeLine(" Parent path: " + path);
|
||||
writeLine(" Duplicate name: " + childName);
|
||||
writeLine(" Replaced with: " + usedChildName);
|
||||
}
|
||||
}
|
||||
// clear the session to preserve memory
|
||||
@@ -222,10 +263,17 @@ public class UniqueChildNamePatch extends AbstractPatch
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// build the result message
|
||||
String msg = I18NUtil.getMessage(MSG_SUCCESS, processed, fixed, logFile);
|
||||
return msg;
|
||||
// check if it was successful or not
|
||||
if (unableToFix)
|
||||
{
|
||||
throw new PatchException(ERR_UNABLE_TO_FIX, logFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
// build the result message
|
||||
String msg = I18NUtil.getMessage(MSG_SUCCESS, processed, fixed, logFile);
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@@ -16,32 +16,27 @@
|
||||
*/
|
||||
package org.alfresco.repo.admin.patch.impl;
|
||||
|
||||
import org.alfresco.repo.admin.patch.AbstractPatch;
|
||||
import org.alfresco.service.cmr.admin.PatchException;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.model.ContentModel;
|
||||
|
||||
/**
|
||||
* The permission 'Guest' has been renamed to 'Consumer'.
|
||||
* <p>
|
||||
* <b>WILL NOT EXECUTE ANYMORE</b>
|
||||
*
|
||||
* @author David Caruana
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class UpdateGuestPermissionPatch extends AbstractPatch
|
||||
public class UpdateGuestPermissionPatch extends AbstractPermissionChangePatch
|
||||
{
|
||||
private static final String MSG_UPGRADE = "patch.updateGuestPermission.upgrade";
|
||||
|
||||
public UpdateGuestPermissionPatch()
|
||||
{
|
||||
}
|
||||
|
||||
public void setSessionFactory(SessionFactory sessionFactory)
|
||||
{
|
||||
}
|
||||
private static final String MSG_SUCCESS = "patch.updateGuestPermission.result";
|
||||
|
||||
@Override
|
||||
protected String applyInternal() throws Exception
|
||||
{
|
||||
throw new PatchException(MSG_UPGRADE);
|
||||
int updateCount = super.renamePermission(ContentModel.TYPE_CMOBJECT, "Guest", ContentModel.TYPE_CMOBJECT, "Consumer");
|
||||
|
||||
// build the result message
|
||||
String msg = I18NUtil.getMessage(MSG_SUCCESS, updateCount);
|
||||
// done
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,573 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package org.alfresco.repo.admin.patch.util;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.action.ActionModel;
|
||||
import org.alfresco.repo.rule.RuleModel;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.dom4j.io.OutputFormat;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
import org.xml.sax.helpers.AttributesImpl;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlPullParserFactory;
|
||||
|
||||
/**
|
||||
* Updates a XML import file to be compatable with the current version of the repository.
|
||||
*
|
||||
* @author royw
|
||||
*/
|
||||
public class ImportFileUpdater
|
||||
{
|
||||
/** Indent size **/
|
||||
private static int INDENT_SIZE = 2;
|
||||
|
||||
/** The destination export version number **/
|
||||
private static String EXPORT_VERSION = "1.4.0";
|
||||
|
||||
/** Element names **/
|
||||
private static String NAME_EXPORTER_VERSION = "exporterVersion";
|
||||
private static String NAME_RULE = "rule";
|
||||
|
||||
/** The current import version number **/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* Updates the passed import file into the equivalent 1.4 format.
|
||||
*
|
||||
* @param source the source import file
|
||||
* @param destination the destination import file
|
||||
*/
|
||||
public void updateImportFile(String source, String destination)
|
||||
{
|
||||
XmlPullParser reader = getReader(source);
|
||||
XMLWriter writer = getWriter(destination);
|
||||
|
||||
try
|
||||
{
|
||||
// Start the documentation
|
||||
writer.startDocument();
|
||||
|
||||
// Start reading the document
|
||||
int eventType = reader.getEventType();
|
||||
while (eventType != XmlPullParser.END_DOCUMENT)
|
||||
{
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
ImportFileUpdater.this.outputCurrentElement(reader, writer, new OutputChildren());
|
||||
}
|
||||
eventType = reader.next();
|
||||
}
|
||||
|
||||
// End and close the document
|
||||
writer.endDocument();
|
||||
writer.close();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unable to update import file.", exception);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reader for the source import file
|
||||
*
|
||||
* @param source the source import file
|
||||
* @return the XML pull parser used to read the file
|
||||
*/
|
||||
private XmlPullParser getReader(String source)
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
|
||||
factory.setNamespaceAware(true);
|
||||
|
||||
XmlPullParser xpp = factory.newPullParser();
|
||||
xpp.setInput(new FileReader(source));
|
||||
|
||||
return xpp;
|
||||
}
|
||||
catch (XmlPullParserException exception)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unable to update import file.", exception);
|
||||
}
|
||||
catch (FileNotFoundException fileNotFound)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("The source file could not be loaded.", fileNotFound);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the writer for the import file
|
||||
*
|
||||
* @param destination the destination XML import file
|
||||
* @return the XML writer
|
||||
*/
|
||||
private XMLWriter getWriter(String destination)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Define output format
|
||||
OutputFormat format = OutputFormat.createPrettyPrint();
|
||||
format.setNewLineAfterDeclaration(false);
|
||||
format.setIndentSize(INDENT_SIZE);
|
||||
format.setEncoding("UTF-8");
|
||||
|
||||
return new XMLWriter(new FileOutputStream(destination), format);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unable to create XML writer.", exception);
|
||||
}
|
||||
}
|
||||
|
||||
private void outputCurrentElement(XmlPullParser reader, XMLWriter writer, Work work)
|
||||
throws Exception
|
||||
{
|
||||
outputCurrentElement(reader, writer, work, true);
|
||||
}
|
||||
|
||||
private void outputCurrentElement(XmlPullParser reader, XMLWriter writer, Work work, boolean checkForCallbacks)
|
||||
throws Exception
|
||||
{
|
||||
if (checkForCallbacks == false || checkForCallbacks(reader, writer) == false)
|
||||
{
|
||||
// Get the name details of the element
|
||||
String name = reader.getName();
|
||||
String namespace = reader.getNamespace();
|
||||
String prefix = reader.getPrefix();
|
||||
|
||||
// Sort out namespaces
|
||||
Map<String, String> nss = new HashMap<String, String>();
|
||||
int nsStart = reader.getNamespaceCount(reader.getDepth()-1);
|
||||
int nsEnd = reader.getNamespaceCount(reader.getDepth());
|
||||
for (int i = nsStart; i < nsEnd; i++)
|
||||
{
|
||||
String nsPrefix = reader.getNamespacePrefix(i);
|
||||
String ns = reader.getNamespaceUri(i);
|
||||
nss.put(nsPrefix, ns);
|
||||
}
|
||||
|
||||
// Sort out attributes
|
||||
AttributesImpl attributes = new AttributesImpl();
|
||||
for (int i = 0; i < reader.getAttributeCount(); i++)
|
||||
{
|
||||
String attributeName = reader.getAttributeName(i);
|
||||
String attributeNamespace = reader.getAttributeNamespace(i);
|
||||
String attributePrefix = reader.getAttributePrefix(i);
|
||||
String attributeType = reader.getAttributeType(i);
|
||||
String attributeValue = reader.getAttributeValue(i);
|
||||
|
||||
attributes.addAttribute(attributeNamespace, attributeName, attributePrefix+":"+attributeName, attributeType, attributeValue);
|
||||
}
|
||||
|
||||
// Start the namespace prefixes
|
||||
for (Map.Entry<String, String> entry : nss.entrySet())
|
||||
{
|
||||
writer.startPrefixMapping(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
// Write the start of the element
|
||||
writer.startElement(namespace, name, prefix+":"+name, attributes);
|
||||
|
||||
// Do the work
|
||||
work.doWork(reader, writer);
|
||||
|
||||
// Write the end of the element
|
||||
writer.endElement(namespace, name, prefix+":"+name);
|
||||
|
||||
// End the namespace prefixes
|
||||
for (String nsPrefix : nss.keySet())
|
||||
{
|
||||
writer.endPrefixMapping(nsPrefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkForCallbacks(XmlPullParser reader, XMLWriter writer)
|
||||
throws Exception
|
||||
{
|
||||
boolean result = false;
|
||||
if (reader.getName().equals(NAME_EXPORTER_VERSION) == true)
|
||||
{
|
||||
new ImportVersionLabelCallback().doCallback(reader, writer);
|
||||
result = true;
|
||||
}
|
||||
else if (reader.getName().equals(NAME_RULE) == true)
|
||||
{
|
||||
if (this.version.startsWith("1.3") == true)
|
||||
{
|
||||
new RuleCallback().doCallback(reader, writer);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private interface Work
|
||||
{
|
||||
void doWork(XmlPullParser reader, XMLWriter writer)
|
||||
throws Exception;
|
||||
}
|
||||
|
||||
private class OutputChildren implements Work
|
||||
{
|
||||
public void doWork(XmlPullParser reader, XMLWriter writer)
|
||||
throws Exception
|
||||
{
|
||||
// Deal with the contents of the tag
|
||||
int eventType = reader.getEventType();
|
||||
while (eventType != XmlPullParser.END_TAG)
|
||||
{
|
||||
eventType = reader.next();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
ImportFileUpdater.this.outputCurrentElement(reader, writer, new OutputChildren());
|
||||
}
|
||||
else if (eventType == XmlPullParser.TEXT)
|
||||
{
|
||||
// Write the text to the output file
|
||||
writer.write(reader.getText());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private class IgnoreChildren implements Work
|
||||
{
|
||||
public void doWork(XmlPullParser reader, XMLWriter writer)
|
||||
throws Exception
|
||||
{
|
||||
int eventType = reader.getEventType();
|
||||
while (eventType != XmlPullParser.END_TAG)
|
||||
{
|
||||
eventType = reader.next();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
doWork(reader, writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private interface ImportUpdaterCallback
|
||||
{
|
||||
void doCallback(XmlPullParser reader, XMLWriter writer)
|
||||
throws Exception;
|
||||
}
|
||||
|
||||
private class ImportVersionLabelCallback implements ImportUpdaterCallback
|
||||
{
|
||||
public void doCallback(XmlPullParser reader, XMLWriter writer)
|
||||
throws Exception
|
||||
{
|
||||
ImportFileUpdater.this.outputCurrentElement(reader, writer,
|
||||
new Work()
|
||||
{
|
||||
public void doWork(XmlPullParser reader, XMLWriter writer) throws Exception
|
||||
{
|
||||
reader.next();
|
||||
ImportFileUpdater.this.version = reader.getText();
|
||||
writer.write(EXPORT_VERSION);
|
||||
reader.next();
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
private class RuleCallback implements ImportUpdaterCallback
|
||||
{
|
||||
public void doCallback(XmlPullParser reader, XMLWriter writer)
|
||||
throws Exception
|
||||
{
|
||||
// Get the name details of the element
|
||||
String name = reader.getName();
|
||||
String namespace = reader.getNamespace();
|
||||
String prefix = reader.getPrefix();
|
||||
|
||||
// Rename the child assoc appropriately
|
||||
AttributesImpl attributes = new AttributesImpl();
|
||||
String attributeName = reader.getAttributeName(0);
|
||||
String attributeNamespace = reader.getAttributeNamespace(0);
|
||||
String attributePrefix = reader.getAttributePrefix(0);
|
||||
String attributeType = reader.getAttributeType(0);
|
||||
String attributeValue = reader.getAttributeValue(0) + GUID.generate();
|
||||
attributes.addAttribute(attributeNamespace, attributeName, attributePrefix+":"+attributeName, attributeType, attributeValue);
|
||||
|
||||
// Output the rules element
|
||||
writer.startElement(namespace, name, prefix+":"+name, attributes);
|
||||
|
||||
int eventType = reader.getEventType();
|
||||
while (eventType != XmlPullParser.END_TAG)
|
||||
{
|
||||
eventType = reader.next();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String childName = reader.getName();
|
||||
if (childName.equals("aspects") == true)
|
||||
{
|
||||
ImportFileUpdater.this.outputCurrentElement(reader, writer,
|
||||
new Work()
|
||||
{
|
||||
public void doWork(XmlPullParser reader, XMLWriter writer) throws Exception
|
||||
{
|
||||
// Add titled aspect
|
||||
writer.startElement(
|
||||
ContentModel.ASPECT_TITLED.getNamespaceURI(),
|
||||
ContentModel.ASPECT_TITLED.getLocalName(),
|
||||
NamespaceService.CONTENT_MODEL_PREFIX + ":" + ContentModel.ASPECT_TITLED.getLocalName(),
|
||||
new AttributesImpl());
|
||||
writer.endElement(
|
||||
ContentModel.ASPECT_TITLED.getNamespaceURI(),
|
||||
ContentModel.ASPECT_TITLED.getLocalName(),
|
||||
NamespaceService.CONTENT_MODEL_PREFIX + ":" + ContentModel.ASPECT_TITLED.getLocalName());
|
||||
|
||||
// Read the rest of the elements and output
|
||||
int eventType = reader.getEventType();
|
||||
while (eventType != XmlPullParser.END_TAG)
|
||||
{
|
||||
eventType = reader.next();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
ImportFileUpdater.this.outputCurrentElement(reader, writer, new OutputChildren());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}, false);
|
||||
}
|
||||
else if (childName.equals("properties") == true)
|
||||
{
|
||||
ImportFileUpdater.this.outputCurrentElement(reader, writer,
|
||||
new Work()
|
||||
{
|
||||
public void doWork(XmlPullParser reader, XMLWriter writer) throws Exception
|
||||
{
|
||||
int eventType = reader.getEventType();
|
||||
while (eventType != XmlPullParser.END_TAG)
|
||||
{
|
||||
eventType = reader.next();
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
String propName = reader.getName();
|
||||
if (propName.equals("actionDescription") == true)
|
||||
{
|
||||
writer.startElement(
|
||||
ContentModel.PROP_DESCRIPTION.getNamespaceURI(),
|
||||
ContentModel.PROP_DESCRIPTION.getLocalName(),
|
||||
NamespaceService.CONTENT_MODEL_PREFIX + ":" + ContentModel.PROP_DESCRIPTION.getLocalName(),
|
||||
new AttributesImpl());
|
||||
|
||||
// Output the value within
|
||||
new OutputChildren().doWork(reader, writer);
|
||||
|
||||
writer.endElement(
|
||||
ContentModel.PROP_DESCRIPTION.getNamespaceURI(),
|
||||
ContentModel.PROP_DESCRIPTION.getLocalName(),
|
||||
NamespaceService.CONTENT_MODEL_PREFIX + ":" + ContentModel.PROP_DESCRIPTION.getLocalName());
|
||||
eventType = reader.next();
|
||||
|
||||
}
|
||||
else if (propName.equals("actionTitle") == true)
|
||||
{
|
||||
writer.startElement(
|
||||
ContentModel.PROP_TITLE.getNamespaceURI(),
|
||||
ContentModel.PROP_TITLE.getLocalName(),
|
||||
NamespaceService.CONTENT_MODEL_PREFIX + ":" + ContentModel.PROP_TITLE.getLocalName(),
|
||||
new AttributesImpl());
|
||||
|
||||
// Output the value within
|
||||
new OutputChildren().doWork(reader, writer);
|
||||
|
||||
writer.endElement(
|
||||
ContentModel.PROP_TITLE.getNamespaceURI(),
|
||||
ContentModel.PROP_TITLE.getLocalName(),
|
||||
NamespaceService.CONTENT_MODEL_PREFIX + ":" + ContentModel.PROP_TITLE.getLocalName());
|
||||
eventType = reader.next();
|
||||
}
|
||||
else if (propName.equals("executeAsynchronously") == true)
|
||||
{
|
||||
writer.startElement(
|
||||
RuleModel.PROP_EXECUTE_ASYNC.getNamespaceURI(),
|
||||
RuleModel.PROP_EXECUTE_ASYNC.getLocalName(),
|
||||
RuleModel.RULE_MODEL_PREFIX + ":" + RuleModel.PROP_EXECUTE_ASYNC.getLocalName(),
|
||||
new AttributesImpl());
|
||||
|
||||
// Output the value within
|
||||
new OutputChildren().doWork(reader, writer);
|
||||
|
||||
writer.endElement(
|
||||
RuleModel.PROP_EXECUTE_ASYNC.getNamespaceURI(),
|
||||
RuleModel.PROP_EXECUTE_ASYNC.getLocalName(),
|
||||
RuleModel.RULE_MODEL_PREFIX + ":" + RuleModel.PROP_EXECUTE_ASYNC.getLocalName());
|
||||
eventType = reader.next();
|
||||
}
|
||||
else if (propName.equals("ruleType") == true)
|
||||
{
|
||||
ImportFileUpdater.this.outputCurrentElement(reader, writer,
|
||||
new Work()
|
||||
{
|
||||
public void doWork(XmlPullParser reader, XMLWriter writer) throws Exception
|
||||
{
|
||||
// Output the elements that contain a multi values property
|
||||
writer.startElement(NamespaceService.REPOSITORY_VIEW_1_0_URI, "values", "view:values", new AttributesImpl());
|
||||
writer.startElement(NamespaceService.REPOSITORY_VIEW_1_0_URI, "value", "view:value", new AttributesImpl());
|
||||
|
||||
// Output the value within
|
||||
new OutputChildren().doWork(reader, writer);
|
||||
|
||||
// End the multi values elements
|
||||
writer.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX, "value", "view:value");
|
||||
writer.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX, "values", "view:values");
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
else if (propName.equals("definitionName") == true)
|
||||
{
|
||||
// Skip past next end
|
||||
while (eventType != XmlPullParser.END_TAG)
|
||||
{
|
||||
eventType = reader.next();
|
||||
}
|
||||
eventType = reader.next();
|
||||
}
|
||||
else
|
||||
{
|
||||
ImportFileUpdater.this.outputCurrentElement(reader, writer, new OutputChildren());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Output value for the disabled property
|
||||
writer.startElement(
|
||||
RuleModel.PROP_DISABLED.getNamespaceURI(),
|
||||
RuleModel.PROP_DISABLED.getLocalName(),
|
||||
RuleModel.RULE_MODEL_PREFIX + ":" + RuleModel.PROP_DISABLED.getLocalName(),
|
||||
new AttributesImpl());
|
||||
writer.write("false");
|
||||
writer.endElement(
|
||||
RuleModel.PROP_DISABLED.getNamespaceURI(),
|
||||
RuleModel.PROP_DISABLED.getLocalName(),
|
||||
RuleModel.RULE_MODEL_PREFIX + ":" + RuleModel.PROP_DISABLED.getLocalName());
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
else if (childName.equals("associations") == true)
|
||||
{
|
||||
ImportFileUpdater.this.outputCurrentElement(reader, writer,
|
||||
new Work()
|
||||
{
|
||||
public void doWork(XmlPullParser reader, XMLWriter writer) throws Exception
|
||||
{
|
||||
// <rule:action>
|
||||
writer.startElement(
|
||||
RuleModel.ASSOC_ACTION.getNamespaceURI(),
|
||||
RuleModel.ASSOC_ACTION.getLocalName(),
|
||||
RuleModel.RULE_MODEL_PREFIX + ":" + RuleModel.ASSOC_ACTION.getLocalName(),
|
||||
new AttributesImpl());
|
||||
|
||||
// <act:compositeaction view:childName="rule:action">
|
||||
AttributesImpl attributes = new AttributesImpl();
|
||||
attributes.addAttribute(NamespaceService.REPOSITORY_VIEW_1_0_URI, "childName", "view:childName", null, "rule:action");
|
||||
writer.startElement(
|
||||
ActionModel.TYPE_COMPOSITE_ACTION.getNamespaceURI(),
|
||||
ActionModel.TYPE_COMPOSITE_ACTION.getLocalName(),
|
||||
ActionModel.ACTION_MODEL_PREFIX+ ":" + ActionModel.TYPE_COMPOSITE_ACTION.getLocalName(),
|
||||
attributes);
|
||||
|
||||
// <view:properties>
|
||||
writer.startElement(
|
||||
NamespaceService.REPOSITORY_VIEW_1_0_URI,
|
||||
"properties",
|
||||
"view:properties",
|
||||
new AttributesImpl());
|
||||
|
||||
// <act:definitionName>composite-action</definitionName>
|
||||
writer.startElement(
|
||||
ActionModel.PROP_DEFINITION_NAME.getNamespaceURI(),
|
||||
ActionModel.PROP_DEFINITION_NAME.getLocalName(),
|
||||
ActionModel.ACTION_MODEL_PREFIX + ":" + ActionModel.PROP_DEFINITION_NAME.getLocalName(),
|
||||
new AttributesImpl());
|
||||
writer.write("composite-action");
|
||||
writer.endElement(
|
||||
ActionModel.PROP_DEFINITION_NAME.getNamespaceURI(),
|
||||
ActionModel.PROP_DEFINITION_NAME.getLocalName(),
|
||||
ActionModel.ACTION_MODEL_PREFIX + ":" + ActionModel.PROP_DEFINITION_NAME.getLocalName());
|
||||
|
||||
// </view:properties>
|
||||
writer.endElement(
|
||||
NamespaceService.REPOSITORY_VIEW_1_0_URI,
|
||||
"properties",
|
||||
"view:properties");
|
||||
|
||||
// <view:association>
|
||||
writer.startElement(
|
||||
NamespaceService.REPOSITORY_VIEW_1_0_URI,
|
||||
"associations",
|
||||
"view:associations",
|
||||
new AttributesImpl());
|
||||
|
||||
// Output the association details
|
||||
new OutputChildren().doWork(reader, writer);
|
||||
|
||||
// </view:association>
|
||||
writer.endElement(
|
||||
NamespaceService.REPOSITORY_VIEW_1_0_URI,
|
||||
"associations",
|
||||
"view:associations");
|
||||
|
||||
// </act:compositeaction>
|
||||
writer.endElement(
|
||||
ActionModel.TYPE_COMPOSITE_ACTION.getNamespaceURI(),
|
||||
ActionModel.TYPE_COMPOSITE_ACTION.getLocalName(),
|
||||
ActionModel.ACTION_MODEL_PREFIX+ ":" + ActionModel.TYPE_COMPOSITE_ACTION.getLocalName());
|
||||
|
||||
// </rule:action>
|
||||
writer.endElement(
|
||||
RuleModel.ASSOC_ACTION.getNamespaceURI(),
|
||||
RuleModel.ASSOC_ACTION.getLocalName(),
|
||||
RuleModel.RULE_MODEL_PREFIX + ":" + RuleModel.ASSOC_ACTION.getLocalName());
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Output anything else that might be hanging araound
|
||||
ImportFileUpdater.this.outputCurrentElement(reader, writer, new OutputChildren());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// End the rules element
|
||||
writer.endElement(namespace, name, prefix+":"+name);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
if (args.length == 2)
|
||||
{
|
||||
ImportFileUpdater util = new ImportFileUpdater();
|
||||
util.updateImportFile(args[0], args[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println(" ImportFileUpdater <destination> <source>");
|
||||
System.out.println(" source - 1.3 import file name to be updated");
|
||||
System.out.println(" destination - name of the generated 1.4 import file");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -25,6 +25,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.policy.ClassPolicyDelegate;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
@@ -43,6 +44,7 @@ import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.CopyService;
|
||||
import org.alfresco.service.cmr.repository.CopyServiceException;
|
||||
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
@@ -65,8 +67,12 @@ import org.alfresco.util.ParameterCheck;
|
||||
*/
|
||||
public class CopyServiceImpl implements CopyService
|
||||
{
|
||||
/** I18N labels */
|
||||
private String COPY_OF_LABEL = "copy_service.copy_of_label";
|
||||
|
||||
/** The node service */
|
||||
private NodeService nodeService;
|
||||
private NodeService internalNodeService;
|
||||
|
||||
/** The dictionary service*/
|
||||
private DictionaryService dictionaryService;
|
||||
@@ -100,6 +106,16 @@ public class CopyServiceImpl implements CopyService
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the internal node service
|
||||
*
|
||||
* @param internalNodeService the internal node service
|
||||
*/
|
||||
public void setInternalNodeService(NodeService internalNodeService)
|
||||
{
|
||||
this.internalNodeService = internalNodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the dictionary service
|
||||
*
|
||||
@@ -234,6 +250,31 @@ public class CopyServiceImpl implements CopyService
|
||||
return copy;
|
||||
}
|
||||
|
||||
public NodeRef copyAndRename(NodeRef sourceNodeRef, NodeRef destinationParent, QName destinationAssocTypeQName, QName destinationQName, boolean copyChildren)
|
||||
{
|
||||
// Make a note of the source name and do the copy
|
||||
String sourceName = (String)this.internalNodeService.getProperty(sourceNodeRef, ContentModel.PROP_NAME);
|
||||
NodeRef copy = copy(sourceNodeRef, destinationParent, destinationAssocTypeQName, destinationQName, copyChildren);
|
||||
|
||||
// Do the rename, iterating until a non-duplicate name is found
|
||||
boolean bDone = false;
|
||||
while (bDone == false)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.internalNodeService.setProperty(copy, ContentModel.PROP_NAME, sourceName);
|
||||
bDone = true;
|
||||
}
|
||||
catch(DuplicateChildNodeNameException exception)
|
||||
{
|
||||
sourceName = I18NUtil.getMessage(COPY_OF_LABEL, sourceName);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the copy
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the copy complete policy for the node reference provided
|
||||
*
|
||||
|
@@ -104,6 +104,7 @@ public class CopyServiceImplTest extends BaseSpringTest
|
||||
private static final QName TEST_MANDATORY_ASPECT_QNAME = QName.createQName(TEST_TYPE_NAMESPACE, "testMandatoryAspect");
|
||||
private static final QName PROP5_QNAME_MANDATORY = QName.createQName(TEST_TYPE_NAMESPACE, "prop5Mandatory");
|
||||
|
||||
private static final String TEST_NAME = "testName";
|
||||
private static final String TEST_VALUE_1 = "testValue1";
|
||||
private static final String TEST_VALUE_2 = "testValue2";
|
||||
private static final String TEST_VALUE_3 = "testValue3";
|
||||
@@ -239,6 +240,7 @@ public class CopyServiceImplTest extends BaseSpringTest
|
||||
private Map<QName, Serializable> createTypePropertyBag()
|
||||
{
|
||||
Map<QName, Serializable> result = new HashMap<QName, Serializable>();
|
||||
result.put(ContentModel.PROP_NAME, TEST_NAME);
|
||||
result.put(PROP1_QNAME_MANDATORY, TEST_VALUE_1);
|
||||
result.put(PROP2_QNAME_OPTIONAL, TEST_VALUE_2);
|
||||
result.put(PROP5_QNAME_MANDATORY, TEST_VALUE_3);
|
||||
@@ -625,6 +627,31 @@ public class CopyServiceImplTest extends BaseSpringTest
|
||||
assertEquals(nodeTwoCopy, value);
|
||||
}
|
||||
|
||||
public void testCopyAndRename()
|
||||
{
|
||||
// Check a normal copy with no dup restrictions
|
||||
NodeRef copy = this.copyService.copyAndRename(
|
||||
this.sourceNodeRef,
|
||||
this.rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}copyAssoc"),
|
||||
false);
|
||||
checkCopiedNode(this.sourceNodeRef, copy, true, true, false);
|
||||
assertTrue(TEST_NAME.equals(this.nodeService.getProperty(copy, ContentModel.PROP_NAME)));
|
||||
|
||||
// Create a folder and content node
|
||||
Map<QName, Serializable> propsFolder = new HashMap<QName, Serializable>(1);
|
||||
propsFolder.put(ContentModel.PROP_NAME, "tempFolder");
|
||||
NodeRef folderNode = this.nodeService.createNode(this.rootNodeRef, ContentModel.ASSOC_CHILDREN, QName.createQName("{test}tempFolder"), ContentModel.TYPE_FOLDER, propsFolder).getChildRef();
|
||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>(1);
|
||||
props.put(ContentModel.PROP_NAME, TEST_NAME);
|
||||
NodeRef contentNode = this.nodeService.createNode(folderNode, ContentModel.ASSOC_CONTAINS, QName.createQName("{test}renametest"), ContentModel.TYPE_CONTENT, props).getChildRef();
|
||||
|
||||
// Now copy the content node with the duplicate name restriction
|
||||
NodeRef contentCopy = this.copyService.copy(contentNode, folderNode, ContentModel.ASSOC_CONTAINS, QName.createQName("{test}bobbins"), false);
|
||||
assertFalse(TEST_NAME.equals(this.nodeService.getProperty(contentCopy, ContentModel.PROP_NAME)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the copied node contains the state we are expecting
|
||||
*
|
||||
|
@@ -41,16 +41,12 @@ import org.alfresco.service.license.LicenseService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.AbstractLifecycleBean;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
|
||||
@@ -59,12 +55,10 @@ import org.springframework.core.io.Resource;
|
||||
*
|
||||
* @author David Caruana
|
||||
*/
|
||||
public class DescriptorServiceImpl implements DescriptorService, ApplicationListener, InitializingBean, ApplicationContextAware, DisposableBean
|
||||
public class DescriptorServiceImpl extends AbstractLifecycleBean implements DescriptorService, InitializingBean
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(DescriptorServiceImpl.class);
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private Properties serverProperties;
|
||||
|
||||
private ImporterBootstrap systemBootstrap;
|
||||
@@ -78,14 +72,6 @@ public class DescriptorServiceImpl implements DescriptorService, ApplicationList
|
||||
private Descriptor installedRepoDescriptor;
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
*/
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
||||
{
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the server descriptor from a resource file
|
||||
*
|
||||
@@ -163,34 +149,34 @@ public class DescriptorServiceImpl implements DescriptorService, ApplicationList
|
||||
return (licenseService == null) ? null : licenseService.getLicense();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param event
|
||||
*/
|
||||
public void onApplicationEvent(ApplicationEvent event)
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent event)
|
||||
{
|
||||
if (event instanceof ContextRefreshedEvent)
|
||||
// initialise the repository descriptor
|
||||
// note: this requires that the repository schema has already been initialised
|
||||
TransactionWork<Descriptor> createDescriptorWork = new TransactionUtil.TransactionWork<Descriptor>()
|
||||
{
|
||||
// initialise the repository descriptor
|
||||
// note: this requires that the repository schema has already been initialised
|
||||
TransactionWork<Descriptor> createDescriptorWork = new TransactionUtil.TransactionWork<Descriptor>()
|
||||
public Descriptor doWork()
|
||||
{
|
||||
public Descriptor doWork()
|
||||
{
|
||||
// initialise license service (if installed)
|
||||
initialiseLicenseService();
|
||||
// initialise license service (if installed)
|
||||
initialiseLicenseService();
|
||||
|
||||
// verify license, but only if license component is installed
|
||||
licenseService.verifyLicense();
|
||||
// verify license, but only if license component is installed
|
||||
licenseService.verifyLicense();
|
||||
|
||||
// persist the server descriptor values
|
||||
updateCurrentRepositoryDescriptor(serverDescriptor);
|
||||
// persist the server descriptor values
|
||||
updateCurrentRepositoryDescriptor(serverDescriptor);
|
||||
|
||||
// return the repository installed descriptor
|
||||
return createInstalledRepositoryDescriptor();
|
||||
}
|
||||
};
|
||||
installedRepoDescriptor = TransactionUtil.executeInUserTransaction(transactionService, createDescriptorWork);
|
||||
}
|
||||
// return the repository installed descriptor
|
||||
return createInstalledRepositoryDescriptor();
|
||||
}
|
||||
};
|
||||
installedRepoDescriptor = TransactionUtil.executeInUserTransaction(transactionService, createDescriptorWork);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShutdown(ApplicationEvent event)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,13 +188,6 @@ public class DescriptorServiceImpl implements DescriptorService, ApplicationList
|
||||
serverDescriptor = createServerDescriptor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destruction hook
|
||||
*/
|
||||
public void destroy() throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create server descriptor
|
||||
*
|
||||
@@ -358,7 +337,7 @@ public class DescriptorServiceImpl implements DescriptorService, ApplicationList
|
||||
// be declaratively taken out in an installed environment.
|
||||
Class licenseComponentClass = Class.forName("org.alfresco.license.LicenseComponent");
|
||||
Constructor constructor = licenseComponentClass.getConstructor(new Class[] { ApplicationContext.class} );
|
||||
licenseService = (LicenseService)constructor.newInstance(new Object[] { applicationContext });
|
||||
licenseService = (LicenseService)constructor.newInstance(new Object[] { getApplicationContext() });
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
@@ -766,4 +745,5 @@ public class DescriptorServiceImpl implements DescriptorService, ApplicationList
|
||||
return serverProperties.getProperty(key, "");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -23,11 +23,10 @@ import java.util.Map;
|
||||
import org.alfresco.service.descriptor.Descriptor;
|
||||
import org.alfresco.service.descriptor.DescriptorService;
|
||||
import org.alfresco.service.license.LicenseDescriptor;
|
||||
import org.alfresco.util.AbstractLifecycleBean;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
|
||||
|
||||
/**
|
||||
@@ -35,7 +34,7 @@ import org.springframework.context.event.ContextRefreshedEvent;
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class DescriptorStartupLog implements ApplicationListener
|
||||
public class DescriptorStartupLog extends AbstractLifecycleBean
|
||||
{
|
||||
// Logger
|
||||
private static final Log logger = LogFactory.getLog(DescriptorService.class);
|
||||
@@ -52,82 +51,6 @@ public class DescriptorStartupLog implements ApplicationListener
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param event
|
||||
*/
|
||||
public void onApplicationEvent(ApplicationEvent event)
|
||||
{
|
||||
if (event instanceof ContextRefreshedEvent)
|
||||
{
|
||||
//
|
||||
// log output of VM stats
|
||||
//
|
||||
Map properties = System.getProperties();
|
||||
String version = (properties.get("java.runtime.version") == null) ? "unknown" : (String)properties.get("java.runtime.version");
|
||||
long maxHeap = Runtime.getRuntime().maxMemory();
|
||||
float maxHeapMB = maxHeap / 1024l;
|
||||
maxHeapMB = maxHeapMB / 1024l;
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.info(String.format("Alfresco JVM - v%s; maximum heap size %.3fMB", version, maxHeapMB));
|
||||
}
|
||||
if (logger.isWarnEnabled())
|
||||
{
|
||||
if (version.startsWith("1.2") || version.startsWith("1.3") || version.startsWith("1.4"))
|
||||
{
|
||||
logger.warn(String.format("Alfresco JVM - WARNING - v1.5 is required; currently using v%s", version));
|
||||
}
|
||||
if (maxHeapMB < 500)
|
||||
{
|
||||
logger.warn(String.format("Alfresco JVM - WARNING - maximum heap size %.3fMB is less than recommended 512MB", maxHeapMB));
|
||||
}
|
||||
}
|
||||
|
||||
// Log License Descriptors (if applicable)
|
||||
LicenseDescriptor license = descriptorService.getLicenseDescriptor();
|
||||
if (license != null && logger.isInfoEnabled())
|
||||
{
|
||||
String subject = license.getSubject();
|
||||
String msg = "Alfresco license: " + subject;
|
||||
String holder = getHolderOrganisation(license.getHolder());
|
||||
if (holder != null)
|
||||
{
|
||||
msg += " granted to " + holder;
|
||||
}
|
||||
Date validUntil = license.getValidUntil();
|
||||
if (validUntil != null)
|
||||
{
|
||||
Integer days = license.getDays();
|
||||
Integer remainingDays = license.getRemainingDays();
|
||||
|
||||
msg += " limited to " + days + " days expiring " + validUntil + " (" + remainingDays + " days remaining)";
|
||||
}
|
||||
else
|
||||
{
|
||||
msg += " (does not expire)";
|
||||
}
|
||||
|
||||
|
||||
logger.info(msg);
|
||||
}
|
||||
|
||||
// Log Repository Descriptors
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
Descriptor serverDescriptor = descriptorService.getServerDescriptor();
|
||||
Descriptor installedRepoDescriptor = descriptorService.getInstalledRepositoryDescriptor();
|
||||
String serverEdition = serverDescriptor.getEdition();
|
||||
String serverVersion = serverDescriptor.getVersion();
|
||||
int serverSchemaVersion = serverDescriptor.getSchema();
|
||||
String installedRepoVersion = installedRepoDescriptor.getVersion();
|
||||
int installedSchemaVersion = installedRepoDescriptor.getSchema();
|
||||
logger.info(String.format("Alfresco started (%s): Current version %s schema %d - Installed version %s schema %d",
|
||||
serverEdition, serverVersion, serverSchemaVersion, installedRepoVersion, installedSchemaVersion));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get Organisation from Principal
|
||||
*
|
||||
@@ -157,4 +80,82 @@ public class DescriptorStartupLog implements ApplicationListener
|
||||
return holder;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent event)
|
||||
{
|
||||
//
|
||||
// log output of VM stats
|
||||
//
|
||||
Map properties = System.getProperties();
|
||||
String version = (properties.get("java.runtime.version") == null) ? "unknown" : (String)properties.get("java.runtime.version");
|
||||
long maxHeap = Runtime.getRuntime().maxMemory();
|
||||
float maxHeapMB = maxHeap / 1024l;
|
||||
maxHeapMB = maxHeapMB / 1024l;
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
logger.info(String.format("Alfresco JVM - v%s; maximum heap size %.3fMB", version, maxHeapMB));
|
||||
}
|
||||
if (logger.isWarnEnabled())
|
||||
{
|
||||
if (version.startsWith("1.2") || version.startsWith("1.3") || version.startsWith("1.4"))
|
||||
{
|
||||
logger.warn(String.format("Alfresco JVM - WARNING - v1.5 is required; currently using v%s", version));
|
||||
}
|
||||
if (maxHeapMB < 500)
|
||||
{
|
||||
logger.warn(String.format("Alfresco JVM - WARNING - maximum heap size %.3fMB is less than recommended 512MB", maxHeapMB));
|
||||
}
|
||||
}
|
||||
|
||||
// Log License Descriptors (if applicable)
|
||||
LicenseDescriptor license = descriptorService.getLicenseDescriptor();
|
||||
if (license != null && logger.isInfoEnabled())
|
||||
{
|
||||
String subject = license.getSubject();
|
||||
String msg = "Alfresco license: " + subject;
|
||||
String holder = getHolderOrganisation(license.getHolder());
|
||||
if (holder != null)
|
||||
{
|
||||
msg += " granted to " + holder;
|
||||
}
|
||||
Date validUntil = license.getValidUntil();
|
||||
if (validUntil != null)
|
||||
{
|
||||
Integer days = license.getDays();
|
||||
Integer remainingDays = license.getRemainingDays();
|
||||
|
||||
msg += " limited to " + days + " days expiring " + validUntil + " (" + remainingDays + " days remaining)";
|
||||
}
|
||||
else
|
||||
{
|
||||
msg += " (does not expire)";
|
||||
}
|
||||
|
||||
|
||||
logger.info(msg);
|
||||
}
|
||||
|
||||
// Log Repository Descriptors
|
||||
if (logger.isInfoEnabled())
|
||||
{
|
||||
Descriptor serverDescriptor = descriptorService.getServerDescriptor();
|
||||
Descriptor installedRepoDescriptor = descriptorService.getInstalledRepositoryDescriptor();
|
||||
String serverEdition = serverDescriptor.getEdition();
|
||||
String serverVersion = serverDescriptor.getVersion();
|
||||
int serverSchemaVersion = serverDescriptor.getSchema();
|
||||
String installedRepoVersion = installedRepoDescriptor.getVersion();
|
||||
int installedSchemaVersion = installedRepoDescriptor.getSchema();
|
||||
logger.info(String.format("Alfresco started (%s): Current version %s schema %d - Installed version %s schema %d",
|
||||
serverEdition, serverVersion, serverSchemaVersion, installedRepoVersion, installedSchemaVersion));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onShutdown(ApplicationEvent event)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
}
|
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package org.alfresco.repo.dictionary;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -275,4 +276,25 @@ public class DictionaryDAOTest extends TestCase
|
||||
}
|
||||
|
||||
|
||||
public void testPropertyOverride()
|
||||
{
|
||||
TypeDefinition type1 = service.getType(QName.createQName(TEST_URL, "overridetype1"));
|
||||
Map<QName, PropertyDefinition> props1 = type1.getProperties();
|
||||
PropertyDefinition prop1 = props1.get(QName.createQName(TEST_URL, "propoverride"));
|
||||
String def1 = prop1.getDefaultValue();
|
||||
assertEquals("one", def1);
|
||||
|
||||
TypeDefinition type2 = service.getType(QName.createQName(TEST_URL, "overridetype2"));
|
||||
Map<QName, PropertyDefinition> props2 = type2.getProperties();
|
||||
PropertyDefinition prop2 = props2.get(QName.createQName(TEST_URL, "propoverride"));
|
||||
String def2 = prop2.getDefaultValue();
|
||||
assertEquals("two", def2);
|
||||
|
||||
TypeDefinition type3 = service.getType(QName.createQName(TEST_URL, "overridetype3"));
|
||||
Map<QName, PropertyDefinition> props3 = type3.getProperties();
|
||||
PropertyDefinition prop3 = props3.get(QName.createQName(TEST_URL, "propoverride"));
|
||||
String def3 = prop3.getDefaultValue();
|
||||
assertEquals("three", def3);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -43,6 +43,8 @@ public class TestModel
|
||||
bootstrapModels.add("alfresco/model/systemModel.xml");
|
||||
bootstrapModels.add("alfresco/model/contentModel.xml");
|
||||
bootstrapModels.add("alfresco/model/applicationModel.xml");
|
||||
bootstrapModels.add("alfresco/model/bpmModel.xml");
|
||||
bootstrapModels.add("alfresco/workflow/workflowModel.xml");
|
||||
|
||||
// include models specified on command line
|
||||
for (String arg: args)
|
||||
|
@@ -188,6 +188,33 @@
|
||||
</properties>
|
||||
</type>
|
||||
|
||||
<type name="test:overridetype1">
|
||||
<properties>
|
||||
<property name="test:propoverride">
|
||||
<type>d:text</type>
|
||||
<default>one</default>
|
||||
</property>
|
||||
</properties>
|
||||
</type>
|
||||
|
||||
<type name="test:overridetype2">
|
||||
<parent>test:overridetype1</parent>
|
||||
<overrides>
|
||||
<property name="test:propoverride">
|
||||
<default>two</default>
|
||||
</property>
|
||||
</overrides>
|
||||
</type>
|
||||
|
||||
<type name="test:overridetype3">
|
||||
<parent>test:overridetype2</parent>
|
||||
<overrides>
|
||||
<property name="test:propoverride">
|
||||
<default>three</default>
|
||||
</property>
|
||||
</overrides>
|
||||
</type>
|
||||
|
||||
</types>
|
||||
|
||||
<aspects>
|
||||
|
@@ -25,7 +25,6 @@ import org.alfresco.repo.domain.ChildAssoc;
|
||||
import org.alfresco.repo.domain.Node;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.EqualsHelper;
|
||||
|
||||
/**
|
||||
* @author Derek Hulley
|
||||
@@ -124,9 +123,12 @@ public class ChildAssocImpl implements ChildAssoc, Serializable
|
||||
{
|
||||
StringBuffer sb = new StringBuffer(32);
|
||||
sb.append("ChildAssoc")
|
||||
.append("[ parent=").append(parent)
|
||||
.append(", child=").append(child)
|
||||
.append("[ id=").append(id)
|
||||
.append(", parent=").append(parent.getId())
|
||||
.append(", child=").append(child.getId())
|
||||
.append(", child name=").append(childNodeName)
|
||||
.append(", child name crc=").append(childNodeNameCrc)
|
||||
.append(", assoc type=").append(getTypeQName())
|
||||
.append(", assoc name=").append(getQname())
|
||||
.append(", isPrimary=").append(isPrimary)
|
||||
.append("]");
|
||||
|
@@ -144,4 +144,14 @@
|
||||
ace.authority.recipient = :authorityRecipient
|
||||
</query>
|
||||
|
||||
<query name="permission.patch.GetAccessControlEntriesToChangePermissionOn" >
|
||||
select
|
||||
entry
|
||||
from
|
||||
org.alfresco.repo.domain.hibernate.DbAccessControlEntryImpl entry
|
||||
where
|
||||
entry.permission.typeQname = :oldTypeQName and
|
||||
entry.permission.name = :oldName
|
||||
</query>
|
||||
|
||||
</hibernate-mapping>
|
@@ -29,7 +29,7 @@
|
||||
unique="false"
|
||||
not-null="false"
|
||||
cascade="none" />
|
||||
<property name="changeTxnId" column="change_txn_id" type="string" length="56" not-null="true" index="CHANGE_TXN_ID"/>
|
||||
<property name="changeTxnId" column="change_txn_id" type="string" length="56" not-null="true" />
|
||||
</class>
|
||||
|
||||
<class
|
||||
@@ -70,6 +70,14 @@
|
||||
status.key.identifier = :identifier
|
||||
</query>
|
||||
|
||||
<query name="txn.GetLastTxnId">
|
||||
select
|
||||
max(txn.id)
|
||||
from
|
||||
org.alfresco.repo.domain.hibernate.NodeStatusImpl as status
|
||||
join status.transaction as txn
|
||||
</query>
|
||||
|
||||
<query name="txn.CountTransactions">
|
||||
select
|
||||
count(txn.id)
|
||||
@@ -90,6 +98,21 @@
|
||||
]]>
|
||||
</query>
|
||||
|
||||
<query name="txn.GetNextRemoteTxns">
|
||||
<![CDATA[
|
||||
select
|
||||
txn
|
||||
from
|
||||
org.alfresco.repo.domain.hibernate.TransactionImpl as txn
|
||||
join txn.server as server
|
||||
where
|
||||
txn.id > :lastTxnId and
|
||||
server.ipAddress != :serverIpAddress
|
||||
order by
|
||||
txn.id
|
||||
]]>
|
||||
</query>
|
||||
|
||||
<query name="txn.GetTxnUpdateCountForStore">
|
||||
select
|
||||
count(status.key.guid)
|
||||
@@ -98,9 +121,7 @@
|
||||
join status.transaction as txn
|
||||
where
|
||||
txn.id = :txnId and
|
||||
status.node is not null and
|
||||
status.key.protocol = :protocol and
|
||||
status.key.identifier = :identifier
|
||||
status.node is not null
|
||||
</query>
|
||||
|
||||
<query name="txn.GetTxnDeleteCountForStore">
|
||||
@@ -111,9 +132,7 @@
|
||||
join status.transaction as txn
|
||||
where
|
||||
txn.id = :txnId and
|
||||
status.node is null and
|
||||
status.key.protocol = :protocol and
|
||||
status.key.identifier = :identifier
|
||||
status.node is null
|
||||
</query>
|
||||
|
||||
<query name="txn.GetTxnChangesForStore">
|
||||
|
@@ -25,7 +25,9 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Writer;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -33,6 +35,9 @@ import java.util.List;
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.repo.admin.patch.impl.SchemaUpgradeScriptPatch;
|
||||
import org.alfresco.repo.content.filestore.FileContentWriter;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.util.AbstractLifecycleBean;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -45,8 +50,6 @@ import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
|
||||
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
@@ -58,12 +61,14 @@ import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class SchemaBootstrap implements ApplicationListener
|
||||
public class SchemaBootstrap extends AbstractLifecycleBean
|
||||
{
|
||||
/** The placeholder for the configured <code>Dialect</code> class name: <b>${db.script.dialect}</b> */
|
||||
private static final String PLACEHOLDER_SCRIPT_DIALECT = "\\$\\{db\\.script\\.dialect\\}";
|
||||
|
||||
private static final String MSG_EXECUTING_SCRIPT = "schema.update.msg.executing_script";
|
||||
private static final String MSG_OPTIONAL_STATEMENT_FAILED = "schema.update.msg.optional_statement_failed";
|
||||
private static final String ERR_STATEMENT_FAILED = "schema.update.err.statement_failed";
|
||||
private static final String ERR_UPDATE_FAILED = "schema.update.err.update_failed";
|
||||
private static final String ERR_VALIDATION_FAILED = "schema.update.err.validation_failed";
|
||||
private static final String ERR_SCRIPT_NOT_RUN = "schema.update.err.update_script_not_run";
|
||||
@@ -148,58 +153,6 @@ public class SchemaBootstrap implements ApplicationListener
|
||||
this.applyUpdateScriptPatches = scriptPatches;
|
||||
}
|
||||
|
||||
public void onApplicationEvent(ApplicationEvent event)
|
||||
{
|
||||
if (!(event instanceof ContextRefreshedEvent))
|
||||
{
|
||||
// only work on startup
|
||||
return;
|
||||
}
|
||||
|
||||
// do everything in a transaction
|
||||
Session session = getLocalSessionFactory().openSession();
|
||||
Transaction transaction = session.beginTransaction();
|
||||
try
|
||||
{
|
||||
// make sure that we don't autocommit
|
||||
Connection connection = session.connection();
|
||||
connection.setAutoCommit(false);
|
||||
|
||||
Configuration cfg = localSessionFactory.getConfiguration();
|
||||
// dump the schema, if required
|
||||
if (schemaOuputFilename != null)
|
||||
{
|
||||
File schemaOutputFile = new File(schemaOuputFilename);
|
||||
dumpSchemaCreate(cfg, schemaOutputFile);
|
||||
}
|
||||
|
||||
// update the schema, if required
|
||||
if (updateSchema)
|
||||
{
|
||||
updateSchema(cfg, session, connection);
|
||||
}
|
||||
|
||||
// verify that all patches have been applied correctly
|
||||
checkSchemaPatchScripts(cfg, session, connection, validateUpdateScriptPatches, false); // check scripts
|
||||
checkSchemaPatchScripts(cfg, session, connection, applyUpdateScriptPatches, false); // check scripts
|
||||
|
||||
// all done successfully
|
||||
transaction.commit();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
try { transaction.rollback(); } catch (Throwable ee) {}
|
||||
if (updateSchema)
|
||||
{
|
||||
throw new AlfrescoRuntimeException(ERR_UPDATE_FAILED, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AlfrescoRuntimeException(ERR_VALIDATION_FAILED, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dumpSchemaCreate(Configuration cfg, File schemaOutputFile)
|
||||
{
|
||||
// if the file exists, delete it
|
||||
@@ -220,39 +173,78 @@ public class SchemaBootstrap implements ApplicationListener
|
||||
return (SessionFactory) localSessionFactory.getObject();
|
||||
}
|
||||
|
||||
private static class NoSchemaException extends Exception
|
||||
{
|
||||
private static final long serialVersionUID = 5574280159910824660L;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the number of applied patches
|
||||
*/
|
||||
private int countAppliedPatches(Connection connection) throws Exception
|
||||
{
|
||||
Statement stmt = connection.createStatement();
|
||||
DatabaseMetaData dbMetadata = connection.getMetaData();
|
||||
|
||||
ResultSet tableRs = dbMetadata.getTables(null, null, "%", null);
|
||||
boolean newPatchTable = false;
|
||||
boolean oldPatchTable = false;
|
||||
try
|
||||
{
|
||||
ResultSet rs = stmt.executeQuery("select count(id) from alf_applied_patch");
|
||||
rs.next();
|
||||
int count = rs.getInt(1);
|
||||
return count;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// we'll try another table name
|
||||
while (tableRs.next())
|
||||
{
|
||||
String tableName = tableRs.getString("TABLE_NAME");
|
||||
if (tableName.equalsIgnoreCase("applied_patch"))
|
||||
{
|
||||
oldPatchTable = true;
|
||||
break;
|
||||
}
|
||||
else if (tableName.equalsIgnoreCase("alf_applied_patch"))
|
||||
{
|
||||
newPatchTable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
try { stmt.close(); } catch (Throwable e) {}
|
||||
try { tableRs.close(); } catch (Throwable e) {e.printStackTrace(); }
|
||||
}
|
||||
// for pre-1.4 databases, the table was named differently
|
||||
stmt = connection.createStatement();
|
||||
try
|
||||
|
||||
if (newPatchTable)
|
||||
{
|
||||
ResultSet rs = stmt.executeQuery("select count(id) from applied_patch");
|
||||
rs.next();
|
||||
int count = rs.getInt(1);
|
||||
return count;
|
||||
Statement stmt = connection.createStatement();
|
||||
try
|
||||
{
|
||||
ResultSet rs = stmt.executeQuery("select count(id) from alf_applied_patch");
|
||||
rs.next();
|
||||
int count = rs.getInt(1);
|
||||
return count;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try { stmt.close(); } catch (Throwable e) {}
|
||||
}
|
||||
}
|
||||
finally
|
||||
else if (oldPatchTable)
|
||||
{
|
||||
try { stmt.close(); } catch (Throwable e) {}
|
||||
// found the old style table name
|
||||
Statement stmt = connection.createStatement();
|
||||
try
|
||||
{
|
||||
ResultSet rs = stmt.executeQuery("select count(id) from applied_patch");
|
||||
rs.next();
|
||||
int count = rs.getInt(1);
|
||||
return count;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try { stmt.close(); } catch (Throwable e) {}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The applied patches table is not present
|
||||
throw new NoSchemaException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,22 +300,21 @@ public class SchemaBootstrap implements ApplicationListener
|
||||
{
|
||||
countAppliedPatches(connection);
|
||||
}
|
||||
catch (Throwable e)
|
||||
catch (NoSchemaException e)
|
||||
{
|
||||
create = true;
|
||||
}
|
||||
// Get the dialect
|
||||
final Dialect dialect = Dialect.getDialect(cfg.getProperties());
|
||||
String dialectStr = dialect.getClass().getName();
|
||||
|
||||
if (create)
|
||||
{
|
||||
// Get the dialect
|
||||
final Dialect dialect = Dialect.getDialect(cfg.getProperties());
|
||||
String dialectStr = dialect.getClass().getName();
|
||||
|
||||
// the applied patch table is missing - we assume that all other tables are missing
|
||||
// perform a full update using Hibernate-generated statements
|
||||
File tempFile = TempFileProvider.createTempFile("AlfrescoSchemaCreate-" + dialectStr + "-", ".sql");
|
||||
dumpSchemaCreate(cfg, tempFile);
|
||||
FileInputStream tempInputStream = new FileInputStream(tempFile);
|
||||
executeScriptFile(cfg, connection, tempInputStream, tempFile.getPath());
|
||||
executeScriptFile(cfg, connection, tempFile, tempFile.getPath());
|
||||
// execute post-create scripts (not patches)
|
||||
for (String scriptUrl : this.postCreateScriptUrls)
|
||||
{
|
||||
@@ -340,12 +331,11 @@ public class SchemaBootstrap implements ApplicationListener
|
||||
Writer writer = null;
|
||||
try
|
||||
{
|
||||
final Dialect dialect = Dialect.getDialect(cfg.getProperties());
|
||||
DatabaseMetadata metadata = new DatabaseMetadata(connection, dialect);
|
||||
String[] sqls = cfg.generateSchemaUpdateScript(dialect, metadata);
|
||||
if (sqls.length > 0)
|
||||
{
|
||||
tempFile = TempFileProvider.createTempFile("AlfrescoSchemaUpdate", ".sql");
|
||||
tempFile = TempFileProvider.createTempFile("AlfrescoSchemaUpdate-" + dialectStr + "-", ".sql");
|
||||
writer = new BufferedWriter(new FileWriter(tempFile));
|
||||
for (String sql : sqls)
|
||||
{
|
||||
@@ -364,8 +354,7 @@ public class SchemaBootstrap implements ApplicationListener
|
||||
// execute if there were changes raised by Hibernate
|
||||
if (tempFile != null)
|
||||
{
|
||||
InputStream tempInputStream = new FileInputStream(tempFile);
|
||||
executeScriptFile(cfg, connection, tempInputStream, tempFile.getPath());
|
||||
executeScriptFile(cfg, connection, tempFile, tempFile.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -414,14 +403,27 @@ public class SchemaBootstrap implements ApplicationListener
|
||||
private void executeScriptUrl(Configuration cfg, Connection connection, String scriptUrl) throws Exception
|
||||
{
|
||||
Dialect dialect = Dialect.getDialect(cfg.getProperties());
|
||||
String dialectStr = dialect.getClass().getName();
|
||||
InputStream scriptInputStream = getScriptInputStream(dialect.getClass(), scriptUrl);
|
||||
// check that it exists
|
||||
if (scriptInputStream == null)
|
||||
{
|
||||
throw AlfrescoRuntimeException.create(ERR_SCRIPT_NOT_FOUND, scriptUrl);
|
||||
}
|
||||
// write the script to a temp location for future and failure reference
|
||||
File tempFile = null;
|
||||
try
|
||||
{
|
||||
tempFile = TempFileProvider.createTempFile("AlfrescoSchemaUpdate-" + dialectStr + "-", ".sql");
|
||||
ContentWriter writer = new FileContentWriter(tempFile);
|
||||
writer.putContent(scriptInputStream);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try { scriptInputStream.close(); } catch (Throwable e) {} // usually a duplicate close
|
||||
}
|
||||
// now execute it
|
||||
executeScriptFile(cfg, connection, scriptInputStream, scriptUrl);
|
||||
executeScriptFile(cfg, connection, tempFile, scriptUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -463,11 +465,12 @@ public class SchemaBootstrap implements ApplicationListener
|
||||
private void executeScriptFile(
|
||||
Configuration cfg,
|
||||
Connection connection,
|
||||
InputStream scriptInputStream,
|
||||
File scriptFile,
|
||||
String scriptUrl) throws Exception
|
||||
{
|
||||
logger.info(I18NUtil.getMessage(MSG_EXECUTING_SCRIPT, scriptUrl));
|
||||
|
||||
InputStream scriptInputStream = new FileInputStream(scriptFile);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(scriptInputStream, "UTF8"));
|
||||
try
|
||||
{
|
||||
@@ -502,31 +505,27 @@ public class SchemaBootstrap implements ApplicationListener
|
||||
}
|
||||
// have we reached the end of a statement?
|
||||
boolean execute = false;
|
||||
boolean optional = false;
|
||||
if (sql.endsWith(";"))
|
||||
{
|
||||
sql = sql.substring(0, sql.length() - 1);
|
||||
execute = true;
|
||||
optional = false;
|
||||
}
|
||||
else if (sql.endsWith(";(optional)"))
|
||||
{
|
||||
sql = sql.substring(0, sql.length() - 11);
|
||||
execute = true;
|
||||
optional = true;
|
||||
}
|
||||
// append to the statement being built up
|
||||
sb.append(" ").append(sql);
|
||||
// execute, if required
|
||||
if (execute)
|
||||
{
|
||||
Statement stmt = connection.createStatement();
|
||||
try
|
||||
{
|
||||
sql = sb.toString();
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Executing statment: " + sql);
|
||||
}
|
||||
stmt.execute(sql);
|
||||
sb = new StringBuilder(1024);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try { stmt.close(); } catch (Throwable e) {}
|
||||
}
|
||||
sql = sb.toString();
|
||||
executeStatement(connection, sql, optional, line, scriptFile);
|
||||
sb = new StringBuilder(1024);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -536,4 +535,93 @@ public class SchemaBootstrap implements ApplicationListener
|
||||
try { scriptInputStream.close(); } catch (Throwable e) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the given SQL statement, absorbing exceptions that we expect during
|
||||
* schema creation or upgrade.
|
||||
*/
|
||||
private void executeStatement(Connection connection, String sql, boolean optional, int line, File file) throws Exception
|
||||
{
|
||||
Statement stmt = connection.createStatement();
|
||||
try
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Executing statment: " + sql);
|
||||
}
|
||||
stmt.execute(sql);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
if (optional)
|
||||
{
|
||||
// it was marked as optional, so we just ignore it
|
||||
String msg = I18NUtil.getMessage(MSG_OPTIONAL_STATEMENT_FAILED, sql, e.getMessage(), file.getAbsolutePath(), line);
|
||||
logger.warn(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
String err = I18NUtil.getMessage(ERR_STATEMENT_FAILED, sql, e.getMessage(), file.getAbsolutePath(), line);
|
||||
logger.error(err);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
try { stmt.close(); } catch (Throwable e) {}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent event)
|
||||
{
|
||||
// do everything in a transaction
|
||||
Session session = getLocalSessionFactory().openSession();
|
||||
Transaction transaction = session.beginTransaction();
|
||||
try
|
||||
{
|
||||
// make sure that we don't autocommit
|
||||
Connection connection = session.connection();
|
||||
connection.setAutoCommit(false);
|
||||
|
||||
Configuration cfg = localSessionFactory.getConfiguration();
|
||||
// dump the schema, if required
|
||||
if (schemaOuputFilename != null)
|
||||
{
|
||||
File schemaOutputFile = new File(schemaOuputFilename);
|
||||
dumpSchemaCreate(cfg, schemaOutputFile);
|
||||
}
|
||||
|
||||
// update the schema, if required
|
||||
if (updateSchema)
|
||||
{
|
||||
updateSchema(cfg, session, connection);
|
||||
}
|
||||
|
||||
// verify that all patches have been applied correctly
|
||||
checkSchemaPatchScripts(cfg, session, connection, validateUpdateScriptPatches, false); // check scripts
|
||||
checkSchemaPatchScripts(cfg, session, connection, applyUpdateScriptPatches, false); // check scripts
|
||||
|
||||
// all done successfully
|
||||
transaction.commit();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
try { transaction.rollback(); } catch (Throwable ee) {}
|
||||
if (updateSchema)
|
||||
{
|
||||
throw new AlfrescoRuntimeException(ERR_UPDATE_FAILED, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AlfrescoRuntimeException(ERR_VALIDATION_FAILED, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShutdown(ApplicationEvent event)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
@@ -46,6 +47,7 @@ import org.alfresco.service.cmr.view.Location;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.AbstractLifecycleBean;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -53,8 +55,6 @@ import org.apache.commons.logging.impl.Log4JLogger;
|
||||
import org.apache.log4j.Level;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
/**
|
||||
@@ -62,7 +62,7 @@ import org.springframework.util.FileCopyUtils;
|
||||
*
|
||||
* @author David Caruana
|
||||
*/
|
||||
public class ImporterBootstrap implements ApplicationListener
|
||||
public class ImporterBootstrap extends AbstractLifecycleBean
|
||||
{
|
||||
// View Properties (used in setBootstrapViews)
|
||||
public static final String VIEW_PATH_PROPERTY = "path";
|
||||
@@ -83,6 +83,7 @@ public class ImporterBootstrap implements ApplicationListener
|
||||
private NodeService nodeService;
|
||||
private ImporterService importerService;
|
||||
private List<Properties> bootstrapViews;
|
||||
private List<Properties> extensionBootstrapViews;
|
||||
private StoreRef storeRef = null;
|
||||
private List<String> mustNotExistStoreUrls = null;
|
||||
private Properties configuration = null;
|
||||
@@ -176,6 +177,20 @@ public class ImporterBootstrap implements ApplicationListener
|
||||
this.bootstrapViews = bootstrapViews;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bootstrap views
|
||||
*
|
||||
* @param bootstrapViews
|
||||
*/
|
||||
public void addBootstrapViews(List<Properties> bootstrapViews)
|
||||
{
|
||||
if (this.extensionBootstrapViews == null)
|
||||
{
|
||||
this.extensionBootstrapViews = new ArrayList<Properties>();
|
||||
}
|
||||
this.extensionBootstrapViews.addAll(bootstrapViews);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Store Ref to bootstrap into
|
||||
*
|
||||
@@ -348,6 +363,12 @@ public class ImporterBootstrap implements ApplicationListener
|
||||
// bootstrap the store contents
|
||||
if (bootstrapViews != null)
|
||||
{
|
||||
// add-in any extended views
|
||||
if (extensionBootstrapViews != null)
|
||||
{
|
||||
bootstrapViews.addAll(extensionBootstrapViews);
|
||||
}
|
||||
|
||||
for (Properties bootstrapView : bootstrapViews)
|
||||
{
|
||||
String view = bootstrapView.getProperty(VIEW_LOCATION_VIEW);
|
||||
@@ -643,16 +664,16 @@ public class ImporterBootstrap implements ApplicationListener
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
public void onApplicationEvent(ApplicationEvent event)
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent event)
|
||||
{
|
||||
if (event instanceof ContextRefreshedEvent)
|
||||
{
|
||||
bootstrap();
|
||||
}
|
||||
bootstrap();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShutdown(ApplicationEvent event)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* 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.importer;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* Collection of views to import
|
||||
*
|
||||
* @author David Caruana
|
||||
*/
|
||||
public class ImporterBootstrapViews implements InitializingBean
|
||||
{
|
||||
// Dependencies
|
||||
private ImporterBootstrap importer;
|
||||
private List<Properties> bootstrapViews;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the importer
|
||||
*
|
||||
* @param importer
|
||||
*/
|
||||
public void setImporter(ImporterBootstrap importer)
|
||||
{
|
||||
this.importer = importer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bootstrap views
|
||||
*
|
||||
* @param bootstrapViews
|
||||
*/
|
||||
public void setBootstrapViews(List<Properties> bootstrapViews)
|
||||
{
|
||||
this.bootstrapViews = bootstrapViews;
|
||||
}
|
||||
|
||||
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
importer.addBootstrapViews(bootstrapViews);
|
||||
}
|
||||
|
||||
}
|
@@ -22,7 +22,7 @@ import java.util.List;
|
||||
|
||||
import org.alfresco.repo.admin.patch.PatchDaoService;
|
||||
import org.alfresco.repo.domain.AppliedPatch;
|
||||
import org.alfresco.repo.domain.hibernate.VersionCounterDaoComponentImpl;
|
||||
import org.alfresco.repo.version.common.counter.VersionCounterService;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
|
||||
@@ -37,7 +37,7 @@ public class SystemExporterImporter
|
||||
// dependencies
|
||||
private NodeService nodeService;
|
||||
private PatchDaoService patchDao;
|
||||
private VersionCounterDaoComponentImpl versionCounterDao;
|
||||
private VersionCounterService versionCounterService;
|
||||
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
@@ -50,9 +50,9 @@ public class SystemExporterImporter
|
||||
this.patchDao = patchDaoService;
|
||||
}
|
||||
|
||||
public void setVersionDao(VersionCounterDaoComponentImpl versionCounterDao)
|
||||
public void setVersionCounterService(VersionCounterService versionCounterService)
|
||||
{
|
||||
this.versionCounterDao = versionCounterDao;
|
||||
this.versionCounterService = versionCounterService;
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ public class SystemExporterImporter
|
||||
for (StoreRef storeRef : storeRefs)
|
||||
{
|
||||
VersionCounterInfo versionCounterInfo = new VersionCounterInfo();
|
||||
int versionCount = versionCounterDao.currentVersionNumber(storeRef);
|
||||
int versionCount = versionCounterService.currentVersionNumber(storeRef);
|
||||
versionCounterInfo.storeRef = storeRef.toString();
|
||||
versionCounterInfo.count = versionCount;
|
||||
systemInfo.versionCounters.add(versionCounterInfo);
|
||||
@@ -128,7 +128,7 @@ public class SystemExporterImporter
|
||||
for (VersionCounterInfo versionCounterInfo : systemInfo.versionCounters)
|
||||
{
|
||||
StoreRef storeRef = new StoreRef(versionCounterInfo.storeRef);
|
||||
versionCounterDao.setVersionNumber(storeRef, versionCounterInfo.count);
|
||||
versionCounterService.setVersionNumber(storeRef, versionCounterInfo.count);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -26,9 +26,8 @@ import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.view.ImporterException;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.AbstractLifecycleBean;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
|
||||
|
||||
/**
|
||||
@@ -36,7 +35,7 @@ import org.springframework.context.event.ContextRefreshedEvent;
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class SystemInfoBootstrap implements ApplicationListener
|
||||
public class SystemInfoBootstrap extends AbstractLifecycleBean
|
||||
{
|
||||
// dependencies
|
||||
private TransactionService transactionService;
|
||||
@@ -177,16 +176,16 @@ public class SystemInfoBootstrap implements ApplicationListener
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
public void onApplicationEvent(ApplicationEvent event)
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent event)
|
||||
{
|
||||
if (event instanceof ContextRefreshedEvent)
|
||||
{
|
||||
bootstrap();
|
||||
}
|
||||
bootstrap();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShutdown(ApplicationEvent event)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -28,14 +28,14 @@ import org.alfresco.service.cmr.action.ParameterDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
import org.mozilla.javascript.Wrapper;
|
||||
|
||||
/**
|
||||
* Scripted Action service for describing and executing actions against Nodes.
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public final class Actions implements Scopeable
|
||||
public final class Actions extends BaseScriptImplementation implements Scopeable
|
||||
{
|
||||
/** Repository Service Registry */
|
||||
private ServiceRegistry services;
|
||||
@@ -43,15 +43,14 @@ public final class Actions implements Scopeable
|
||||
/** Root scope for this object */
|
||||
private Scriptable scope;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Set the service registry
|
||||
*
|
||||
* @param services repository service registry
|
||||
* @param serviceRegistry the service registry
|
||||
*/
|
||||
public Actions(ServiceRegistry services)
|
||||
public void setServiceRegistry(ServiceRegistry serviceRegistry)
|
||||
{
|
||||
this.services = services;
|
||||
this.services = serviceRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,7 +64,7 @@ public final class Actions implements Scopeable
|
||||
/**
|
||||
* Gets the list of registered action names
|
||||
*
|
||||
* @return the registered action names
|
||||
* @return the registered action names
|
||||
*/
|
||||
public String[] getRegistered()
|
||||
{
|
||||
@@ -88,8 +87,9 @@ public final class Actions implements Scopeable
|
||||
/**
|
||||
* Create an Action
|
||||
*
|
||||
* @param actionName the action name
|
||||
* @return the action
|
||||
* @param actionName
|
||||
* the action name
|
||||
* @return the action
|
||||
*/
|
||||
public ScriptAction create(String actionName)
|
||||
{
|
||||
@@ -105,7 +105,6 @@ public final class Actions implements Scopeable
|
||||
return scriptAction;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Scriptable Action
|
||||
*
|
||||
@@ -123,14 +122,16 @@ public final class Actions implements Scopeable
|
||||
|
||||
/** Action state */
|
||||
private Action action;
|
||||
private ActionDefinition actionDef;
|
||||
private ScriptableParameterMap<String, Serializable> parameters = null;
|
||||
|
||||
private ActionDefinition actionDef;
|
||||
|
||||
private ScriptableParameterMap<String, Serializable> parameters = null;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param action Alfresco action
|
||||
* @param action
|
||||
* Alfresco action
|
||||
*/
|
||||
public ScriptAction(Action action, ActionDefinition actionDef)
|
||||
{
|
||||
@@ -150,7 +151,7 @@ public final class Actions implements Scopeable
|
||||
/**
|
||||
* Returns the action name
|
||||
*
|
||||
* @return action name
|
||||
* @return action name
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
@@ -163,11 +164,8 @@ public final class Actions implements Scopeable
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the properties known about this node.
|
||||
*
|
||||
* The Map returned implements the Scriptable interface to allow access to the properties via
|
||||
* JavaScript associative array access. This means properties of a node can be access thus:
|
||||
* <code>node.properties["name"]</code>
|
||||
* Return all the properties known about this node. The Map returned implements the Scriptable interface to allow access to the properties via JavaScript associative array
|
||||
* access. This means properties of a node can be access thus: <code>node.properties["name"]</code>
|
||||
*
|
||||
* @return Map of properties for this Node.
|
||||
*/
|
||||
@@ -197,7 +195,8 @@ public final class Actions implements Scopeable
|
||||
/**
|
||||
* Execute action
|
||||
*
|
||||
* @param node the node to execute action upon
|
||||
* @param node
|
||||
* the node to execute action upon
|
||||
*/
|
||||
@SuppressWarnings("synthetic-access")
|
||||
public void execute(Node node)
|
||||
@@ -216,6 +215,9 @@ public final class Actions implements Scopeable
|
||||
}
|
||||
}
|
||||
services.getActionService().executeAction(action, node.getNodeRef());
|
||||
|
||||
// Reset the actioned upon node
|
||||
node.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,9 +230,11 @@ public final class Actions implements Scopeable
|
||||
/**
|
||||
* Convert Action Parameter for Script usage
|
||||
*
|
||||
* @param paramName parameter name
|
||||
* @param value value to convert
|
||||
* @return converted value
|
||||
* @param paramName
|
||||
* parameter name
|
||||
* @param value
|
||||
* value to convert
|
||||
* @return converted value
|
||||
*/
|
||||
@SuppressWarnings("synthetic-access")
|
||||
public Serializable convertActionParamForScript(String paramName, Serializable value)
|
||||
@@ -238,7 +242,7 @@ public final class Actions implements Scopeable
|
||||
ParameterDefinition paramDef = actionDef.getParameterDefintion(paramName);
|
||||
if (paramDef != null && paramDef.getType().equals(DataTypeDefinition.QNAME))
|
||||
{
|
||||
return ((QName)value).toPrefixString(services.getNamespaceService());
|
||||
return ((QName) value).toPrefixString(services.getNamespaceService());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -249,17 +253,45 @@ public final class Actions implements Scopeable
|
||||
/**
|
||||
* Convert Action Parameter for Java usage
|
||||
*
|
||||
* @param paramName parameter name
|
||||
* @param value value to convert
|
||||
* @return converted value
|
||||
* @param paramName
|
||||
* parameter name
|
||||
* @param value
|
||||
* value to convert
|
||||
* @return converted value
|
||||
*/
|
||||
@SuppressWarnings("synthetic-access")
|
||||
public Serializable convertActionParamForRepo(String paramName, Serializable value)
|
||||
{
|
||||
ParameterDefinition paramDef = actionDef.getParameterDefintion(paramName);
|
||||
|
||||
if (paramDef != null && paramDef.getType().equals(DataTypeDefinition.QNAME))
|
||||
{
|
||||
return QName.createQName((String)value, services.getNamespaceService());
|
||||
if (value instanceof Wrapper)
|
||||
{
|
||||
// unwrap a Java object from a JavaScript wrapper
|
||||
// recursively call this method to convert the unwrapped value
|
||||
return convertActionParamForRepo(paramName, (Serializable) ((Wrapper) value).unwrap());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value instanceof String)
|
||||
{
|
||||
String stringQName = (String) value;
|
||||
if (stringQName.startsWith("{"))
|
||||
{
|
||||
return QName.createQName(stringQName);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return QName.createQName(stringQName, services.getNamespaceService());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -269,24 +301,23 @@ public final class Actions implements Scopeable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Scripted Parameter map with modified flag.
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public static final class ScriptableParameterMap<K,V> extends ScriptableHashMap<K,V>
|
||||
public static final class ScriptableParameterMap<K, V> extends ScriptableHashMap<K, V>
|
||||
{
|
||||
private static final long serialVersionUID = 574661815973241554L;
|
||||
private boolean modified = false;
|
||||
|
||||
private boolean modified = false;
|
||||
|
||||
/**
|
||||
* Is this a modified parameter map?
|
||||
*
|
||||
* @return true => modified
|
||||
* @return true => modified
|
||||
*/
|
||||
/*package*/ boolean isModified()
|
||||
/* package */boolean isModified()
|
||||
{
|
||||
return modified;
|
||||
}
|
||||
@@ -294,14 +325,17 @@ public final class Actions implements Scopeable
|
||||
/**
|
||||
* Set explicitly whether this map is modified
|
||||
*
|
||||
* @param modified true => modified, false => not modified
|
||||
* @param modified
|
||||
* true => modified, false => not modified
|
||||
*/
|
||||
/*package*/ void setModified(boolean modified)
|
||||
/* package */void setModified(boolean modified)
|
||||
{
|
||||
this.modified = modified;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.mozilla.javascript.Scriptable#getClassName()
|
||||
*/
|
||||
@Override
|
||||
@@ -310,7 +344,9 @@ public final class Actions implements Scopeable
|
||||
return "ScriptableParameterMap";
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.mozilla.javascript.Scriptable#delete(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
@@ -320,7 +356,9 @@ public final class Actions implements Scopeable
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.mozilla.javascript.Scriptable#put(java.lang.String, org.mozilla.javascript.Scriptable, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
|
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package org.alfresco.repo.jscript;
|
||||
|
||||
import org.alfresco.service.cmr.repository.ScriptImplementation;
|
||||
import org.alfresco.service.cmr.repository.ScriptService;
|
||||
|
||||
/**
|
||||
* Abstract base class for a script implementation
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public abstract class BaseScriptImplementation implements ScriptImplementation
|
||||
{
|
||||
/** The script service */
|
||||
private ScriptService scriptService;
|
||||
|
||||
/** The name of the script */
|
||||
private String scriptName;
|
||||
|
||||
/**
|
||||
* Sets the script service
|
||||
*
|
||||
* @param scriptService the script service
|
||||
*/
|
||||
public void setScriptService(ScriptService scriptService)
|
||||
{
|
||||
this.scriptService = scriptService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this script with the script service
|
||||
*/
|
||||
public void register()
|
||||
{
|
||||
this.scriptService.registerScript(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the script name
|
||||
*
|
||||
* @param scriptName the script name
|
||||
*/
|
||||
public void setScriptName(String scriptName)
|
||||
{
|
||||
this.scriptName = scriptName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.repository.ScriptImplementation#getScriptName()
|
||||
*/
|
||||
public String getScriptName()
|
||||
{
|
||||
return this.scriptName;
|
||||
}
|
||||
}
|
206
source/java/org/alfresco/repo/jscript/CategoryNode.java
Normal file
206
source/java/org/alfresco/repo/jscript/CategoryNode.java
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* 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.jscript;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.TemplateImageResolver;
|
||||
import org.alfresco.service.cmr.search.CategoryService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
/**
|
||||
* Category Nodes from the classification helper have special support.
|
||||
*
|
||||
* @author Andy Hind
|
||||
*/
|
||||
public class CategoryNode extends Node
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param nodeRef
|
||||
* @param services
|
||||
* @param resolver
|
||||
*/
|
||||
public CategoryNode(NodeRef nodeRef, ServiceRegistry services, TemplateImageResolver resolver)
|
||||
{
|
||||
super(nodeRef, services, resolver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param nodeRef
|
||||
* @param services
|
||||
* @param resolver
|
||||
* @param scope
|
||||
*/
|
||||
public CategoryNode(NodeRef nodeRef, ServiceRegistry services, TemplateImageResolver resolver, Scriptable scope)
|
||||
{
|
||||
super(nodeRef, services, resolver, scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all the members of a category
|
||||
*/
|
||||
public Node[] getCategoryMembers()
|
||||
{
|
||||
return buildNodes(services.getCategoryService().getChildren(getNodeRef(), CategoryService.Mode.MEMBERS, CategoryService.Depth.ANY));
|
||||
}
|
||||
|
||||
public Node[] jsGet_categoryMembers()
|
||||
{
|
||||
return getCategoryMembers();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all the subcategories of a category
|
||||
*/
|
||||
public CategoryNode[] getSubCategories()
|
||||
{
|
||||
return buildCategoryNodes(services.getCategoryService().getChildren(getNodeRef(), CategoryService.Mode.SUB_CATEGORIES, CategoryService.Depth.ANY));
|
||||
}
|
||||
|
||||
public CategoryNode[] jsGet_subCategories()
|
||||
{
|
||||
return getSubCategories();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return members and subcategories of a category
|
||||
*/
|
||||
public Node[] getMembersAndSubCategories()
|
||||
{
|
||||
return buildMixedNodes(services.getCategoryService().getChildren(getNodeRef(), CategoryService.Mode.ALL, CategoryService.Depth.ANY));
|
||||
}
|
||||
|
||||
public Node[] jsGet_membersAndSubCategories()
|
||||
{
|
||||
return getMembersAndSubCategories();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all the immediate member of a category
|
||||
*/
|
||||
public Node[] getImmediateCategoryMembers()
|
||||
{
|
||||
return buildNodes(services.getCategoryService().getChildren(getNodeRef(), CategoryService.Mode.MEMBERS, CategoryService.Depth.IMMEDIATE));
|
||||
}
|
||||
|
||||
public Node[] jsGet_immediateCategoryMembers()
|
||||
{
|
||||
return getImmediateCategoryMembers();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all the immediate subcategories of a category
|
||||
*/
|
||||
public CategoryNode[] getImmediateSubCategories()
|
||||
{
|
||||
return buildCategoryNodes(services.getCategoryService().getChildren(getNodeRef(), CategoryService.Mode.SUB_CATEGORIES, CategoryService.Depth.IMMEDIATE));
|
||||
}
|
||||
|
||||
public CategoryNode[] jsGet_immediateSubCategories()
|
||||
{
|
||||
return getImmediateSubCategories();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return immediate members and subcategories of a category
|
||||
*/
|
||||
public Node[] getImmediateMembersAndSubCategories()
|
||||
{
|
||||
return buildMixedNodes(services.getCategoryService().getChildren(getNodeRef(), CategoryService.Mode.ALL, CategoryService.Depth.IMMEDIATE));
|
||||
}
|
||||
|
||||
public Node[] jsGet_immediateMembersAndSubCategories()
|
||||
{
|
||||
return getImmediateMembersAndSubCategories();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new subcategory
|
||||
*
|
||||
* @param name Of the category to create
|
||||
*
|
||||
* @return CategoryNode
|
||||
*/
|
||||
public CategoryNode createSubCategory(String name)
|
||||
{
|
||||
return new CategoryNode(services.getCategoryService().createCategory(getNodeRef(), name), this.services, this.imageResolver, this.scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove this category
|
||||
*/
|
||||
public void removeCategory()
|
||||
{
|
||||
services.getCategoryService().deleteCategory(getNodeRef());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getIsCategory()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private CategoryNode[] buildCategoryNodes(Collection<ChildAssociationRef> cars)
|
||||
{
|
||||
CategoryNode[] categoryNodes = new CategoryNode[cars.size()];
|
||||
int i = 0;
|
||||
for (ChildAssociationRef car : cars)
|
||||
{
|
||||
categoryNodes[i++] = new CategoryNode(car.getChildRef(), this.services, this.imageResolver, this.scope);
|
||||
}
|
||||
return categoryNodes;
|
||||
}
|
||||
|
||||
private Node[] buildNodes(Collection<ChildAssociationRef> cars)
|
||||
{
|
||||
Node[] nodes = new Node[cars.size()];
|
||||
int i = 0;
|
||||
for (ChildAssociationRef car : cars)
|
||||
{
|
||||
nodes[i++] = new Node(car.getChildRef(), this.services, this.imageResolver, this.scope);
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private Node[] buildMixedNodes(Collection<ChildAssociationRef> cars)
|
||||
{
|
||||
Node[] nodes = new Node[cars.size()];
|
||||
int i = 0;
|
||||
for (ChildAssociationRef car : cars)
|
||||
{
|
||||
QName type = services.getNodeService().getType(car.getChildRef());
|
||||
if (services.getDictionaryService().isSubClass(type, ContentModel.TYPE_CATEGORY))
|
||||
{
|
||||
nodes[i++] = new CategoryNode(car.getChildRef(), this.services, this.imageResolver, this.scope);
|
||||
}
|
||||
else
|
||||
{
|
||||
nodes[i++] = new Node(car.getChildRef(), this.services, this.imageResolver, this.scope);
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
}
|
202
source/java/org/alfresco/repo/jscript/CategoryTemplateNode.java
Normal file
202
source/java/org/alfresco/repo/jscript/CategoryTemplateNode.java
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* 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.jscript;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.TemplateImageResolver;
|
||||
import org.alfresco.service.cmr.repository.TemplateNode;
|
||||
import org.alfresco.service.cmr.search.CategoryService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* Category Nodes from the classification helper have special support.
|
||||
*/
|
||||
public class CategoryTemplateNode extends TemplateNode
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param nodeRef
|
||||
* @param services
|
||||
* @param resolver
|
||||
*/
|
||||
public CategoryTemplateNode(NodeRef nodeRef, ServiceRegistry services, TemplateImageResolver resolver)
|
||||
{
|
||||
super(nodeRef, services, resolver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getIsCategory()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all the member of a category
|
||||
*/
|
||||
public List<TemplateNode> getCategoryMembers()
|
||||
{
|
||||
if (getIsCategory())
|
||||
{
|
||||
return buildTemplateNodeList(services.getCategoryService().getChildren(getNodeRef(),
|
||||
CategoryService.Mode.MEMBERS, CategoryService.Depth.ANY));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Collections.<TemplateNode>emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all the subcategories of a category
|
||||
*/
|
||||
public List<CategoryTemplateNode> getSubCategories()
|
||||
{
|
||||
if (getIsCategory())
|
||||
{
|
||||
return buildCategoryNodeList(services.getCategoryService().getChildren(getNodeRef(),
|
||||
CategoryService.Mode.SUB_CATEGORIES, CategoryService.Depth.ANY));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Collections.<CategoryTemplateNode>emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return members and subcategories of a category
|
||||
*/
|
||||
public List<TemplateNode> getMembersAndSubCategories()
|
||||
{
|
||||
if (getIsCategory())
|
||||
{
|
||||
|
||||
return buildMixedNodeList(services.getCategoryService().getChildren(getNodeRef(), CategoryService.Mode.ALL,
|
||||
CategoryService.Depth.ANY));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Collections.<TemplateNode>emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all the immediate member of a category
|
||||
*/
|
||||
public List<TemplateNode> getImmediateCategoryMembers()
|
||||
{
|
||||
if (getIsCategory())
|
||||
{
|
||||
return buildTemplateNodeList(services.getCategoryService().getChildren(getNodeRef(),
|
||||
CategoryService.Mode.MEMBERS, CategoryService.Depth.IMMEDIATE));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Collections.<TemplateNode>emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all the immediate subcategories of a category
|
||||
*/
|
||||
public List<CategoryTemplateNode> getImmediateSubCategories()
|
||||
{
|
||||
if (getIsCategory())
|
||||
{
|
||||
return buildCategoryNodeList(services.getCategoryService().getChildren(getNodeRef(),
|
||||
CategoryService.Mode.SUB_CATEGORIES, CategoryService.Depth.IMMEDIATE));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Collections.<CategoryTemplateNode>emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return immediate members and subcategories of a category
|
||||
*/
|
||||
public List<TemplateNode> getImmediateMembersAndSubCategories()
|
||||
{
|
||||
if (getIsCategory())
|
||||
{
|
||||
return buildMixedNodeList(services.getCategoryService().getChildren(getNodeRef(),
|
||||
CategoryService.Mode.ALL, CategoryService.Depth.IMMEDIATE));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Collections.<TemplateNode>emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Support to build node lists from category service API calls.
|
||||
*
|
||||
* @param childRefs
|
||||
*
|
||||
* @return List of TemplateNode
|
||||
*/
|
||||
private List<TemplateNode> buildTemplateNodeList(Collection<ChildAssociationRef> childRefs)
|
||||
{
|
||||
List<TemplateNode> answer = new ArrayList<TemplateNode>(childRefs.size());
|
||||
for (ChildAssociationRef ref : childRefs)
|
||||
{
|
||||
// create our Node representation from the NodeRef
|
||||
TemplateNode child = new TemplateNode(ref.getChildRef(), this.services, this.imageResolver);
|
||||
answer.add(child);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
private List<CategoryTemplateNode> buildCategoryNodeList(Collection<ChildAssociationRef> childRefs)
|
||||
{
|
||||
List<CategoryTemplateNode> answer = new ArrayList<CategoryTemplateNode>(childRefs.size());
|
||||
for (ChildAssociationRef ref : childRefs)
|
||||
{
|
||||
// create our Node representation from the NodeRef
|
||||
CategoryTemplateNode child = new CategoryTemplateNode(ref.getChildRef(), this.services, this.imageResolver);
|
||||
answer.add(child);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
private List<TemplateNode> buildMixedNodeList(Collection<ChildAssociationRef> cars)
|
||||
{
|
||||
List<TemplateNode> nodes = new ArrayList<TemplateNode>(cars.size());
|
||||
int i = 0;
|
||||
for (ChildAssociationRef car : cars)
|
||||
{
|
||||
QName type = services.getNodeService().getType(car.getChildRef());
|
||||
if (services.getDictionaryService().isSubClass(type, ContentModel.TYPE_CATEGORY))
|
||||
{
|
||||
nodes.add(new CategoryTemplateNode(car.getChildRef(), this.services, this.imageResolver));
|
||||
}
|
||||
else
|
||||
{
|
||||
nodes.add(new TemplateNode(car.getChildRef(), this.services, this.imageResolver));
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
}
|
144
source/java/org/alfresco/repo/jscript/Classification.java
Normal file
144
source/java/org/alfresco/repo/jscript/Classification.java
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* 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.jscript;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.repository.TemplateImageResolver;
|
||||
import org.alfresco.service.cmr.search.CategoryService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
/**
|
||||
* Support class for finding categories, finding root nodes for categories and creating root categories.
|
||||
*
|
||||
* @author Andy Hind
|
||||
*/
|
||||
public final class Classification implements Scopeable
|
||||
{
|
||||
@SuppressWarnings("unused")
|
||||
private Scriptable scope;
|
||||
|
||||
private ServiceRegistry services;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private TemplateImageResolver imageResolver;
|
||||
|
||||
private StoreRef storeRef;
|
||||
|
||||
public Classification(ServiceRegistry services, StoreRef storeRef, TemplateImageResolver imageResolver)
|
||||
{
|
||||
this.services = services;
|
||||
this.imageResolver = imageResolver;
|
||||
this.storeRef = storeRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.jscript.Scopeable#setScope(org.mozilla.javascript.Scriptable)
|
||||
*/
|
||||
public void setScope(Scriptable scope)
|
||||
{
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all the category nodes in a given classification.
|
||||
*
|
||||
* @param aspect
|
||||
* @return
|
||||
*/
|
||||
public CategoryNode[] getAllCategoryNodes(String aspect)
|
||||
{
|
||||
return buildCategoryNodes(services.getCategoryService().getCategories(storeRef, createQName(aspect),
|
||||
CategoryService.Depth.ANY));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the aspects that define a classification.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String[] getAllClassificationAspects()
|
||||
{
|
||||
Collection<QName> aspects = services.getCategoryService().getClassificationAspects();
|
||||
String[] answer = new String[aspects.size()];
|
||||
int i = 0;
|
||||
for (QName qname : aspects)
|
||||
{
|
||||
answer[i++] = qname.toPrefixString(this.services.getNamespaceService());
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
public String[] jsGet_allClassificationAspects()
|
||||
{
|
||||
return getAllClassificationAspects();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a root category in a classification.
|
||||
*
|
||||
* @param aspect
|
||||
* @param name
|
||||
*/
|
||||
public void createRootCategory(String aspect, String name)
|
||||
{
|
||||
services.getCategoryService().createRootCategory(storeRef, createQName(aspect), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root categories in a classification.
|
||||
*
|
||||
* @param aspect
|
||||
* @return
|
||||
*/
|
||||
public CategoryNode[] getRootCategories(String aspect)
|
||||
{
|
||||
return buildCategoryNodes(services.getCategoryService().getRootCategories(storeRef, createQName(aspect)));
|
||||
}
|
||||
|
||||
private CategoryNode[] buildCategoryNodes(Collection<ChildAssociationRef> cars)
|
||||
{
|
||||
CategoryNode[] categoryNodes = new CategoryNode[cars.size()];
|
||||
int i = 0;
|
||||
for (ChildAssociationRef car : cars)
|
||||
{
|
||||
categoryNodes[i++] = new CategoryNode(car.getChildRef(), this.services, this.imageResolver, this.scope);
|
||||
}
|
||||
return categoryNodes;
|
||||
}
|
||||
|
||||
private QName createQName(String s)
|
||||
{
|
||||
QName qname;
|
||||
if (s.indexOf(QName.NAMESPACE_BEGIN) != -1)
|
||||
{
|
||||
qname = QName.createQName(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
qname = QName.createQName(s, this.services.getNamespaceService());
|
||||
}
|
||||
return qname;
|
||||
}
|
||||
|
||||
}
|
@@ -92,7 +92,7 @@ public class Node implements Serializable, Scopeable
|
||||
private final static String FOLDER_BROWSE_URL = "/navigate/browse/{0}/{1}/{2}";
|
||||
|
||||
/** Root scope for this object */
|
||||
private Scriptable scope;
|
||||
protected Scriptable scope;
|
||||
|
||||
/** Node Value Converter */
|
||||
private NodeValueConverter converter = null;
|
||||
@@ -110,18 +110,17 @@ public class Node implements Serializable, Scopeable
|
||||
private Node[] children = null;
|
||||
/** The properties of this node */
|
||||
private ScriptableQNameMap<String, Serializable> properties = null;
|
||||
private ServiceRegistry services = null;
|
||||
protected ServiceRegistry services = null;
|
||||
private NodeService nodeService = null;
|
||||
private Boolean isDocument = null;
|
||||
private Boolean isContainer = null;
|
||||
private String displayPath = null;
|
||||
private TemplateImageResolver imageResolver = null;
|
||||
protected TemplateImageResolver imageResolver = null;
|
||||
private Node parent = null;
|
||||
private ChildAssociationRef primaryParentAssoc = null;
|
||||
// NOTE: see the reset() method when adding new cached members!
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Construction
|
||||
|
||||
@@ -428,7 +427,7 @@ public class Node implements Serializable, Scopeable
|
||||
/**
|
||||
* @return true if this Node is a container (i.e. a folder)
|
||||
*/
|
||||
public boolean isContainer()
|
||||
public boolean getIsContainer()
|
||||
{
|
||||
if (isContainer == null)
|
||||
{
|
||||
@@ -442,13 +441,13 @@ public class Node implements Serializable, Scopeable
|
||||
|
||||
public boolean jsGet_isContainer()
|
||||
{
|
||||
return isContainer();
|
||||
return getIsContainer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this Node is a Document (i.e. with content)
|
||||
*/
|
||||
public boolean isDocument()
|
||||
public boolean getIsDocument()
|
||||
{
|
||||
if (isDocument == null)
|
||||
{
|
||||
@@ -461,7 +460,21 @@ public class Node implements Serializable, Scopeable
|
||||
|
||||
public boolean jsGet_isDocument()
|
||||
{
|
||||
return isDocument();
|
||||
return getIsDocument();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the Node is a Category
|
||||
*/
|
||||
public boolean getIsCategory()
|
||||
{
|
||||
// this valid is overriden by the CategoryNode sub-class
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean jsGet_isCategory()
|
||||
{
|
||||
return getIsCategory();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -554,7 +567,7 @@ public class Node implements Serializable, Scopeable
|
||||
{
|
||||
if (this.imageResolver != null)
|
||||
{
|
||||
if (isDocument())
|
||||
if (getIsDocument())
|
||||
{
|
||||
return this.imageResolver.resolveImagePathForName(getName(), true);
|
||||
}
|
||||
@@ -581,7 +594,7 @@ public class Node implements Serializable, Scopeable
|
||||
{
|
||||
if (this.imageResolver != null)
|
||||
{
|
||||
if (isDocument())
|
||||
if (getIsDocument())
|
||||
{
|
||||
return this.imageResolver.resolveImagePathForName(getName(), false);
|
||||
}
|
||||
@@ -727,7 +740,7 @@ public class Node implements Serializable, Scopeable
|
||||
*/
|
||||
public String getUrl()
|
||||
{
|
||||
if (isDocument() == true)
|
||||
if (getIsDocument() == true)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -890,7 +903,8 @@ public class Node implements Serializable, Scopeable
|
||||
this.services.getPermissionService().deletePermission(this.nodeRef, authority, permission);
|
||||
}
|
||||
|
||||
// -------------
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Ownership API
|
||||
|
||||
/**
|
||||
@@ -1145,7 +1159,7 @@ public class Node implements Serializable, Scopeable
|
||||
{
|
||||
if (destination != null)
|
||||
{
|
||||
NodeRef copyRef = this.services.getCopyService().copy(
|
||||
NodeRef copyRef = this.services.getCopyService().copyAndRename(
|
||||
this.nodeRef,
|
||||
destination.getNodeRef(),
|
||||
ContentModel.ASSOC_CONTAINS,
|
||||
@@ -1632,7 +1646,7 @@ public class Node implements Serializable, Scopeable
|
||||
this.imageResolver);
|
||||
|
||||
// add the current node as either the document/space as appropriate
|
||||
if (this.isDocument())
|
||||
if (this.getIsDocument())
|
||||
{
|
||||
model.put("document", new TemplateNode(this.nodeRef, this.services, this.imageResolver));
|
||||
model.put("space", new TemplateNode(getPrimaryParentAssoc().getParentRef(), this.services, this.imageResolver));
|
||||
@@ -1724,7 +1738,7 @@ public class Node implements Serializable, Scopeable
|
||||
/**
|
||||
* Reset the Node cached state
|
||||
*/
|
||||
private void reset()
|
||||
public void reset()
|
||||
{
|
||||
this.name = null;
|
||||
this.type = null;
|
||||
|
@@ -21,7 +21,9 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
@@ -30,6 +32,7 @@ import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.ScriptException;
|
||||
import org.alfresco.service.cmr.repository.ScriptImplementation;
|
||||
import org.alfresco.service.cmr.repository.ScriptService;
|
||||
import org.alfresco.service.cmr.repository.TemplateImageResolver;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
@@ -51,6 +54,8 @@ public class RhinoScriptService implements ScriptService
|
||||
/** Repository Service Registry */
|
||||
private ServiceRegistry services;
|
||||
|
||||
/** List of global scripts */
|
||||
private List<ScriptImplementation> globalScripts = new ArrayList<ScriptImplementation>(5);
|
||||
|
||||
/**
|
||||
* Set the Service Registry
|
||||
@@ -62,6 +67,14 @@ public class RhinoScriptService implements ScriptService
|
||||
this.services = services;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.repository.ScriptService#registerScript(java.lang.Object)
|
||||
*/
|
||||
public void registerScript(ScriptImplementation script)
|
||||
{
|
||||
this.globalScripts.add(script);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.service.cmr.repository.ScriptService#executeScript(java.lang.String, java.util.Map)
|
||||
*/
|
||||
@@ -217,28 +230,28 @@ public class RhinoScriptService implements ScriptService
|
||||
model = new HashMap<String, Object>();
|
||||
}
|
||||
|
||||
// add useful util objects
|
||||
model.put("actions", new Actions(services));
|
||||
model.put("logger", new ScriptLogger());
|
||||
// add the global scripts
|
||||
for (ScriptImplementation script : this.globalScripts)
|
||||
{
|
||||
model.put(script.getScriptName(), script);
|
||||
}
|
||||
|
||||
// insert supplied object model into root of the default scope
|
||||
for (String key : model.keySet())
|
||||
{
|
||||
for (String key : model.keySet())
|
||||
// set the root scope on appropriate objects
|
||||
// this is used to allow native JS object creation etc.
|
||||
Object obj = model.get(key);
|
||||
if (obj instanceof Scopeable)
|
||||
{
|
||||
// set the root scope on appropriate objects
|
||||
// this is used to allow native JS object creation etc.
|
||||
Object obj = model.get(key);
|
||||
if (obj instanceof Scopeable)
|
||||
{
|
||||
((Scopeable)obj).setScope(scope);
|
||||
}
|
||||
|
||||
// convert/wrap each object to JavaScript compatible
|
||||
Object jsObject = Context.javaToJS(obj, scope);
|
||||
|
||||
// insert into the root scope ready for access by the script
|
||||
ScriptableObject.putProperty(scope, key, jsObject);
|
||||
((Scopeable)obj).setScope(scope);
|
||||
}
|
||||
|
||||
// convert/wrap each object to JavaScript compatible
|
||||
Object jsObject = Context.javaToJS(obj, scope);
|
||||
|
||||
// insert into the root scope ready for access by the script
|
||||
ScriptableObject.putProperty(scope, key, jsObject);
|
||||
}
|
||||
|
||||
// execute the script
|
||||
@@ -343,6 +356,10 @@ public class RhinoScriptService implements ScriptService
|
||||
|
||||
model.put("search", new Search(services, companyHome.getStoreRef(), resolver));
|
||||
|
||||
model.put("session", new Session(services, resolver));
|
||||
|
||||
model.put("classification", new Classification(services, companyHome.getStoreRef(), resolver));
|
||||
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
@@ -21,7 +21,7 @@ import org.apache.log4j.Logger;
|
||||
/**
|
||||
* @author Kevin Roast
|
||||
*/
|
||||
public final class ScriptLogger
|
||||
public final class ScriptLogger extends BaseScriptImplementation
|
||||
{
|
||||
private static final Logger logger = Logger.getLogger(ScriptLogger.class);
|
||||
|
||||
|
56
source/java/org/alfresco/repo/jscript/ScriptUtils.java
Normal file
56
source/java/org/alfresco/repo/jscript/ScriptUtils.java
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* 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.jscript;
|
||||
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
/**
|
||||
* Place for general and miscellenous utility functions not already found in generic JavaScript.
|
||||
*
|
||||
* @author Kevin Roast
|
||||
*/
|
||||
public final class ScriptUtils extends BaseScriptImplementation implements Scopeable
|
||||
{
|
||||
/** Root scope for this object */
|
||||
private Scriptable scope;
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.jscript.Scopeable#setScope(org.mozilla.javascript.Scriptable)
|
||||
*/
|
||||
public void setScope(Scriptable scope)
|
||||
{
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to pad a string with zero '0' characters to the required length
|
||||
*
|
||||
* @param s String to pad with leading zero '0' characters
|
||||
* @param len Length to pad to
|
||||
*
|
||||
* @return padded string or the original if already at >=len characters
|
||||
*/
|
||||
public String pad(String s, int len)
|
||||
{
|
||||
String result = s;
|
||||
for (int i=0; i<(len - s.length()); i++)
|
||||
{
|
||||
result = "0" + result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
79
source/java/org/alfresco/repo/jscript/Session.java
Normal file
79
source/java/org/alfresco/repo/jscript/Session.java
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* 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.jscript;
|
||||
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.TemplateImageResolver;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
/**
|
||||
* Support object for session level properties etc.
|
||||
* <p>
|
||||
* Provides access to the user's authentication ticket.
|
||||
*
|
||||
* @author Andy Hind
|
||||
*/
|
||||
public class Session implements Scopeable
|
||||
{
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static Log logger = LogFactory.getLog(Session.class);
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private Scriptable scope;
|
||||
|
||||
private ServiceRegistry services;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private TemplateImageResolver imageResolver;
|
||||
|
||||
public Session(ServiceRegistry services, TemplateImageResolver imageResolver)
|
||||
{
|
||||
this.services = services;
|
||||
this.imageResolver = imageResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.repo.jscript.Scopeable#setScope(org.mozilla.javascript.Scriptable)
|
||||
*/
|
||||
public void setScope(Scriptable scope)
|
||||
{
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user's authentication ticket.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getTicket()
|
||||
{
|
||||
return services.getAuthenticationService().getCurrentTicket();
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose the user's authentication ticket as JavaScipt property.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String jsGet_ticket()
|
||||
{
|
||||
return getTicket();
|
||||
}
|
||||
}
|
@@ -503,7 +503,7 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
*/
|
||||
public FileInfo rename(NodeRef sourceNodeRef, String newName) throws FileExistsException, FileNotFoundException
|
||||
{
|
||||
return move(sourceNodeRef, null, newName);
|
||||
return moveOrCopy(sourceNodeRef, null, newName, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -815,12 +815,25 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
for (int i = 0; i < folderCount; i++)
|
||||
{
|
||||
String pathElement = pathElements.get(i);
|
||||
FileInfo pathElementInfo = getPathElementInfo(currentPath, rootNodeRef, parentNodeRef, pathElement, true);
|
||||
parentNodeRef = pathElementInfo.getNodeRef();
|
||||
NodeRef folderNodeRef = searchSimple(parentNodeRef, pathElement);
|
||||
if (folderNodeRef == null)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(128);
|
||||
sb.append("Folder not found: " + currentPath);
|
||||
throw new FileNotFoundException(sb.toString());
|
||||
}
|
||||
parentNodeRef = folderNodeRef;
|
||||
}
|
||||
// we have resolved the folder path - resolve the last component
|
||||
String pathElement = pathElements.get(pathElements.size() - 1);
|
||||
FileInfo result = getPathElementInfo(currentPath, rootNodeRef, parentNodeRef, pathElement, false);
|
||||
NodeRef fileNodeRef = searchSimple(parentNodeRef, pathElement);
|
||||
if (fileNodeRef == null)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(128);
|
||||
sb.append("File not found: " + currentPath);
|
||||
throw new FileNotFoundException(sb.toString());
|
||||
}
|
||||
FileInfo result = getFileInfo(fileNodeRef);
|
||||
// found it
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
@@ -832,42 +845,6 @@ public class FileFolderServiceImpl implements FileFolderService
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to dig down a level for a node based on name
|
||||
*/
|
||||
private FileInfo getPathElementInfo(
|
||||
StringBuilder currentPath,
|
||||
NodeRef rootNodeRef,
|
||||
NodeRef parentNodeRef,
|
||||
String pathElement,
|
||||
boolean folderOnly) throws FileNotFoundException
|
||||
{
|
||||
currentPath.append("/").append(pathElement);
|
||||
|
||||
boolean includeFiles = (folderOnly ? false : true);
|
||||
List<FileInfo> pathElementInfos = search(parentNodeRef, pathElement, includeFiles, true, false);
|
||||
// check
|
||||
if (pathElementInfos.size() == 0)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(128);
|
||||
sb.append(folderOnly ? "Folder" : "File or folder").append(" not found: \n")
|
||||
.append(" root: ").append(rootNodeRef).append("\n")
|
||||
.append(" path: ").append(currentPath);
|
||||
throw new FileNotFoundException(sb.toString());
|
||||
}
|
||||
else if (pathElementInfos.size() > 1)
|
||||
{
|
||||
// we have detected a duplicate name - warn, but allow
|
||||
StringBuilder sb = new StringBuilder(128);
|
||||
sb.append("Duplicate file or folder found: \n")
|
||||
.append(" root: ").append(rootNodeRef).append("\n")
|
||||
.append(" path: ").append(currentPath);
|
||||
logger.warn(sb);
|
||||
}
|
||||
FileInfo pathElementInfo = pathElementInfos.get(0);
|
||||
return pathElementInfo;
|
||||
}
|
||||
|
||||
public FileInfo getFileInfo(NodeRef nodeRef)
|
||||
{
|
||||
try
|
||||
|
@@ -236,11 +236,14 @@ public interface NodeDaoService
|
||||
*/
|
||||
public List<Serializable> getPropertyValuesByActualType(DataTypeDefinition actualDataTypeDefinition);
|
||||
|
||||
public Transaction getLastTxn(final StoreRef storeRef);
|
||||
public int getTxnUpdateCountForStore(final StoreRef storeRef, final long txnId);
|
||||
public int getTxnDeleteCountForStore(final StoreRef storeRef, final long txnId);
|
||||
public Transaction getTxnById(long txnId);
|
||||
public Transaction getLastTxn();
|
||||
public Transaction getLastTxnForStore(final StoreRef storeRef);
|
||||
public int getTxnUpdateCount(final long txnId);
|
||||
public int getTxnDeleteCount(final long txnId);
|
||||
public int getTransactionCount();
|
||||
public List<Transaction> getNextTxns(final Transaction lastTxn, final int count);
|
||||
public List<Transaction> getNextTxns(final long lastTxnId, final int count);
|
||||
public List<Transaction> getNextRemoteTxns(final long lastTxnId, final int count);
|
||||
public List<NodeRef> getTxnChangesForStore(final StoreRef storeRef, final long txnId);
|
||||
public List<NodeRef> getTxnChanges(final long txnId);
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ package org.alfresco.repo.node.db.hibernate;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
@@ -97,6 +98,7 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
|
||||
private final String uuid;
|
||||
|
||||
private static TransactionAwareSingleton<Long> serverIdSingleton = new TransactionAwareSingleton<Long>();
|
||||
private final String ipAddress;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -104,6 +106,14 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
|
||||
public HibernateNodeDaoServiceImpl()
|
||||
{
|
||||
this.uuid = GUID.generate();
|
||||
try
|
||||
{
|
||||
ipAddress = InetAddress.getLocalHost().getHostAddress();
|
||||
}
|
||||
catch (UnknownHostException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to get server IP address", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,7 +158,6 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
|
||||
}
|
||||
try
|
||||
{
|
||||
final String ipAddress = InetAddress.getLocalHost().getHostAddress();
|
||||
HibernateCallback callback = new HibernateCallback()
|
||||
{
|
||||
public Object doInHibernate(Session session)
|
||||
@@ -994,16 +1003,46 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
|
||||
/*
|
||||
* Queries for transactions
|
||||
*/
|
||||
private static final String QUERY_GET_LAST_TXN_ID = "txn.GetLastTxnId";
|
||||
private static final String QUERY_GET_LAST_TXN_ID_FOR_STORE = "txn.GetLastTxnIdForStore";
|
||||
private static final String QUERY_GET_TXN_UPDATE_COUNT_FOR_STORE = "txn.GetTxnUpdateCountForStore";
|
||||
private static final String QUERY_GET_TXN_DELETE_COUNT_FOR_STORE = "txn.GetTxnDeleteCountForStore";
|
||||
private static final String QUERY_COUNT_TRANSACTIONS = "txn.CountTransactions";
|
||||
private static final String QUERY_GET_NEXT_TXNS = "txn.GetNextTxns";
|
||||
private static final String QUERY_GET_NEXT_REMOTE_TXNS = "txn.GetNextRemoteTxns";
|
||||
private static final String QUERY_GET_TXN_CHANGES_FOR_STORE = "txn.GetTxnChangesForStore";
|
||||
private static final String QUERY_GET_TXN_CHANGES = "txn.GetTxnChanges";
|
||||
|
||||
public Transaction getTxnById(long txnId)
|
||||
{
|
||||
return (Transaction) getSession().get(TransactionImpl.class, new Long(txnId));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Transaction getLastTxn(final StoreRef storeRef)
|
||||
public Transaction getLastTxn()
|
||||
{
|
||||
HibernateCallback callback = new HibernateCallback()
|
||||
{
|
||||
public Object doInHibernate(Session session)
|
||||
{
|
||||
Query query = session.getNamedQuery(QUERY_GET_LAST_TXN_ID);
|
||||
query.setMaxResults(1)
|
||||
.setReadOnly(true);
|
||||
return query.uniqueResult();
|
||||
}
|
||||
};
|
||||
Long txnId = (Long) getHibernateTemplate().execute(callback);
|
||||
Transaction txn = null;
|
||||
if (txnId != null)
|
||||
{
|
||||
txn = (Transaction) getSession().get(TransactionImpl.class, txnId);
|
||||
}
|
||||
// done
|
||||
return txn;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Transaction getLastTxnForStore(final StoreRef storeRef)
|
||||
{
|
||||
HibernateCallback callback = new HibernateCallback()
|
||||
{
|
||||
@@ -1028,7 +1067,7 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public int getTxnUpdateCountForStore(final StoreRef storeRef, final long txnId)
|
||||
public int getTxnUpdateCount(final long txnId)
|
||||
{
|
||||
HibernateCallback callback = new HibernateCallback()
|
||||
{
|
||||
@@ -1036,9 +1075,6 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
|
||||
{
|
||||
Query query = session.getNamedQuery(QUERY_GET_TXN_UPDATE_COUNT_FOR_STORE);
|
||||
query.setLong("txnId", txnId)
|
||||
.setString("protocol", storeRef.getProtocol())
|
||||
.setString("identifier", storeRef.getIdentifier())
|
||||
.setMaxResults(1)
|
||||
.setReadOnly(true);
|
||||
return query.uniqueResult();
|
||||
}
|
||||
@@ -1049,7 +1085,7 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public int getTxnDeleteCountForStore(final StoreRef storeRef, final long txnId)
|
||||
public int getTxnDeleteCount(final long txnId)
|
||||
{
|
||||
HibernateCallback callback = new HibernateCallback()
|
||||
{
|
||||
@@ -1057,9 +1093,6 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
|
||||
{
|
||||
Query query = session.getNamedQuery(QUERY_GET_TXN_DELETE_COUNT_FOR_STORE);
|
||||
query.setLong("txnId", txnId)
|
||||
.setString("protocol", storeRef.getProtocol())
|
||||
.setString("identifier", storeRef.getIdentifier())
|
||||
.setMaxResults(1)
|
||||
.setReadOnly(true);
|
||||
return query.uniqueResult();
|
||||
}
|
||||
@@ -1088,14 +1121,12 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Transaction> getNextTxns(final Transaction lastTxn, final int count)
|
||||
public List<Transaction> getNextTxns(final long lastTxnId, final int count)
|
||||
{
|
||||
HibernateCallback callback = new HibernateCallback()
|
||||
{
|
||||
public Object doInHibernate(Session session)
|
||||
{
|
||||
long lastTxnId = (lastTxn == null) ? -1L : lastTxn.getId();
|
||||
|
||||
Query query = session.getNamedQuery(QUERY_GET_NEXT_TXNS);
|
||||
query.setLong("lastTxnId", lastTxnId)
|
||||
.setMaxResults(count)
|
||||
@@ -1108,6 +1139,26 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
|
||||
return results;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Transaction> getNextRemoteTxns(final long lastTxnId, final int count)
|
||||
{
|
||||
HibernateCallback callback = new HibernateCallback()
|
||||
{
|
||||
public Object doInHibernate(Session session)
|
||||
{
|
||||
Query query = session.getNamedQuery(QUERY_GET_NEXT_REMOTE_TXNS);
|
||||
query.setLong("lastTxnId", lastTxnId)
|
||||
.setString("serverIpAddress", ipAddress)
|
||||
.setMaxResults(count)
|
||||
.setReadOnly(true);
|
||||
return query.list();
|
||||
}
|
||||
};
|
||||
List<Transaction> results = (List<Transaction>) getHibernateTemplate().execute(callback);
|
||||
// done
|
||||
return results;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<NodeRef> getTxnChangesForStore(final StoreRef storeRef, final long txnId)
|
||||
{
|
||||
|
@@ -16,20 +16,30 @@
|
||||
*/
|
||||
package org.alfresco.repo.node.index;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.domain.Transaction;
|
||||
import org.alfresco.repo.node.db.NodeDaoService;
|
||||
import org.alfresco.repo.search.Indexer;
|
||||
import org.alfresco.repo.search.impl.lucene.LuceneQueryParser;
|
||||
import org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.transaction.TransactionComponent;
|
||||
import org.alfresco.repo.transaction.TransactionUtil;
|
||||
import org.alfresco.repo.transaction.TransactionUtil.TransactionWork;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef.Status;
|
||||
import org.alfresco.service.cmr.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchParameters;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.alfresco.util.VmShutdownListener;
|
||||
@@ -224,4 +234,229 @@ public abstract class AbstractReindexComponent implements IndexRecovery
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the last indexed transaction working back from the provided index.
|
||||
* This method can be used to hunt for a starting point for indexing of
|
||||
* transactions not yet in the index.
|
||||
*/
|
||||
protected long getLastIndexedTxn(long lastTxnId)
|
||||
{
|
||||
// get the last transaction
|
||||
long lastFoundTxnId = lastTxnId + 10L;
|
||||
boolean found = false;
|
||||
while (!found && lastFoundTxnId >= 0)
|
||||
{
|
||||
// reduce the transaction ID
|
||||
lastFoundTxnId = lastFoundTxnId - 10L;
|
||||
// break out as soon as we find a transaction that is in the index
|
||||
found = isTxnIdPresentInIndex(lastFoundTxnId);
|
||||
if (found)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Found last index txn before " + lastTxnId + ": " + lastFoundTxnId);
|
||||
}
|
||||
return lastFoundTxnId;
|
||||
}
|
||||
|
||||
protected boolean isTxnIdPresentInIndex(long txnId)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Checking for transaction in index: " + txnId);
|
||||
}
|
||||
|
||||
Transaction txn = nodeDaoService.getTxnById(txnId);
|
||||
if (txn == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// count the changes in the transaction
|
||||
int updateCount = nodeDaoService.getTxnUpdateCount(txnId);
|
||||
int deleteCount = nodeDaoService.getTxnDeleteCount(txnId);
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Transaction has " + updateCount + " updates and " + deleteCount + " deletes: " + txnId);
|
||||
}
|
||||
|
||||
// get the stores
|
||||
boolean found = false;
|
||||
List<StoreRef> storeRefs = nodeService.getStores();
|
||||
for (StoreRef storeRef : storeRefs)
|
||||
{
|
||||
boolean inStore = isTxnIdPresentInIndex(storeRef, txn, updateCount, deleteCount);
|
||||
if (inStore)
|
||||
{
|
||||
// found in a particular store
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Transaction " + txnId + " was " + (found ? "found" : "not found") + " in indexes.");
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns true if the given transaction is indexed in the in the
|
||||
*/
|
||||
private boolean isTxnIdPresentInIndex(StoreRef storeRef, Transaction txn, int updateCount, int deleteCount)
|
||||
{
|
||||
long txnId = txn.getId();
|
||||
String changeTxnId = txn.getChangeTxnId();
|
||||
// do the most update check, which is most common
|
||||
if (updateCount > 0)
|
||||
{
|
||||
ResultSet results = null;
|
||||
try
|
||||
{
|
||||
SearchParameters sp = new SearchParameters();
|
||||
sp.addStore(storeRef);
|
||||
// search for it in the index, sorting with youngest first, fetching only 1
|
||||
sp.setLanguage(SearchService.LANGUAGE_LUCENE);
|
||||
sp.setQuery("TX:" + LuceneQueryParser.escape(changeTxnId));
|
||||
sp.setLimit(1);
|
||||
|
||||
results = searcher.query(sp);
|
||||
|
||||
if (results.length() > 0)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Index has results for txn (OK): " + txnId);
|
||||
}
|
||||
return true; // there were updates/creates and results for the txn were found
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Index has no results for txn (Index out of date): " + txnId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (results != null) { results.close(); }
|
||||
}
|
||||
}
|
||||
// there have been deletes, so we have to ensure that none of the nodes deleted are present in the index
|
||||
// get all node refs for the transaction
|
||||
List<NodeRef> nodeRefs = nodeDaoService.getTxnChangesForStore(storeRef, txnId);
|
||||
for (NodeRef nodeRef : nodeRefs)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Searching for node in index: \n" +
|
||||
" node: " + nodeRef + "\n" +
|
||||
" txn: " + txnId);
|
||||
}
|
||||
// we know that these are all deletions
|
||||
ResultSet results = null;
|
||||
try
|
||||
{
|
||||
SearchParameters sp = new SearchParameters();
|
||||
sp.addStore(storeRef);
|
||||
// search for it in the index, sorting with youngest first, fetching only 1
|
||||
sp.setLanguage(SearchService.LANGUAGE_LUCENE);
|
||||
sp.setQuery("ID:" + LuceneQueryParser.escape(nodeRef.toString()));
|
||||
sp.setLimit(1);
|
||||
|
||||
results = searcher.query(sp);
|
||||
|
||||
if (results.length() == 0)
|
||||
{
|
||||
// no results, as expected
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(" --> Node not found (OK)");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(" --> Node found (Index out of date)");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (results != null) { results.close(); }
|
||||
}
|
||||
}
|
||||
|
||||
// all tests passed
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Index is in synch with transaction: " + txnId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a full reindexing of the given transaction in the context of a completely
|
||||
* new transaction.
|
||||
*
|
||||
* @param txnId the transaction identifier
|
||||
*/
|
||||
protected void reindexTransaction(final long txnId)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Reindexing transaction: " + txnId);
|
||||
}
|
||||
|
||||
TransactionWork<Object> reindexWork = new TransactionWork<Object>()
|
||||
{
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
// get the node references pertinent to the transaction
|
||||
List<NodeRef> nodeRefs = nodeDaoService.getTxnChanges(txnId);
|
||||
// reindex each node
|
||||
for (NodeRef nodeRef : nodeRefs)
|
||||
{
|
||||
Status nodeStatus = nodeService.getNodeStatus(nodeRef);
|
||||
if (nodeStatus == null)
|
||||
{
|
||||
// it's not there any more
|
||||
continue;
|
||||
}
|
||||
if (nodeStatus.isDeleted()) // node deleted
|
||||
{
|
||||
// only the child node ref is relevant
|
||||
ChildAssociationRef assocRef = new ChildAssociationRef(
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
null,
|
||||
null,
|
||||
nodeRef);
|
||||
indexer.deleteNode(assocRef);
|
||||
}
|
||||
else // node created
|
||||
{
|
||||
// get the primary assoc for the node
|
||||
ChildAssociationRef primaryAssocRef = nodeService.getPrimaryParent(nodeRef);
|
||||
// reindex
|
||||
indexer.createNode(primaryAssocRef);
|
||||
}
|
||||
}
|
||||
// done
|
||||
return null;
|
||||
}
|
||||
};
|
||||
TransactionUtil.executeInNonPropagatingUserTransaction(transactionService, reindexWork, true);
|
||||
// done
|
||||
}
|
||||
}
|
@@ -21,27 +21,25 @@ import java.util.List;
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.domain.Transaction;
|
||||
import org.alfresco.repo.search.impl.lucene.LuceneQueryParser;
|
||||
import org.alfresco.repo.transaction.TransactionUtil;
|
||||
import org.alfresco.repo.transaction.TransactionUtil.TransactionWork;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef.Status;
|
||||
import org.alfresco.service.cmr.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchParameters;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Component to check and recover the indexes.
|
||||
* Component to check and recover the indexes. By default, the server is
|
||||
* put into read-only mode during the reindex process in order to prevent metadata changes.
|
||||
* This is not critical and can be {@link #setLockServer(boolean) switched off} if the
|
||||
* server is required immediately.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
*/
|
||||
public class FullIndexRecoveryComponent extends AbstractReindexComponent
|
||||
{
|
||||
private static final String ERR_STORE_NOT_UP_TO_DATE = "index.recovery.store_not_up_to_date";
|
||||
private static final String ERR_INDEX_OUT_OF_DATE = "index.recovery.out_of_date";
|
||||
private static final String MSG_RECOVERY_STARTING = "index.recovery.starting";
|
||||
private static final String MSG_RECOVERY_COMPLETE = "index.recovery.complete";
|
||||
private static final String MSG_RECOVERY_PROGRESS = "index.recovery.progress";
|
||||
@@ -51,17 +49,25 @@ public class FullIndexRecoveryComponent extends AbstractReindexComponent
|
||||
|
||||
public static enum RecoveryMode
|
||||
{
|
||||
/** Do nothing - not even a check */
|
||||
/** Do nothing - not even a check. */
|
||||
NONE,
|
||||
/** Perform a quick check on the state of the indexes only */
|
||||
/**
|
||||
* Perform a quick check on the state of the indexes only.
|
||||
*/
|
||||
VALIDATE,
|
||||
/** Performs a quick validation and then starts a full pass-through on failure */
|
||||
/**
|
||||
* Performs a validation and starts a quick recovery, if necessary.
|
||||
*/
|
||||
AUTO,
|
||||
/** Performs a full pass-through of all recorded transactions to ensure that the indexes are up to date */
|
||||
/**
|
||||
* Performs a full pass-through of all recorded transactions to ensure that the indexes
|
||||
* are up to date.
|
||||
*/
|
||||
FULL;
|
||||
}
|
||||
|
||||
private RecoveryMode recoveryMode;
|
||||
private boolean lockServer;
|
||||
|
||||
public FullIndexRecoveryComponent()
|
||||
{
|
||||
@@ -69,7 +75,8 @@ public class FullIndexRecoveryComponent extends AbstractReindexComponent
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type of recovery to perform.
|
||||
* Set the type of recovery to perform. Default is {@link RecoveryMode#VALIDATE to validate}
|
||||
* the indexes only.
|
||||
*
|
||||
* @param recoveryMode one of the {@link RecoveryMode } values
|
||||
*/
|
||||
@@ -78,6 +85,17 @@ public class FullIndexRecoveryComponent extends AbstractReindexComponent
|
||||
this.recoveryMode = RecoveryMode.valueOf(recoveryMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this on to put the server into READ-ONLY mode for the duration of the index recovery.
|
||||
* The default is <tt>true</tt>, i.e. the server will be locked against further updates.
|
||||
*
|
||||
* @param lockServer true to force the server to be read-only
|
||||
*/
|
||||
public void setLockServer(boolean lockServer)
|
||||
{
|
||||
this.lockServer = lockServer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reindexImpl()
|
||||
{
|
||||
@@ -99,25 +117,22 @@ public class FullIndexRecoveryComponent extends AbstractReindexComponent
|
||||
}
|
||||
else // validate first
|
||||
{
|
||||
List<StoreRef> storeRefs = nodeService.getStores();
|
||||
for (StoreRef storeRef : storeRefs)
|
||||
Transaction txn = nodeDaoService.getLastTxn();
|
||||
if (txn == null)
|
||||
{
|
||||
// get the last txn ID in the database
|
||||
Transaction txn = nodeDaoService.getLastTxn(storeRef);
|
||||
boolean lastChangeTxnIdInIndex = isTxnIdPresentInIndex(storeRef, txn);
|
||||
if (lastChangeTxnIdInIndex)
|
||||
{
|
||||
// this store is good
|
||||
continue;
|
||||
}
|
||||
// this store isn't up to date
|
||||
String msg = I18NUtil.getMessage(ERR_STORE_NOT_UP_TO_DATE, storeRef);
|
||||
// no transactions - just bug out
|
||||
return;
|
||||
}
|
||||
long txnId = txn.getId();
|
||||
boolean txnInIndex = isTxnIdPresentInIndex(txnId);
|
||||
if (!txnInIndex)
|
||||
{
|
||||
String msg = I18NUtil.getMessage(ERR_INDEX_OUT_OF_DATE);
|
||||
logger.warn(msg);
|
||||
// the store is out of date - validation failed
|
||||
// this store isn't up to date
|
||||
if (recoveryMode == RecoveryMode.VALIDATE)
|
||||
{
|
||||
// next store
|
||||
continue;
|
||||
// the store is out of date - validation failed
|
||||
}
|
||||
else if (recoveryMode == RecoveryMode.AUTO)
|
||||
{
|
||||
@@ -130,8 +145,11 @@ public class FullIndexRecoveryComponent extends AbstractReindexComponent
|
||||
boolean allowWrite = !transactionService.isReadOnly();
|
||||
try
|
||||
{
|
||||
// set the server into read-only mode
|
||||
transactionService.setAllowWrite(false);
|
||||
if (lockServer)
|
||||
{
|
||||
// set the server into read-only mode
|
||||
transactionService.setAllowWrite(false);
|
||||
}
|
||||
|
||||
// do we need to perform a full recovery
|
||||
if (fullRecoveryRequired)
|
||||
@@ -160,8 +178,9 @@ public class FullIndexRecoveryComponent extends AbstractReindexComponent
|
||||
Transaction lastTxn = null;
|
||||
while(true)
|
||||
{
|
||||
long lastTxnId = (lastTxn == null) ? -1L : lastTxn.getId().longValue();
|
||||
List<Transaction> nextTxns = nodeDaoService.getNextTxns(
|
||||
lastTxn,
|
||||
lastTxnId,
|
||||
MAX_TRANSACTIONS_PER_ITERATION);
|
||||
|
||||
// reindex each transaction
|
||||
@@ -256,125 +275,4 @@ public class FullIndexRecoveryComponent extends AbstractReindexComponent
|
||||
TransactionUtil.executeInNonPropagatingUserTransaction(transactionService, reindexWork, true);
|
||||
// done
|
||||
}
|
||||
|
||||
private boolean isTxnIdPresentInIndex(StoreRef storeRef, Transaction txn)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Checking for transaction in index: \n" +
|
||||
" store: " + storeRef + "\n" +
|
||||
" txn: " + txn);
|
||||
}
|
||||
|
||||
String changeTxnId = txn.getChangeTxnId();
|
||||
// count the changes in the transaction
|
||||
int updateCount = nodeDaoService.getTxnUpdateCountForStore(storeRef, txn.getId());
|
||||
int deleteCount = nodeDaoService.getTxnDeleteCountForStore(storeRef, txn.getId());
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Transaction has " + updateCount + " updates and " + deleteCount + " deletes: " + txn);
|
||||
}
|
||||
|
||||
// do the most update check, which is most common
|
||||
if (deleteCount == 0 && updateCount == 0)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("No changes in transaction: " + txn);
|
||||
}
|
||||
// there's nothing to check for
|
||||
return true;
|
||||
}
|
||||
else if (updateCount > 0)
|
||||
{
|
||||
ResultSet results = null;
|
||||
try
|
||||
{
|
||||
SearchParameters sp = new SearchParameters();
|
||||
sp.addStore(storeRef);
|
||||
// search for it in the index, sorting with youngest first, fetching only 1
|
||||
sp.setLanguage(SearchService.LANGUAGE_LUCENE);
|
||||
sp.setQuery("TX:" + LuceneQueryParser.escape(changeTxnId));
|
||||
sp.setLimit(1);
|
||||
|
||||
results = searcher.query(sp);
|
||||
|
||||
if (results.length() > 0)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Index has results for txn (OK): " + txn);
|
||||
}
|
||||
return true; // there were updates/creates and results for the txn were found
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Index has no results for txn (Index out of date): " + txn);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (results != null) { results.close(); }
|
||||
}
|
||||
}
|
||||
// there have been deletes, so we have to ensure that none of the nodes deleted are present in the index
|
||||
// get all node refs for the transaction
|
||||
Long txnId = txn.getId();
|
||||
List<NodeRef> nodeRefs = nodeDaoService.getTxnChangesForStore(storeRef, txnId);
|
||||
for (NodeRef nodeRef : nodeRefs)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Searching for node in index: \n" +
|
||||
" node: " + nodeRef + "\n" +
|
||||
" txn: " + txn);
|
||||
}
|
||||
// we know that these are all deletions
|
||||
ResultSet results = null;
|
||||
try
|
||||
{
|
||||
SearchParameters sp = new SearchParameters();
|
||||
sp.addStore(storeRef);
|
||||
// search for it in the index, sorting with youngest first, fetching only 1
|
||||
sp.setLanguage(SearchService.LANGUAGE_LUCENE);
|
||||
sp.setQuery("ID:" + LuceneQueryParser.escape(nodeRef.toString()));
|
||||
sp.setLimit(1);
|
||||
|
||||
results = searcher.query(sp);
|
||||
|
||||
if (results.length() == 0)
|
||||
{
|
||||
// no results, as expected
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(" --> Node not found (OK)");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(" --> Node found (Index out of date)");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (results != null) { results.close(); }
|
||||
}
|
||||
}
|
||||
|
||||
// all tests passed
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Index is in synch with transaction: " + txn);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user