Merge from HEAD to WCM-DEV2.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3659 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Britt Park
2006-09-02 18:19:00 +00:00
parent db3c29b45e
commit 820da6ecab
147 changed files with 9873 additions and 1289 deletions

View File

@@ -355,7 +355,7 @@
</property>
</bean>
<bean id="script" class="org.alfresco.repo.action.executer.ScriptActionExecutor" parent="action-executer">
<bean id="script" class="org.alfresco.repo.action.executer.ScriptActionExecuter" parent="action-executer">
<property name="serviceRegistry">
<ref bean="ServiceRegistry" />
</property>
@@ -370,6 +370,12 @@
</property>
</bean>
<bean id="counter" class="org.alfresco.repo.action.executer.CounterIncrementActionExecuter" parent="action-executer">
<property name="nodeService">
<ref bean="nodeService" /> <!-- runtime nodeService -->
</property>
</bean>
<bean id="execute-all-rules" class="org.alfresco.repo.action.executer.ExecuteAllRulesActionExecuter" parent="action-executer">
<property name="nodeService">
<ref bean="NodeService" />

View File

@@ -24,8 +24,10 @@
<import resource="classpath:alfresco/import-export-context.xml" />
<import resource="classpath:alfresco/workflow-context.xml" />
<import resource="classpath:alfresco/bootstrap-context.xml" />
<import resource="classpath:alfresco/workflow-context.xml" />
<import resource="classpath:alfresco/jcr-api-context.xml" />
<import resource="classpath:alfresco/avm-services-context.xml" />
<import resource="classpath:alfresco/audit-services-context.xml" />
<import resource="classpath*:alfresco/patch/*-context.xml" />
<import resource="classpath*:alfresco/domain/*-context.xml" />

View File

@@ -0,0 +1,87 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<!-- Base audit service - non TX -->
<bean id="auditService" class="org.alfresco.repo.audit.AuditServiceImpl">
<property name="auditComponent">
<ref bean="auditComponent"/>
</property>
</bean>
<!-- Audit component -->
<bean id="auditComponent" class="org.alfresco.repo.audit.AuditComponentImpl">
<property name="publicServiceIdentifier">
<ref bean="publicServiceIdentifier"/>
</property>
<property name="auditDAO">
<ref bean="auditDao"/>
</property>
<property name="auditFailedDAO">
<ref bean="auditFailedDao"/>
</property>
<property name="auditConfiguration">
<ref bean="auditConfiguration"/>
</property>
<property name="auditModel">
<ref bean="auditModel"/>
</property>
</bean>
<!-- Public service idntifier -->
<bean id="publicServiceIdentifier" class="org.alfresco.repo.audit.PublicServiceIdentifierImpl"/>
<!-- The configuration of the audit model -->
<bean id="auditConfiguration" class="org.alfresco.repo.audit.AuditConfigurationImpl">
<property name="config">
<value>alfresco/auditConfig.xml</value>
</property>
</bean>
<!-- The content store in which to store audit information -->
<bean id="auditFileContentStore" class="org.alfresco.repo.content.filestore.FileContentStore">
<constructor-arg>
<value>${dir.auditcontentstore}</value>
</constructor-arg>
</bean>
<!-- The audit model -->
<bean id="auditModel" class="org.alfresco.repo.audit.model.AuditEntry">
<property name="auditConfiguration">
<ref bean="auditConfiguration"/>
</property>
<property name="namespacePrefixResolver">
<ref bean="namespaceService"/>
</property>
<property name="publicServiceIdentifier">
<ref bean="publicServiceIdentifier"/>
</property>
</bean>
<!-- The audit DAO wapped to use another TX so we can log exceptions -->
<bean id='auditFailedDao' class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.repo.audit.AuditDAO</value>
</property>
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="target">
<ref bean="auditDao" />
</property>
<property name="transactionAttributes">
<props>
<prop key="*">${server.transaction.mode.default}, PROPAGATION_REQUIRES_NEW</prop>
</props>
</property>
</bean>
</beans>

View File

@@ -3,7 +3,7 @@
<!-- Default Audit Configuration -->
<Audit xmlns="http://www.alfresco.org/model/audit/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" enabled="true" auditInternal="false" mode="all">
<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">
<!-- -->
<!-- Global options -->
@@ -174,7 +174,7 @@
<Service name="LicenseService" mode="none" enabled="false"/>
<Service name="NamespaceService"/>
<Service name="NamespaceService" mode="none" enabled="false"/>
<Service name="TransactionService" mode="none" enabled="false"/>

View File

@@ -32,7 +32,9 @@
<!-- Abstract Filter entry -->
<xs:complexType name="Filter" abstract="true"/>
<xs:complexType name="Filter" abstract="true">
<xs:attribute name="invert" type="xs:boolean" default="false"/>
</xs:complexType>
<!-- Simple Filter entry -->
<!--
@@ -47,17 +49,17 @@
A simple value (intended for use with non node arguments)
-->
<xs:simpleType name="KeyFilterType">
<xs:simpleType name="KeyFilterMode">
<xs:restriction base="xs:string">
<xs:enumeration value="path"/>
<xs:enumeration value="type"/>
<xs:enumeration value="aspect"/>
<xs:enumeration value="id"/>
<xs:enumeration value="node_ref"/>
<xs:enumeration value="all"/>
<xs:enumeration value="xpath"/>
<xs:enumeration value="value"/>
<xs:enumeration value="protocol"/>
<xs:enumeration value="store"/>
<xs:enumeration value="store_protocol"/>
<xs:enumeration value="store_identifier"/>
</xs:restriction>
</xs:simpleType>
@@ -102,7 +104,7 @@
<xs:sequence>
<xs:element name="Expression" type="xs:string"/>
</xs:sequence>
<xs:attribute name="type" type="a:KeyFilterType" use="required"/>
<xs:attribute name="mode" type="a:KeyFilterMode" use="required"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
@@ -196,6 +198,7 @@
<xs:extension base="a:MandatoryAuditEntry">
<xs:sequence>
<xs:element name="Service" type="a:Service" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Application" type="a:Application" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>

View File

@@ -25,6 +25,31 @@
<beans>
<!-- ensure that the schema is bootstrapped -->
<bean id="schemaBootstrap" class="org.alfresco.repo.domain.schema.SchemaBootstrap" >
<property name="localSessionFactory">
<ref bean="&amp;sessionFactory"></ref> <!-- inject the actual factory, not a session -->
</property>
<property name="updateSchema">
<value>${db.schema.update}</value>
</property>
<property name="postCreateScriptUrls">
<list>
<value>classpath:alfresco/dbscripts/create/1.4/${db.script.dialect}/sample.sql</value>
</list>
</property>
<property name="validateUpdateScriptPatches">
<list>
</list>
</property>
<property name="applyUpdateScriptPatches">
<list>
<ref bean="patch.schemaUpdateScript-V1.4-1" />
<ref bean="patch.schemaUpdateScript-V1.4-2" />
</list>
</property>
</bean>
<!-- Bootstrap Files -->
<bean id="systemInfoBootstrap" parent="systemInfoImporter">

View File

@@ -13,7 +13,7 @@
<!-- EH Cache Manager to produce in-transaction EH Caches -->
<!-- ==================================================== -->
<bean name="transactionalEHCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" >
<bean name="transactionalEHCacheManager" class="org.alfresco.repo.cache.EhCacheManagerFactoryBean" >
<property name="configLocation">
<value>classpath:alfresco/ehcache-transactional.xml</value>
</property>

View File

@@ -60,9 +60,6 @@
</property>
</bean>
<!-- use around method calls to debug - see class comments for details -->
<bean id="methodCallLogAdvice" class="org.alfresco.util.debug.MethodCallLogAdvice" />
<!-- -->
<!-- I18N -->
<!-- -->
@@ -79,6 +76,7 @@
<value>alfresco.messages.template-service</value>
<value>alfresco.messages.lock-service</value>
<value>alfresco.messages.patch-service</value>
<value>alfresco.messages.schema-update</value>
<value>alfresco.messages.webdav-messages</value>
</list>
</property>

View File

@@ -0,0 +1,4 @@
--
-- Insert post-creation scripts here
-- This is a generic fallback for cases where specific dialects are not catered for
--

View File

@@ -0,0 +1,4 @@
--
-- Insert post-creation scripts here
-- This is specific to the dialect described in the path to the file
--

View File

@@ -0,0 +1,653 @@
-- ------------------------------------------------------
-- Alfresco Schema conversion V1.2.1 to V1.3
--
-- Author: Derek Hulley
-- ------------------------------------------------------
--
-- Create temporary 1.3 schema
--
CREATE TABLE `T_access_control_entry` (
`id` bigint(20) NOT NULL auto_increment,
`protocol` varchar(50) default NULL,
`identifier` varchar(100) default NULL,
`uuid` varchar(36) default NULL,
`typeUri` varchar(100) default NULL,
`typeName` varchar(100) default NULL,
`name` varchar(100) default NULL,
`recipient` varchar(100) default NULL,
`acl_id` bigint(20),
`permission_id` bigint(20),
`authority_id` varchar(100),
`allowed` bit(1) NOT NULL,
PRIMARY KEY (`id`)
);
ALTER TABLE `T_access_control_entry` ADD INDEX `IDX_REF`(`protocol`, `identifier`, `uuid`);
CREATE TABLE `T_access_control_list` (
`id` bigint(20) NOT NULL auto_increment,
`protocol` varchar(50) NOT NULL,
`identifier` varchar(100) NOT NULL,
`uuid` varchar(36) NOT NULL,
`inherits` bit(1) NOT NULL,
PRIMARY KEY (`id`)
);
ALTER TABLE `T_access_control_list` ADD INDEX `IDX_REF`(`protocol`, `identifier`, `uuid`);
CREATE TABLE `T_applied_patch` (
`id` varchar(32) NOT NULL,
`description` text,
`fixes_from_schema` int(11) default NULL,
`fixes_to_schema` int(11) default NULL,
`applied_to_schema` int(11) default NULL,
`target_schema` int(11) default NULL,
`applied_on_date` datetime default NULL,
`applied_to_server` varchar(64) default NULL,
`was_executed` bit(1) default NULL,
`succeeded` bit(1) default NULL,
`report` text
);
CREATE TABLE `T_auth_ext_keys` (
`id` varchar(100) NOT NULL,
`externalKey` varchar(100) NOT NULL
);
CREATE TABLE `T_authority` (
`recipient` varchar(100) NOT NULL
);
CREATE TABLE `T_child_assoc` (
`id` bigint(20) NOT NULL auto_increment,
`parent_node_id` bigint(20) default NULL,
`parent_protocol` varchar(50) default NULL,
`parent_identifier` varchar(100) default NULL,
`parent_uuid` varchar(36) default NULL,
`child_node_id` bigint(20) default NULL,
`child_protocol` varchar(50) default NULL,
`child_identifier` varchar(100) default NULL,
`child_uuid` varchar(36) default NULL,
`type_qname` varchar(255) NOT NULL,
`qname` varchar(255) NOT NULL,
`is_primary` bit(1) default NULL,
`assoc_index` int(11) default NULL,
PRIMARY KEY (`id`)
);
ALTER TABLE `T_child_assoc` ADD INDEX `IDX_REF_PARENT`(`parent_protocol`, `parent_identifier`, `parent_uuid`);
ALTER TABLE `T_child_assoc` ADD INDEX `IDX_REF_CHILD`(`child_protocol`, `child_identifier`, `child_uuid`);
CREATE TABLE `T_node` (
`id` bigint(20) NOT NULL auto_increment,
`protocol` varchar(50) NOT NULL,
`identifier` varchar(100) NOT NULL,
`uuid` varchar(36) NOT NULL,
`acl_id` bigint(20) default NULL,
`type_qname` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
);
ALTER TABLE `T_node` ADD INDEX `IDX_REF`(`protocol`, `identifier`, `uuid`);
CREATE TABLE `T_node_aspects` (
`protocol` varchar(50) NOT NULL,
`identifier` varchar(100) NOT NULL,
`uuid` varchar(36) NOT NULL,
`node_id` bigint(20),
`qname` varchar(200) default NULL
);
ALTER TABLE `T_node_aspects` ADD INDEX `IDX_REF`(`protocol`, `identifier`, `uuid`);
CREATE TABLE `T_node_assoc` (
`id` bigint(20) NOT NULL auto_increment,
`source_node_id` bigint(20) default NULL,
`source_protocol` varchar(50) default NULL,
`source_identifier` varchar(100) default NULL,
`source_uuid` varchar(36) default NULL,
`target_node_id` bigint(20) default NULL,
`target_protocol` varchar(50) default NULL,
`target_identifier` varchar(100) default NULL,
`target_uuid` varchar(36) default NULL,
`type_qname` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
);
ALTER TABLE `T_node_assoc` ADD INDEX `IDX_REF_SOURCE`(`source_protocol`, `source_identifier`, `source_uuid`);
ALTER TABLE `T_node_assoc` ADD INDEX `IDX_REF_TARGET`(`target_protocol`, `target_identifier`, `target_uuid`);
CREATE TABLE `T_node_properties` (
`protocol` varchar(50) NOT NULL,
`identifier` varchar(100) NOT NULL,
`uuid` varchar(36) NOT NULL,
`node_id` bigint(20),
`actual_type` varchar(15) NOT NULL,
`multi_valued` bit(1) NOT NULL,
`persisted_type` varchar(15) NOT NULL,
`boolean_value` bit(1) default NULL,
`long_value` bigint(20) default NULL,
`float_value` float default NULL,
`double_value` double default NULL,
`string_value` text,
`serializable_value` blob,
`qname` varchar(200) NOT NULL
);
ALTER TABLE `t_node_properties` ADD INDEX `IDX_REF`(`protocol`, `identifier`, `uuid`);
CREATE TABLE `T_node_status` (
`protocol` varchar(50) NOT NULL,
`identifier` varchar(100) NOT NULL,
`guid` varchar(36) NOT NULL,
`node_id` bigint(20) default NULL,
`change_txn_id` varchar(56) NOT NULL,
`deleted` bit(1) NOT NULL
);
ALTER TABLE `t_node_status` ADD INDEX `IDX_REF`(`protocol`, `identifier`, `guid`);
CREATE TABLE `T_permission` (
`id` bigint(20) NOT NULL auto_increment,
`type_qname` varchar(200) NOT NULL,
`name` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `T_store` (
`protocol` varchar(50) NOT NULL,
`identifier` varchar(100) NOT NULL,
`root_node_id` bigint(20) default NULL
);
ALTER TABLE `t_store` ADD INDEX `IDX_STORE_REF`(`protocol`, `identifier`);
CREATE TABLE `T_version_count` (
`protocol` varchar(50) NOT NULL,
`identifier` varchar(100) NOT NULL,
`version_count` int(11) NOT NULL
);
--
-- Copy data from old tables to intermediate tables
--
insert into T_store (protocol, identifier)
select protocol, identifier from store;
insert into T_node (protocol, identifier, uuid, type_qname)
select protocol, identifier, guid, type_qname from node;
update T_store tstore set root_node_id =
(select tnode.id from T_node tnode where
tnode.protocol = tstore.protocol and
tnode.identifier = tstore.identifier and
tnode.uuid =
(select ostore.root_guid from store ostore where
ostore.protocol = tstore.protocol and
ostore.identifier = tstore.identifier
)
);
insert into t_version_count (protocol, identifier, version_count)
select protocol, identifier, version_count from version_count;
insert into t_node_status (protocol, identifier, guid, change_txn_id, deleted)
select protocol, identifier, guid, change_txn_id, deleted from node_status;
update T_node_status tstatus set node_id =
(select tnode.id from T_node tnode where
tnode.protocol = tstatus.protocol and
tnode.identifier = tstatus.identifier and
tnode.uuid = tstatus.guid
);
insert into T_node_properties
(
protocol, identifier, uuid, actual_type, multi_valued, persisted_type,
boolean_value, long_value, float_value, double_value, string_value, serializable_value, qname
)
select
protocol, identifier, guid, actual_type, multi_valued, persisted_type,
boolean_value, long_value, float_value, double_value, string_value, serializable_value, qname
from node_properties;
update T_node_properties tproperties set node_id =
(select tnode.id from T_node tnode where
tnode.protocol = tproperties.protocol and
tnode.identifier = tproperties.identifier and
tnode.uuid = tproperties.uuid
);
insert into T_node_aspects
(
protocol, identifier, uuid, qname
)
select
protocol, identifier, guid, qname
from node_aspects;
update T_node_aspects taspects set node_id =
(select tnode.id from T_node tnode where
tnode.protocol = taspects.protocol and
tnode.identifier = taspects.identifier and
tnode.uuid = taspects.uuid
);
insert into T_child_assoc
(
parent_protocol, parent_identifier, parent_uuid,
child_protocol, child_identifier, child_uuid,
type_qname, qname, is_primary, assoc_index
)
select
parent_protocol, parent_identifier, parent_guid,
child_protocol, child_identifier, child_guid,
type_qname, qname, isPrimary, assoc_index
from
child_assoc;
update T_child_assoc tassoc set parent_node_id =
(select tnode.id from T_node tnode where
tnode.protocol = tassoc.parent_protocol and
tnode.identifier = tassoc.parent_identifier and
tnode.uuid = tassoc.parent_uuid
);
update T_child_assoc tassoc set child_node_id =
(select tnode.id from T_node tnode where
tnode.protocol = tassoc.child_protocol and
tnode.identifier = tassoc.child_identifier and
tnode.uuid = tassoc.child_uuid
);
insert into T_node_assoc
(
source_protocol, source_identifier, source_uuid,
target_protocol, target_identifier, target_uuid,
type_qname
)
select
source_protocol, source_identifier, source_guid,
target_protocol, target_identifier, target_guid,
type_qname
from
node_assoc;
update T_node_assoc tassoc set source_node_id =
(select tnode.id from T_node tnode where
tnode.protocol = tassoc.source_protocol and
tnode.identifier = tassoc.source_identifier and
tnode.uuid = tassoc.source_uuid
);
update T_node_assoc tassoc set target_node_id =
(select tnode.id from T_node tnode where
tnode.protocol = tassoc.target_protocol and
tnode.identifier = tassoc.target_identifier and
tnode.uuid = tassoc.target_uuid
);
insert into T_permission
(
type_qname, name
)
select
CONCAT('{', type_uri, '}', type_name), name
from
permission_ref;
insert into T_access_control_list
(
protocol, identifier, uuid, inherits
)
select
protocol, identifier, guid, inherits
from node_permission;
update T_node tnode set acl_id =
(select tacl.id from T_access_control_list tacl where
tacl.protocol = tnode.protocol and
tacl.identifier = tnode.identifier and
tacl.uuid = tnode.uuid
);
insert into T_auth_ext_keys
(
id, externalKey
)
select
id, externalKey
from
externalkeys;
insert into T_authority
(
recipient
)
select
recipient
from
recipient;
insert into T_access_control_entry
(
protocol, identifier, uuid,
typeUri, typeName, name,
recipient,
allowed
)
select
protocol, identifier, guid,
typeUri, typeName, name,
recipient,
allowed
from node_perm_entry;
update T_access_control_entry tentry
set
acl_id =
(
select
tacl.id
from T_access_control_list tacl
join T_node tnode on tacl.id = tnode.acl_id
where
tnode.protocol = tentry.protocol and
tnode.identifier = tentry.identifier and
tnode.uuid = tentry.uuid
);
update T_access_control_entry tentry
set
tentry.permission_id =
(
select
tpermission.id
from T_permission tpermission
where
tpermission.type_qname = CONCAT('{', tentry.typeUri, '}', tentry.typeName) and
tpermission.name = tentry.name
);
update T_access_control_entry tentry
set
tentry.authority_id =
(
select
tauthority.recipient
from T_authority tauthority
where
tauthority.recipient = tentry.recipient
);
delete from T_access_control_list where id not in (select distinct(acl_id) id from t_access_control_entry where acl_id is not null);
delete from T_access_control_entry where acl_id is null;
update T_node set acl_id = null where acl_id not in (select id from t_access_control_list);
--
-- Create New schema (MySQL)
--
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE child_assoc;
DROP TABLE node_assoc;
DROP TABLE node_properties;
DROP TABLE node_aspects;
DROP TABLE node;
DROP TABLE node_status;
DROP TABLE version_count;
DROP TABLE store;
DROP TABLE node_perm_entry;
DROP TABLE node_permission;
DROP TABLE permission_ref;
DROP TABLE recipient;
DROP TABLE externalKeys;
CREATE TABLE `access_control_entry` (
`id` bigint(20) NOT NULL auto_increment,
`acl_id` bigint(20) NOT NULL,
`permission_id` bigint(20) NOT NULL,
`authority_id` varchar(100) NOT NULL,
`allowed` bit(1) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `acl_id` (`acl_id`,`permission_id`,`authority_id`),
KEY `FKF064DF7560601995` (`permission_id`),
KEY `FKF064DF75B25A50BF` (`authority_id`),
KEY `FKF064DF75B9553F6C` (`acl_id`),
CONSTRAINT `FKF064DF75B9553F6C` FOREIGN KEY (`acl_id`) REFERENCES `access_control_list` (`id`),
CONSTRAINT `FKF064DF7560601995` FOREIGN KEY (`permission_id`) REFERENCES `permission` (`id`),
CONSTRAINT `FKF064DF75B25A50BF` FOREIGN KEY (`authority_id`) REFERENCES `authority` (`recipient`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `access_control_list` (
`id` bigint(20) NOT NULL auto_increment,
`inherits` bit(1) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `auth_ext_keys` (
`id` varchar(100) NOT NULL,
`externalKey` varchar(100) NOT NULL,
PRIMARY KEY (`id`,`externalKey`),
KEY `FK31D3BA097B7FDE43` (`id`),
CONSTRAINT `FK31D3BA097B7FDE43` FOREIGN KEY (`id`) REFERENCES `authority` (`recipient`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `authority` (
`recipient` varchar(100) NOT NULL,
PRIMARY KEY (`recipient`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `child_assoc` (
`id` bigint(20) NOT NULL auto_increment,
`parent_node_id` bigint(20) default NULL,
`child_node_id` bigint(20) default NULL,
`type_qname` varchar(255) NOT NULL,
`qname` varchar(255) NOT NULL,
`is_primary` bit(1) default NULL,
`assoc_index` int(11) default NULL,
PRIMARY KEY (`id`),
KEY `FKFFC5468E74173FF4` (`child_node_id`),
KEY `FKFFC5468E8E50E582` (`parent_node_id`),
CONSTRAINT `FKFFC5468E8E50E582` FOREIGN KEY (`parent_node_id`) REFERENCES `node` (`id`),
CONSTRAINT `FKFFC5468E74173FF4` FOREIGN KEY (`child_node_id`) REFERENCES `node` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
FKFFC5468E74173FF4
CREATE TABLE `node` (
`id` bigint(20) NOT NULL auto_increment,
`protocol` varchar(50) NOT NULL,
`identifier` varchar(100) NOT NULL,
`uuid` varchar(36) NOT NULL,
`type_qname` varchar(255) NOT NULL,
`acl_id` bigint(20) default NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `protocol` (`protocol`,`identifier`,`uuid`),
KEY `FK33AE02D24ADD25` (`protocol`,`identifier`),
CONSTRAINT `FK33AE02D24ADD25` FOREIGN KEY (`protocol`, `identifier`) REFERENCES `store` (`protocol`, `identifier`),
CONSTRAINT `FK33AE02B9553F6C` FOREIGN KEY (`acl_id`) REFERENCES `access_control_list` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `node_aspects` (
`node_id` bigint(20) NOT NULL,
`qname` varchar(200) default NULL,
KEY `FK2B91A9DE7F2C8017` (`node_id`),
CONSTRAINT `FK2B91A9DE7F2C8017` FOREIGN KEY (`node_id`) REFERENCES `node` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `node_assoc` (
`id` bigint(20) NOT NULL auto_increment,
`source_node_id` bigint(20) default NULL,
`target_node_id` bigint(20) default NULL,
`type_qname` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `FK5BAEF398B69C43F3` (`source_node_id`),
KEY `FK5BAEF398A8FC7769` (`target_node_id`),
CONSTRAINT `FK5BAEF398A8FC7769` FOREIGN KEY (`target_node_id`) REFERENCES `node` (`id`),
CONSTRAINT `FK5BAEF398B69C43F3` FOREIGN KEY (`source_node_id`) REFERENCES `node` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `node_properties` (
`node_id` bigint(20) NOT NULL,
`actual_type` varchar(15) NOT NULL,
`multi_valued` bit(1) NOT NULL,
`persisted_type` varchar(15) NOT NULL,
`boolean_value` bit(1) default NULL,
`long_value` bigint(20) default NULL,
`float_value` float default NULL,
`double_value` double default NULL,
`string_value` text,
`serializable_value` blob,
`qname` varchar(200) NOT NULL,
PRIMARY KEY (`node_id`,`qname`),
KEY `FKC962BF907F2C8017` (`node_id`),
CONSTRAINT `FKC962BF907F2C8017` FOREIGN KEY (`node_id`) REFERENCES `node` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `node_status` (
`protocol` varchar(50) NOT NULL,
`identifier` varchar(100) NOT NULL,
`guid` varchar(36) NOT NULL,
`node_id` bigint(20) default NULL,
`change_txn_id` varchar(56) NOT NULL,
PRIMARY KEY (`protocol`,`identifier`,`guid`),
KEY `FK38ECB8CF7F2C8017` (`node_id`),
CONSTRAINT `FK38ECB8CF7F2C8017` FOREIGN KEY (`node_id`) REFERENCES `node` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `permission` (
`id` bigint(20) NOT NULL auto_increment,
`type_qname` varchar(200) NOT NULL,
`name` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `type_qname` (`type_qname`,`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `store` (
`protocol` varchar(50) NOT NULL,
`identifier` varchar(100) NOT NULL,
`root_node_id` bigint(20) default NULL,
PRIMARY KEY (`protocol`,`identifier`),
KEY `FK68AF8E122DBA5BA` (`root_node_id`),
CONSTRAINT `FK68AF8E122DBA5BA` FOREIGN KEY (`root_node_id`) REFERENCES `node` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `version_count` (
`protocol` varchar(100) NOT NULL,
`identifier` varchar(100) NOT NULL,
`version_count` int(11) NOT NULL,
PRIMARY KEY (`protocol`,`identifier`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Copy data into new schema
--
insert into store
(
protocol, identifier, root_node_id
)
select
protocol, identifier, root_node_id
from
T_store;
insert into node
(
id, protocol, identifier, uuid, type_qname, acl_id
)
select
id, protocol, identifier, uuid, type_qname, acl_id
from
T_node;
insert into version_count
(
protocol, identifier, version_count
)
select
protocol, identifier, version_count
from
T_version_count;
insert into node_status
(
protocol, identifier, guid, node_id, change_txn_id
)
select
protocol, identifier, guid, node_id, change_txn_id
from
T_node_status;
insert into node_properties
(
node_id, actual_type, multi_valued, persisted_type,
boolean_value, long_value, float_value, double_value, string_value, serializable_value, qname
)
select
node_id, actual_type, multi_valued, persisted_type,
boolean_value, long_value, float_value, double_value, string_value, serializable_value, qname
from
T_node_properties;
insert into node_aspects
(
node_id, qname
)
select
node_id, qname
from
T_node_aspects;
insert into child_assoc
(
id, parent_node_id, child_node_id, type_qname, qname, is_primary, assoc_index
)
select
id, parent_node_id, child_node_id, type_qname, qname, is_primary, assoc_index
from
T_child_assoc;
insert into node_assoc
(
id, source_node_id, target_node_id, type_qname
)
select
id, source_node_id, target_node_id, type_qname
from
T_node_assoc;
insert into permission
(
id, type_qname, name
)
select
id, type_qname, name
from
T_permission;
insert into access_control_list
(
id, inherits
)
select
id, inherits
from
T_access_control_list;
insert into auth_ext_keys
(
id, externalKey
)
select
id, externalKey
from
T_auth_ext_keys;
insert into authority
(
recipient
)
select
recipient
from
T_authority;
insert into access_control_entry
(
id, acl_id, permission_id, authority_id, allowed
)
select
id, acl_id, permission_id, authority_id, allowed
from
T_access_control_entry;
SET FOREIGN_KEY_CHECKS = 1;
-- Allow longer patch identifiers
ALTER TABLE applied_patch MODIFY id varchar(64) not null;

View File

@@ -0,0 +1,636 @@
-- ------------------------------------------------------
-- Alfresco Schema conversion V1.2.1 to V1.3
--
-- For Oracle.
--
-- Note: This script does not create a temporary
-- properties table. It updates the existing
-- table as it is not possible to insert..select
-- long raw columns in Oracle.
--
-- Author: David Caruana
-- ------------------------------------------------------
--
-- Create temporary 1.3 schema
--
CREATE TABLE T_access_control_entry (
id number(19,0) NOT NULL,
protocol varchar2(50) default NULL,
identifier varchar2(100) default NULL,
uuid varchar2(36) default NULL,
typeUri varchar2(100) default NULL,
typeName varchar2(100) default NULL,
name varchar2(100) default NULL,
recipient varchar2(100) default NULL,
acl_id number(19, 0),
permission_id number(19, 0),
authority_id varchar2(100),
allowed number(1, 0) NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX IDX_ACE_REF ON T_access_control_entry (protocol, identifier, uuid);
CREATE TABLE T_access_control_list
(
id number(19,0) not null,
protocol varchar2(50) NOT NULL,
identifier varchar2(100) NOT NULL,
uuid varchar2(36) NOT NULL,
inherits number(1,0) NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX IDX_ACL_REF ON T_access_control_list (protocol, identifier, uuid);
create table T_auth_ext_keys
(
id varchar2(100) not null,
externalKey varchar2(100) not null,
primary key (id, externalKey)
);
create table T_authority
(
recipient varchar2(100) not null,
primary key (recipient)
);
CREATE TABLE T_child_assoc
(
id number(19,0) NOT NULL,
parent_node_id number(19,0) default NULL,
parent_protocol varchar(50) default NULL,
parent_identifier varchar(100) default NULL,
parent_uuid varchar(36) default NULL,
child_node_id number(19,0) default NULL,
child_protocol varchar(50) default NULL,
child_identifier varchar(100) default NULL,
child_uuid varchar(36) default NULL,
type_qname varchar(255) NOT NULL,
qname varchar(255) NOT NULL,
is_primary number(1,0) default NULL,
assoc_index number(10,0) default NULL,
PRIMARY KEY (id)
);
CREATE INDEX IDX_CA_PARENT ON T_child_assoc(parent_protocol, parent_identifier, parent_uuid);
CREATE INDEX IDX_CA_CHILD ON T_child_assoc(child_protocol, child_identifier, child_uuid);
CREATE TABLE T_node
(
id number(19,0) NOT NULL,
protocol varchar2(50) NOT NULL,
identifier varchar2(100) NOT NULL,
uuid varchar2(36) NOT NULL,
acl_id number(19,0) default NULL,
type_qname varchar2(255) NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX IDX_NODE_REF ON T_node(protocol, identifier, uuid);
CREATE TABLE T_node_aspects
(
protocol varchar2(50) NOT NULL,
identifier varchar2(100) NOT NULL,
uuid varchar2(36) NOT NULL,
node_id number(19,0),
qname varchar2(200) default NULL
);
CREATE INDEX IDX_ASPECTS_REF ON T_node_aspects(protocol, identifier, uuid);
CREATE TABLE T_node_assoc
(
id number(19,0) NOT NULL,
source_node_id number(19,0) default NULL,
source_protocol varchar2(50) default NULL,
source_identifier varchar2(100) default NULL,
source_uuid varchar2(36) default NULL,
target_node_id number(19,0) default NULL,
target_protocol varchar2(50) default NULL,
target_identifier varchar2(100) default NULL,
target_uuid varchar2(36) default NULL,
type_qname varchar2(255) NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX IDX_NA_SOURCE on T_node_assoc(source_protocol, source_identifier, source_uuid);
CREATE INDEX IDX_NA_TARGET on T_node_assoc(target_protocol, target_identifier, target_uuid);
CREATE TABLE T_node_status
(
protocol varchar2(50) NOT NULL,
identifier varchar2(100) NOT NULL,
guid varchar2(36) NOT NULL,
node_id number(19,0) default NULL,
change_txn_id varchar2(56) NOT NULL,
deleted number(1,0) NOT NULL,
primary key (protocol, identifier, guid)
);
CREATE TABLE T_permission
(
id number(19,0) NOT NULL,
type_qname varchar2(200) NOT NULL,
name varchar2(100) NOT NULL,
PRIMARY KEY (id),
unique (type_qname, name)
);
CREATE TABLE T_store
(
protocol varchar2(50) NOT NULL,
identifier varchar2(100) NOT NULL,
root_node_id number(19,0) default NULL,
primary key (protocol, identifier)
);
CREATE TABLE T_version_count
(
protocol varchar2(50) NOT NULL,
identifier varchar2(100) NOT NULL,
version_count number(10,0) NOT NULL,
primary key (protocol, identifier)
);
create sequence hibernate_sequence;
--
-- Copy data from old tables to intermediate tables
--
insert into T_store (protocol, identifier)
select protocol, identifier from store;
insert into T_node (id, protocol, identifier, uuid, type_qname)
select hibernate_sequence.nextval, protocol, identifier, guid, type_qname from node;
update T_store tstore set root_node_id =
(select tnode.id from T_node tnode where
tnode.protocol = tstore.protocol and
tnode.identifier = tstore.identifier and
tnode.uuid =
(select ostore.root_guid from store ostore where
ostore.protocol = tstore.protocol and
ostore.identifier = tstore.identifier
)
);
insert into t_version_count (protocol, identifier, version_count)
select protocol, identifier, version_count from version_count;
insert into t_node_status (protocol, identifier, guid, change_txn_id, deleted)
select protocol, identifier, guid, change_txn_id, deleted from node_status;
update T_node_status tstatus set node_id =
(select tnode.id from T_node tnode where
tnode.protocol = tstatus.protocol and
tnode.identifier = tstatus.identifier and
tnode.uuid = tstatus.guid
);
insert into T_node_aspects
(
protocol, identifier, uuid, qname
)
select
protocol, identifier, guid, qname
from node_aspects;
update T_node_aspects taspects set node_id =
(select tnode.id from T_node tnode where
tnode.protocol = taspects.protocol and
tnode.identifier = taspects.identifier and
tnode.uuid = taspects.uuid
);
insert into T_child_assoc
(
id, parent_protocol, parent_identifier, parent_uuid,
child_protocol, child_identifier, child_uuid,
type_qname, qname, is_primary, assoc_index
)
select
hibernate_sequence.nextval, parent_protocol, parent_identifier, parent_guid,
child_protocol, child_identifier, child_guid,
type_qname, qname, isPrimary, assoc_index
from
child_assoc;
update T_child_assoc tassoc set parent_node_id =
(select tnode.id from T_node tnode where
tnode.protocol = tassoc.parent_protocol and
tnode.identifier = tassoc.parent_identifier and
tnode.uuid = tassoc.parent_uuid
);
update T_child_assoc tassoc set child_node_id =
(select tnode.id from T_node tnode where
tnode.protocol = tassoc.child_protocol and
tnode.identifier = tassoc.child_identifier and
tnode.uuid = tassoc.child_uuid
);
insert into T_node_assoc
(
id, source_protocol, source_identifier, source_uuid,
target_protocol, target_identifier, target_uuid,
type_qname
)
select
hibernate_sequence.nextval, source_protocol, source_identifier, source_guid,
target_protocol, target_identifier, target_guid,
type_qname
from
node_assoc;
update T_node_assoc tassoc set source_node_id =
(select tnode.id from T_node tnode where
tnode.protocol = tassoc.source_protocol and
tnode.identifier = tassoc.source_identifier and
tnode.uuid = tassoc.source_uuid
);
update T_node_assoc tassoc set target_node_id =
(select tnode.id from T_node tnode where
tnode.protocol = tassoc.target_protocol and
tnode.identifier = tassoc.target_identifier and
tnode.uuid = tassoc.target_uuid
);
insert into T_permission
(
id, type_qname, name
)
select
hibernate_sequence.nextval, '{' || type_uri || '}' || type_name, name
from
permission_ref;
insert into T_access_control_list
(
id, protocol, identifier, uuid, inherits
)
select
hibernate_sequence.nextval, protocol, identifier, guid, inherits
from node_permission;
update T_node tnode set acl_id =
(select tacl.id from T_access_control_list tacl where
tacl.protocol = tnode.protocol and
tacl.identifier = tnode.identifier and
tacl.uuid = tnode.uuid
);
insert into T_auth_ext_keys
(
id, externalKey
)
select
id, externalKey
from
externalkeys;
insert into T_authority
(
recipient
)
select
recipient
from
recipient;
insert into T_access_control_entry
(
id, protocol, identifier, uuid,
typeUri, typeName, name,
recipient,
allowed
)
select
hibernate_sequence.nextval, e.protocol, e.identifier, e.guid,
e.typeUri, e.typeName, e.name,
e.recipient,
e.allowed
from node_perm_entry e join t_node n on e.protocol = n.protocol and e.identifier = n.identifier and e.guid = n.uuid
;
update T_access_control_entry tentry
set
acl_id =
(
select
tacl.id
from T_access_control_list tacl
join T_node tnode on tacl.id = tnode.acl_id
where
tnode.protocol = tentry.protocol and
tnode.identifier = tentry.identifier and
tnode.uuid = tentry.uuid
);
update T_access_control_entry tentry
set
tentry.permission_id =
(
select
tpermission.id
from T_permission tpermission
where
tpermission.type_qname = '{' || tentry.typeUri || '}' || tentry.typeName and
tpermission.name = tentry.name
);
update T_access_control_entry tentry
set
tentry.authority_id =
(
select
tauthority.recipient
from T_authority tauthority
where
tauthority.recipient = tentry.recipient
);
delete from T_access_control_list where id not in (select distinct(acl_id) id from t_access_control_entry where acl_id is not null);
delete from T_access_control_entry where acl_id is null;
update T_node set acl_id = null where acl_id not in (select id from t_access_control_list);
--
-- Create New schema (Oracle)
--
DROP TABLE child_assoc cascade constraints;
DROP TABLE node_assoc cascade constraints;
DROP TABLE node_aspects cascade constraints;
DROP TABLE node cascade constraints;
DROP TABLE node_status cascade constraints;
DROP TABLE version_count cascade constraints;
DROP TABLE store cascade constraints;
DROP TABLE node_perm_entry cascade constraints;
DROP TABLE node_permission cascade constraints;
DROP TABLE permission_ref cascade constraints;
DROP TABLE recipient cascade constraints;
DROP TABLE externalKeys cascade constraints;
create table access_control_entry
(
id number(19,0) not null,
acl_id number(19,0) not null,
permission_id number(19,0) not null,
authority_id varchar2(100) not null,
allowed number(1,0) not null,
primary key (id),
unique (acl_id, permission_id, authority_id)
);
create table access_control_list
(
id number(19,0) not null,
inherits number(1,0) not null,
primary key (id)
);
create table auth_ext_keys
(
id varchar2(100) not null,
externalKey varchar2(100) not null,
primary key (id, externalKey)
);
create table authority
(
recipient varchar2(100) not null,
primary key (recipient)
);
create table child_assoc
(
id number(19,0) not null,
parent_node_id number(19,0),
child_node_id number(19,0),
type_qname varchar2(255) not null,
qname varchar2(255) not null,
is_primary number(1,0),
assoc_index number(10,0),
primary key (id)
);
create table node
(
id number(19,0) not null,
protocol varchar2(50) not null,
identifier varchar2(100) not null,
uuid varchar2(36) not null,
type_qname varchar2(255) not null,
acl_id number(19,0),
primary key (id),
unique (protocol, identifier, uuid)
);
create table node_aspects
(
node_id number(19,0) not null,
qname varchar2(200)
);
create table node_assoc
(
id number(19,0) not null,
source_node_id number(19,0),
target_node_id number(19,0),
type_qname varchar2(255) not null,
primary key (id)
);
create table node_status
(
protocol varchar2(50) not null,
identifier varchar2(100) not null,
guid varchar2(36) not null,
node_id number(19,0),
change_txn_id varchar2(56) not null,
primary key (protocol, identifier, guid)
);
create table permission
(
id number(19,0) not null,
type_qname varchar2(200) not null,
name varchar2(100) not null,
primary key (id),
unique (type_qname, name)
);
create table store
(
protocol varchar2(50) not null,
identifier varchar2(100) not null,
root_node_id number(19,0),
primary key (protocol, identifier)
);
create table version_count
(
protocol varchar2(100) not null,
identifier varchar2(100) not null,
version_count number(10,0) not null,
primary key (protocol, identifier)
);
--
-- Copy data into new schema
--
insert into store
(
protocol, identifier, root_node_id
)
select
protocol, identifier, root_node_id
from
T_store;
insert into node
(
id, protocol, identifier, uuid, type_qname, acl_id
)
select
id, protocol, identifier, uuid, type_qname, acl_id
from
T_node;
insert into version_count
(
protocol, identifier, version_count
)
select
protocol, identifier, version_count
from
T_version_count;
insert into node_status
(
protocol, identifier, guid, node_id, change_txn_id
)
select
protocol, identifier, guid, node_id, change_txn_id
from
T_node_status;
alter table node_properties add (node_id number(19,0));
update node_properties tproperties set node_id =
(select tnode.id from T_node tnode where
tnode.protocol = tproperties.protocol and
tnode.identifier = tproperties.identifier and
tnode.uuid = tproperties.guid
);
alter table node_properties modify (node_id number(19,0) not null);
alter table node_properties drop primary key;
alter table node_properties add primary key (node_id, qname);
alter table node_properties drop column protocol;
alter table node_properties drop column identifier;
alter table node_properties drop column guid;
insert into node_aspects
(
node_id, qname
)
select
node_id, qname
from
T_node_aspects;
insert into child_assoc
(
id, parent_node_id, child_node_id, type_qname, qname, is_primary, assoc_index
)
select
id, parent_node_id, child_node_id, type_qname, qname, is_primary, assoc_index
from
T_child_assoc;
insert into node_assoc
(
id, source_node_id, target_node_id, type_qname
)
select
id, source_node_id, target_node_id, type_qname
from
T_node_assoc;
insert into permission
(
id, type_qname, name
)
select
id, type_qname, name
from
T_permission;
insert into access_control_list
(
id, inherits
)
select
id, inherits
from
T_access_control_list;
insert into auth_ext_keys
(
id, externalKey
)
select
id, externalKey
from
T_auth_ext_keys;
insert into authority
(
recipient
)
select
recipient
from
T_authority;
insert into access_control_entry
(
id, acl_id, permission_id, authority_id, allowed
)
select
id, acl_id, permission_id, authority_id, allowed
from
T_access_control_entry;
-- Enable constraints
alter table access_control_entry add constraint FKF064DF7560601995 foreign key (permission_id) references permission;
alter table access_control_entry add constraint FKF064DF75B25A50BF foreign key (authority_id) references authority;
alter table access_control_entry add constraint FKF064DF75B9553F6C foreign key (acl_id) references access_control_list;
alter table auth_ext_keys add constraint FK31D3BA097B7FDE43 foreign key (id) references authority;
alter table child_assoc add constraint FKC6EFFF3274173FF4 foreign key (child_node_id) references node;
alter table child_assoc add constraint FKC6EFFF328E50E582 foreign key (parent_node_id) references node;
alter table node add constraint FK33AE02B9553F6C foreign key (acl_id) references access_control_list;
alter table node add constraint FK33AE02D24ADD25 foreign key (protocol, identifier) references store;
alter table node_properties add constraint FKC962BF907F2C8017 foreign key (node_id) references node;
alter table node_aspects add constraint FK2B91A9DE7F2C8017 foreign key (node_id) references node;
alter table node_assoc add constraint FK5BAEF398B69C43F3 foreign key (source_node_id) references node;
alter table node_assoc add constraint FK5BAEF398A8FC7769 foreign key (target_node_id) references node;
alter table node_status add constraint FK38ECB8CF7F2C8017 foreign key (node_id) references node;
alter table store add constraint FK68AF8E122DBA5BA foreign key (root_node_id) references node;
-- Add additional indexes
CREATE INDEX FKF064DF7560601995 ON access_control_entry (permission_id);
CREATE INDEX FKF064DF75B25A50BF ON access_control_entry (authority_id);
CREATE INDEX FKF064DF75B9553F6C ON access_control_entry (acl_id);
CREATE INDEX FK31D3BA097B7FDE43 ON auth_ext_keys (id);
CREATE INDEX FKC6EFFF3274173FF4 ON child_assoc (child_node_id);
CREATE INDEX FKC6EFFF328E50E582 ON child_assoc (parent_node_id);
CREATE INDEX FK33AE02B9553F6C ON node (acl_id);
CREATE INDEX FK33AE02D24ADD25 ON node (protocol, identifier);
CREATE INDEX FK2B91A9DE7F2C8017 ON node_aspects (node_id);
CREATE INDEX FK5BAEF398B69C43F3 ON node_assoc (source_node_id);
CREATE INDEX FK5BAEF398A8FC7769 ON node_assoc (target_node_id);
CREATE INDEX FKC962BF907F2C8017 ON node_properties (node_id);
CREATE INDEX FK38ECB8CF7F2C8017 ON node_status (node_id);
CREATE INDEX FK68AF8E122DBA5BA ON store (root_node_id);
ALTER TABLE applied_patch MODIFY id varchar(64);

View File

@@ -0,0 +1,75 @@
-- ------------------------------------------------------
-- Alfresco Schema conversion V1.3 to V1.4 Part 1
--
-- Adds the columns required to enforce the duplicate name detection
--
-- Author: Derek Hulley
-- ------------------------------------------------------
--
-- Delete intermediate tables from previous upgrades
--
DROP TABLE IF EXISTS T_access_control_entry;
DROP TABLE IF EXISTS T_access_control_list;
DROP TABLE IF EXISTS T_applied_patch;
DROP TABLE IF EXISTS T_auth_ext_keys;
DROP TABLE IF EXISTS T_authority;
DROP TABLE IF EXISTS T_child_assoc;
DROP TABLE IF EXISTS T_node;
DROP TABLE IF EXISTS T_node_aspects;
DROP TABLE IF EXISTS T_node_assoc;
DROP TABLE IF EXISTS T_node_properties;
DROP TABLE IF EXISTS T_node_status;
DROP TABLE IF EXISTS T_permission;
DROP TABLE IF EXISTS T_store;
DROP TABLE IF EXISTS T_version_count;
--
-- Unique name constraint
--
-- Apply new schema changes to child assoc table
ALTER TABLE child_assoc
ADD COLUMN child_node_name VARCHAR(50) NOT NULL DEFAULT 'V1.4 upgrade' AFTER type_qname,
ADD COLUMN child_node_name_crc bigint(20) NOT NULL DEFAULT -1 AFTER child_node_name;
UPDATE child_assoc
SET child_node_name_crc = id * -1;
ALTER TABLE child_assoc
ADD UNIQUE INDEX IDX_CHILD_NAMECRC(parent_node_id, type_qname, child_node_name, child_node_name_crc);
-- Apply unique index for node associations
ALTER TABLE node_assoc
ADD UNIQUE INDEX IDX_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;
--
-- 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, now(), 'UNKOWN', 1, 1, 'Script completed'
);

View File

@@ -0,0 +1,59 @@
-- ------------------------------------------------------
-- Alfresco Schema conversion V1.3 to V1.4 Part 2
--
-- 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 bigint(20) NOT NULL auto_increment,
ip_address varchar(15) NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY ip_address (ip_address)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into alf_server (id, ip_address) values (0, '0.0.0.0');
CREATE TABLE alf_transaction (
id bigint(20) NOT NULL auto_increment,
server_id bigint(20) default NULL,
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
(
server_id, change_txn_id
)
select (select max(id) from alf_server), change_txn_id from alf_node_status group by change_txn_id;
-- Alter node status
ALTER TABLE alf_node_status
ADD COLUMN transaction_id bigint(20) NOT NULL DEFAULT 0 AFTER node_id;
-- 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
);
ALTER TABLE alf_node_status
DROP COLUMN change_txn_id,
ADD CONSTRAINT FK71C2002B9E57C13D FOREIGN KEY (transaction_id) REFERENCES alf_transaction (id);
--
-- 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, now(), 'UNKOWN', 1, 1, 'Script completed'
);

View File

@@ -1,10 +1,11 @@
#
# Hibernate configuration
#
hibernate.jdbc.use_streams_for_binary=true
hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect
hibernate.show_sql=false
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
hibernate.cache.provider_class=org.alfresco.repo.cache.InternalEhCacheManagerFactoryBean

View File

@@ -1,189 +1,144 @@
<?xml version='1.0' encoding='UTF-8'?>
<ehcache>
<!-- defaults -->
<diskStore
path="java.io.tmpdir"/>
<!--
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,
multicastGroupPort=4446"/>
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"/>
-->
<defaultCache
maxElementsInMemory="5000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
>
<!--
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=false, replicatePuts=false,
replicateUpdates=true, replicateUpdatesViaCopy=false,
replicateRemovals=true"/>
-->
</defaultCache>
<!-- Hibernate usage -->
<cache
name="org.hibernate.cache.StandardQueryCache"
maxElementsInMemory="50"
eternal="true"
timeToLiveSeconds="0"
overflowToDisk="false"/>
/>
<!-- approx 0.4MB memory required -->
<cache
name="org.hibernate.cache.UpdateTimestampsCache"
maxElementsInMemory="2000"
eternal="true"
overflowToDisk="false"/>
/>
<!-- approx 40MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.NodeImpl"
maxElementsInMemory="10000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<!-- approx 0.1 MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.QNameEntityImpl"
maxElementsInMemory="100"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<!-- approx 40MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.NodeStatusImpl"
maxElementsInMemory="10000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<!-- approx 15MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.NodeImpl.aspects"
maxElementsInMemory="10000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<!-- approx 10MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.NodeImpl.properties"
maxElementsInMemory="10000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<!-- approx 20MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.NodeImpl.childAssocs"
maxElementsInMemory="10000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<!-- approx 10MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.NodeImpl.parentAssocs"
maxElementsInMemory="10000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<!-- approx 250MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.ChildAssocImpl"
maxElementsInMemory="200000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<!-- approx 10MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.NodeImpl.sourceNodeAssocs"
maxElementsInMemory="10000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<!-- approx 10MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.NodeImpl.targetNodeAssocs"
maxElementsInMemory="10000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<!-- general use node associations are not common -->
<cache
name="org.alfresco.repo.domain.hibernate.NodeAssocImpl"
maxElementsInMemory="1000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<!-- low numbers of objects expected -->
<cache
name="org.alfresco.repo.domain.hibernate.StoreImpl"
maxElementsInMemory="100"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<!-- version counters -->
<!-- approx 0.4MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.VersionCountImpl"
maxElementsInMemory="100"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<!-- approx 0.1MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.AppliedPatchImpl"
maxElementsInMemory="100"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="60"
overflowToDisk="false"
/>
<!-- Permission related caches -->
<!-- approx 1MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.DbAccessControlListImpl"
maxElementsInMemory="1000"
eternal="true"
overflowToDisk="false"/>
/>
<!-- approx 1MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.DbAccessControlListImpl.entries"
maxElementsInMemory="1000"
eternal="true"
overflowToDisk="false"/>
/>
<!-- approx 5MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.DbAccessControlEntryImpl"
maxElementsInMemory="5000"
eternal="true"
overflowToDisk="false"/>
/>
<!-- approx 1MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.DbPermissionImpl"
maxElementsInMemory="500"
eternal="true"
overflowToDisk="false"/>
/>
<!-- approx 10MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.DbAuthorityImpl"
maxElementsInMemory="10000"
eternal="true"
overflowToDisk="false"/>
/>
<!-- approx 5MB memory required -->
<cache
name="org.alfresco.repo.domain.hibernate.DbAuthorityImpl.externalKeys"
maxElementsInMemory="5000"
/>
<!-- Audit caches -->
<cache
name="org.alfresco.repo.audit.hibernate.AuditConfigImpl"
maxElementsInMemory="2"
eternal="true"
overflowToDisk="false"/>
<cache
name="org.alfresco.repo.audit.hibernate.AuditDateImpl"
maxElementsInMemory="2"
eternal="true"
overflowToDisk="false"/>
<cache
name="org.alfresco.repo.audit.hibernate.AuditSourceImpl"
maxElementsInMemory="2000"
eternal="true"
overflowToDisk="false"/>
</ehcache>

View File

@@ -2,6 +2,7 @@
# Sample database connection properties
#
#db.schema.update=true
#db.username=alfresco
#db.password=alfresco
#db.pool.initial=10

View File

@@ -30,6 +30,9 @@
</property>
</bean>
<bean id="sessionFactoryBase" abstract="true">
<property name="schemaUpdate">
<value>false</value>
</property>
<property name="mappingResources">
<list>
<!-- -->
@@ -38,11 +41,16 @@
<value>org/alfresco/repo/domain/hibernate/Node.hbm.xml</value>
<value>org/alfresco/repo/domain/hibernate/Store.hbm.xml</value>
<value>org/alfresco/repo/domain/hibernate/Transaction.hbm.xml</value>
<value>org/alfresco/repo/domain/hibernate/VersionCount.hbm.xml</value>
<value>org/alfresco/repo/domain/hibernate/AppliedPatch.hbm.xml</value>
<value>org/alfresco/repo/domain/hibernate/Permission.hbm.xml</value>
<value>org/alfresco/repo/avm/hibernate/AVM.hbm.xml</value>
<!-- Audit config -->
<!-- TODO: Move into org/alfresco/repo/domain/hibernate/ -->
<value>org/alfresco/repo/audit/hibernate/Audit.hbm.xml</value>
<!-- -->
<!-- JBoss jBPM Workflow Engine -->
<!-- -->
@@ -147,6 +155,8 @@
<prop key="org.alfresco.repo.domain.hibernate.ChildAssocImpl">${cache.strategy}</prop>
<prop key="org.alfresco.repo.domain.hibernate.NodeAssocImpl">${cache.strategy}</prop>
<prop key="org.alfresco.repo.domain.hibernate.StoreImpl">${cache.strategy}</prop>
<prop key="org.alfresco.repo.domain.hibernate.TransactionImpl">${cache.strategy}</prop>
<prop key="org.alfresco.repo.domain.hibernate.ServerImpl">${cache.strategy}</prop>
<prop key="org.alfresco.repo.domain.hibernate.VersionCountImpl">${cache.strategy}</prop>
<prop key="org.alfresco.repo.domain.hibernate.AppliedPatchImpl">${cache.strategy}</prop>
@@ -154,6 +164,10 @@
<prop key="org.alfresco.repo.domain.hibernate.DbAccessControlEntryImpl">${cache.strategy}</prop>
<prop key="org.alfresco.repo.domain.hibernate.DbPermissionImpl">${cache.strategy}</prop>
<prop key="org.alfresco.repo.domain.hibernate.DbAuthorityImpl">${cache.strategy}</prop>
<prop key="org.alfresco.repo.audit.hibernate.AuditConfigImpl">${cache.strategy}</prop>
<prop key="org.alfresco.repo.audit.hibernate.AuditDateImpl">${cache.strategy}</prop>
<prop key="org.alfresco.repo.audit.hibernate.AuditSourceImpl">${cache.strategy}</prop>
</props>
</property>
<property name="collectionCacheStrategies" >
@@ -202,16 +216,19 @@
<ref bean="sessionFactory" />
</property>
</bean>
<bean id="dbNodeDaoServiceTxnRegistration" class="org.alfresco.repo.transaction.TransactionalDaoInterceptor" >
<property name="daoService">
<ref bean="nodeDaoServiceImpl" />
</property>
</bean>
<bean id="persmissionsDaoServiceTxnRegistration" class="org.alfresco.repo.transaction.TransactionalDaoInterceptor" >
<property name="daoService">
<ref bean="permissionsDaoComponent" />
</property>
</bean>
<bean id="nodeDaoService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.repo.node.db.NodeDaoService</value>
@@ -226,4 +243,14 @@
</property>
</bean>
<bean id="auditDao" class="org.alfresco.repo.audit.hibernate.HibernateAuditDAO">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
<property name="contentStore">
<ref bean="auditFileContentStore"/>
</property>
</bean>
</beans>

View File

@@ -22,17 +22,11 @@
<property name="nodeService">
<ref bean="nodeService" />
</property>
<property name="stores">
<list>
<value>workspace://SpacesStore</value>
<value>workspace://lightWeightVersionStore</value>
<value>user://alfrescoUserStore</value>
</list>
</property>
</bean>
<!-- full node index recovery -->
<bean id="indexRecoveryComponent" class="org.alfresco.repo.node.index.FullIndexRecoveryComponent" parent="indexRecoveryComponentBase">
<!-- Properties controlling full index rebuilding / tracking -->
<property name="executeFullRecovery">
<value>false</value> <!-- enable this to start the full index recovery -->
</property>
@@ -47,4 +41,43 @@
</property>
</bean>
<!-- attempt to reindex content that was missing before -->
<!--
<bean id="missingContentReindexComponent" class="org.alfresco.repo.node.index.MissingContentReindexComponent" parent="indexRecoveryComponentBase">
<property name="runContinuously">
<value>false</value>
</property>
<property name="waitTime">
<value>300000</value>
</property>
</bean>
<bean id="missingContentReindexTrigger" class="org.alfresco.util.TriggerBean">
<property name="jobDetail">
<bean id="IndexRecoveryJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<value>org.alfresco.repo.node.index.IndexRecoveryJob</value>
</property>
<property name="jobDataAsMap">
<map>
<entry key="missingContentReindexComponent">
<ref bean="missingContentReindexComponent" />
</entry>
</map>
</property>
</bean>
</property>
<property name="startDelay">
<value>60000</value>
</property>
<property name="repeatCount">
<value>0</value>
</property>
<property name="scheduler">
<ref bean="schedulerFactory" />
</property>
</bean>
-->
</beans>

View File

@@ -74,10 +74,13 @@ export.generic.package.description=Alfresco Repository export.
export.package.error=Failed to find temporary file for export
script.title=Execute a script
script.description=Execute a JavaScript file to perform tasks such as creating new files or folders
script.description=Execute a JavaScript file to perform tasks such as creating new files or folders.
counter.title=Increment Counter
counter.counter=Increment the counter property for the item.
execute-all-rules.title=Execute all rules
execute-all-rules.description=Execute all rules on the child items
execute-all-rules.description=Execute all rules on the child items.
start-workflow.title=Start Workflow
start-workflow.description=This will start a workflow for the matched items.

View File

@@ -16,6 +16,9 @@ patch.general.property_not_set=Patch property ''{0}'' has not been set on this p
# Individual patch messages
patch.marker.description=Marker patch to record installations and upgrades
patch.marker.result=Marker patch applied
patch.savedSearchesFolder.description=Ensures the existence of the 'Saved Searches' folder.
patch.savedSearchesFolder.result.exists=The saved searches folder already exists: {0}
patch.savedSearchesFolder.result.created=The saved searches folder was successfully created: {0}

View File

@@ -0,0 +1,8 @@
# Schema update messages
schema.update.msg.executing_script=Executing schema upgrade script: {0}
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}
schema.update.err.script_not_found=The schema script could not be found at location {0}
schema.update.err.statement_terminator=Scripts must terminate all statements with '';'' (line {0} of {1}).

View File

@@ -526,6 +526,9 @@
<property name="cm:hits">
<type>d:int</type>
</property>
<property name="cm:counter">
<type>d:int</type>
</property>
</properties>
</aspect>

View File

@@ -441,12 +441,12 @@
<bean id="patch.schemaUpdateScript-V1.4-1" class="org.alfresco.repo.admin.patch.impl.SchemaUpgradeScriptPatch" parent="basePatch">
<property name="id"><value>patch.schemaUpdateScript-V1.4-1</value></property>
<property name="description"><value>patch.patch.schemaUpgradeScriptPatch.description</value></property>
<property name="description"><value>patch.schemaUpgradeScript.description</value></property>
<property name="fixesFromSchema"><value>0</value></property>
<property name="fixesToSchema"><value>19</value></property>
<property name="targetSchema"><value>20</value></property>
<property name="scriptName">
<value>AlfrescoSchemaUpdate-1.4-1-xxx.sql</value>
<property name="scriptUrl">
<value>classpath:alfresco/dbscripts/upgrade/1.4/${db.script.dialect}/AlfrescoSchemaUpdate-1.4-1.sql</value>
</property>
</bean>
<bean id="patch.uniqueChildName" class="org.alfresco.repo.admin.patch.impl.UniqueChildNamePatch" parent="basePatch" >
@@ -472,5 +472,21 @@
</list>
</property>
</bean>
<bean id="patch.schemaUpdateScript-V1.4-2" class="org.alfresco.repo.admin.patch.impl.SchemaUpgradeScriptPatch" parent="basePatch">
<property name="id"><value>patch.schemaUpdateScript-V1.4-2</value></property>
<property name="description"><value>patch.schemaUpgradeScript.description</value></property>
<property name="fixesFromSchema"><value>0</value></property>
<property name="fixesToSchema"><value>20</value></property>
<property name="targetSchema"><value>21</value></property>
<property name="scriptUrl">
<value>classpath:alfresco/dbscripts/upgrade/1.4/${db.script.dialect}/AlfrescoSchemaUpdate-1.4-2.sql</value>
</property>
<!-- dependent on upgrade script 1.4-1 having being run -->
<property name="dependsOn" >
<list>
<ref bean="patch.schemaUpdateScript-V1.4-1" />
</list>
</property>
</bean>
</beans>

View File

@@ -11,7 +11,6 @@
</property>
</bean>
<!-- Service Registry -->
<bean id="ServiceRegistry" class="org.springframework.aop.framework.ProxyFactoryBean">
@@ -47,7 +46,9 @@
<property name="proxyInterfaces">
<value>org.alfresco.service.descriptor.DescriptorService</value>
</property>
<property name="target"><ref bean="descriptorComponent"/></property>
<property name="target">
<ref bean="descriptorComponent"/>
</property>
<property name="interceptorNames">
<list>
<idref local="exceptionTranslator"/>
@@ -65,6 +66,17 @@
</property>
</bean>
<!-- AuditMethodInterceptor -->
<bean id="AuditMethodInterceptor" class="org.alfresco.repo.audit.AuditMethodInterceptor">
<property name="auditComponent">
<ref bean="auditComponent"/>
</property>
<property name="disabled">
<value>false</value>
</property>
</bean>
<!-- Namespace Service -->
@@ -72,10 +84,13 @@
<property name="proxyInterfaces">
<value>org.alfresco.service.namespace.NamespaceService</value>
</property>
<property name="target"><ref bean="namespaceService"/></property>
<property name="target">
<ref bean="namespaceService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="NamespaceService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="NamespaceService_security"/>
<idref local="NamespaceService_descriptor"/>
@@ -103,22 +118,23 @@
</property>
</bean>
<!-- Transaction Service -->
<alias alias="TransactionService" name="transactionComponent"/>
<!-- Dictionary Service -->
<bean id="DictionaryService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.dictionary.DictionaryService</value>
</property>
<property name="target"><ref bean="dictionaryService"/></property>
<property name="target">
<ref bean="dictionaryService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="DictionaryService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="DictionaryService_security"/>
<idref local="DictionaryService_descriptor"/>
@@ -146,17 +162,22 @@
</property>
</bean>
<!-- Node Service -->
<bean id="NodeService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<list>
<value>org.alfresco.service.ServiceDescriptor</value>
<value>org.alfresco.service.cmr.repository.NodeService</value>
</list>
</property>
<property name="target">
<ref bean="nodeService"/>
</property>
<property name="target"><ref bean="nodeService"/></property>
<property name="interceptorNames">
<list>
<idref local="NodeService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="NodeService_security"/>
<idref local="NodeService_descriptor"/>
@@ -187,19 +208,19 @@
</property>
</bean>
<!-- Content Service -->
<bean id="ContentService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.repository.ContentService</value>
</property>
<property name="target"><ref bean="contentService"/></property>
<property name="target">
<ref bean="contentService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="ContentService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="ContentService_security"/>
<idref local="ContentService_descriptor"/>
@@ -227,16 +248,18 @@
</property>
</bean>
<!-- Mime Type Service -->
<bean id="MimetypeService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.repository.MimetypeService</value>
</property>
<property name="target"><ref bean="mimetypeService"/></property>
<property name="target">
<ref bean="mimetypeService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="MimetypeService_security"/>
<idref local="MimetypeService_descriptor"/>
@@ -253,17 +276,19 @@
</property>
</bean>
<!-- Search Service -->
<bean id="SearchService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.search.SearchService</value>
</property>
<property name="target"><ref bean="searchService"/></property>
<property name="target">
<ref bean="searchService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="SearchService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="SearchService_security"/>
<idref local="SearchService_descriptor"/>
@@ -291,17 +316,19 @@
</property>
</bean>
<!-- Category Service -->
<bean id="CategoryService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.search.CategoryService</value>
</property>
<property name="target"><ref bean="categoryService"/></property>
<property name="target">
<ref bean="categoryService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="CategoryService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="CategoryService_security"/>
<idref local="CategoryService_descriptor"/>
@@ -329,17 +356,19 @@
</property>
</bean>
<!-- Copy Service -->
<bean id="CopyService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.repository.CopyService</value>
</property>
<property name="target"><ref bean="copyService"/></property>
<property name="target">
<ref bean="copyService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="CopyService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="CopyService_security"/>
<idref local="CopyService_descriptor"/>
@@ -367,17 +396,19 @@
</property>
</bean>
<!-- Lock Service -->
<bean id="LockService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.lock.LockService</value>
</property>
<property name="target"><ref bean="lockService"/></property>
<property name="target">
<ref bean="lockService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="LockService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="LockService_security"/>
<idref local="LockService_descriptor"/>
@@ -405,17 +436,19 @@
</property>
</bean>
<!-- Version Service -->
<bean id="VersionService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.version.VersionService</value>
</property>
<property name="target"><ref bean="versionService"/></property>
<property name="target">
<ref bean="versionService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="VersionService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="VersionService_security"/>
<idref local="VersionService_descriptor"/>
@@ -443,17 +476,19 @@
</property>
</bean>
<!-- COCI Service -->
<bean id="CheckoutCheckinService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.coci.CheckOutCheckInService</value>
</property>
<property name="target"><ref bean="checkOutCheckInService"/></property>
<property name="target">
<ref bean="checkOutCheckInService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="CheckoutCheckinService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="CheckoutCheckinService_security"/>
<idref local="CheckoutCheckinService_descriptor"/>
@@ -481,17 +516,19 @@
</property>
</bean>
<!-- Rule Service -->
<bean id="RuleService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.rule.RuleService</value>
</property>
<property name="target"><ref bean="ruleService"/></property>
<property name="target">
<ref bean="ruleService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="RuleService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="RuleService_security"/>
<idref local="RuleService_descriptor"/>
@@ -519,17 +556,19 @@
</property>
</bean>
<!-- Importer Service -->
<bean id="ImporterService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.view.ImporterService</value>
</property>
<property name="target"><ref bean="importerComponent"/></property>
<property name="target">
<ref bean="importerComponent"/>
</property>
<property name="interceptorNames">
<list>
<idref local="ImporterService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="ImporterService_security"/>
<idref local="ImporterService_descriptor"/>
@@ -557,17 +596,19 @@
</property>
</bean>
<!-- Exporter Service -->
<bean id="ExporterService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.view.ExporterService</value>
</property>
<property name="target"><ref bean="exporterComponent"/></property>
<property name="target">
<ref bean="exporterComponent"/>
</property>
<property name="interceptorNames">
<list>
<idref local="ExporterService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="ExporterService_descriptor"/>
</list>
</property>
@@ -593,17 +634,19 @@
</property>
</bean>
<!-- Action Service -->
<bean id="ActionService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.action.ActionService</value>
</property>
<property name="target"><ref bean="actionService"/></property>
<property name="target">
<ref bean="actionService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="ActionService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="ActionService_security"/>
<idref local="ActionService_descriptor"/>
@@ -631,17 +674,19 @@
</property>
</bean>
<!-- Permission Service -->
<bean id="PermissionService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.security.PermissionService</value>
</property>
<property name="target"><ref bean="permissionService"/></property>
<property name="target">
<ref bean="permissionService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="PermissionService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="PermissionService_security"/>
<idref local="PermissionService_descriptor"/>
@@ -669,17 +714,19 @@
</property>
</bean>
<!-- Authority Service -->
<bean id="AuthorityService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.security.AuthorityService</value>
</property>
<property name="target"><ref bean="authorityService"/></property>
<property name="target">
<ref bean="authorityService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="AuthorityService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="AuthorityService_security"/>
<idref local="AuthorityService_descriptor"/>
@@ -707,17 +754,19 @@
</property>
</bean>
<!-- Ownable Service -->
<bean id="OwnableService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.security.OwnableService</value>
</property>
<property name="target"><ref bean="ownableService"/></property>
<property name="target">
<ref bean="ownableService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="OwnableService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="OwnableService_security"/>
<idref local="OwnableService_descriptor"/>
@@ -745,17 +794,19 @@
</property>
</bean>
<!-- Person Service -->
<bean id="PersonService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.security.PersonService</value>
</property>
<property name="target"><ref bean="personService"/></property>
<property name="target">
<ref bean="personService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="PersonService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="PersonService_security"/>
<idref local="PersonService_descriptor"/>
@@ -783,17 +834,19 @@
</property>
</bean>
<!-- Authentication Service -->
<bean id="AuthenticationService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.security.AuthenticationService</value>
</property>
<property name="target"><ref bean="authenticationServiceImpl"/></property>
<property name="target">
<ref bean="authenticationServiceImpl"/>
</property>
<property name="interceptorNames">
<list>
<idref local="AuthenticationService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="AuthenticationService_security"/>
<idref local="AuthenticationService_descriptor"/>
@@ -827,17 +880,19 @@
</property>
</bean>
<!-- Template Service -->
<bean id="TemplateService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.repository.TemplateService</value>
</property>
<property name="target"><ref bean="templateService"/></property>
<property name="target">
<ref bean="templateService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="TemplateService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="TemplateService_security"/>
<idref local="TemplateService_descriptor"/>
@@ -865,17 +920,19 @@
</property>
</bean>
<!-- Script Service -->
<bean id="ScriptService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.repository.ScriptService</value>
</property>
<property name="target"><ref bean="scriptService"/></property>
<property name="target">
<ref bean="scriptService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="ScriptService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="ScriptService_security"/>
<idref local="ScriptService_descriptor"/>
@@ -903,19 +960,22 @@
</property>
</bean>
<!-- File/Folder Service -->
<bean id="FileFolderService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.model.FileFolderService</value>
</property>
<property name="target"><ref bean="fileFolderService"/></property>
<property name="target">
<ref bean="fileFolderService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="FileFolderService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="FileFolderService_security"/>
<idref bean="FileFolderService_descriptor"/>
</list>
</property>
</bean>
@@ -935,6 +995,25 @@
</property>
</bean>
<bean id="FileFolderService_descriptor" parent="AlfrescoServiceDescriptor">
<property name="interface">
<value>org.alfresco.service.cmr.model.FileFolderService</value>
</property>
<property name="description">
<value>FileFolderService Service</value>
</property>
</bean>
<!-- The AVMService -->
<bean id="AVMService" class="org.alfresco.repo.avm.AVMServiceImpl">
<property name="retryingTransaction">
<ref bean="retryingTransaction"/>
</property>
<property name="avmRepository">
<ref bean="avmRepository"/>
</property>
</bean>
<!-- Workflow Service -->
@@ -942,10 +1021,15 @@
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.workflow.WorkflowService</value>
</property>
<property name="target"><ref bean="workflowServiceImpl"/></property>
<property name="target">
<ref bean="workflowServiceImpl"/>
</property>
<property name="interceptorNames">
<list>
<idref local="WorkflowService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="WorkflowService_security"/>
<idref local="WorkflowService_descriptor"/>
</list>
</property>
@@ -971,14 +1055,44 @@
</property>
</bean>
<!-- The AVMService -->
<bean id="AVMService" class="org.alfresco.repo.avm.AVMServiceImpl">
<property name="retryingTransaction">
<ref bean="retryingTransaction"/>
<!-- Audit Service -->
<bean id="AuditService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.audit.AuditService</value>
</property>
<property name="avmRepository">
<ref bean="avmRepository"/>
<property name="target">
<ref bean="auditService"/>
</property>
<property name="interceptorNames">
<list>
<idref local="AuditService_transaction"/>
<idref local="AuditMethodInterceptor"/>
<idref local="exceptionTranslator"/>
<idref bean="AuditService_security"/>
<idref local="AuditService_descriptor"/>
</list>
</property>
</bean>
<bean id="AuditService_transaction" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="*">${server.transaction.mode.default}</prop>
</props>
</property>
</bean>
<bean id="AuditService_descriptor" parent="AlfrescoServiceDescriptor">
<property name="interface">
<value>org.alfresco.service.cmr.audit.AuditService</value>
</property>
<property name="description">
<value>Audit Service</value>
</property>
</bean>

View File

@@ -712,4 +712,20 @@
<bean id="ScriptService_security" class="org.alfresco.repo.security.permissions.impl.AlwaysProceedMethodInterceptor" />
<!-- ================ -->
<!-- Workflow Service -->
<!-- ================ -->
<!-- TODO: Add workflow security -->
<bean id="WorkflowService_security" class="org.alfresco.repo.security.permissions.impl.AlwaysProceedMethodInterceptor" />
<!-- ============= -->
<!-- Audit Service -->
<!-- ============= -->
<!-- TODO: Add audit security -->
<bean id="AuditService_security" class="org.alfresco.repo.security.permissions.impl.AlwaysProceedMethodInterceptor" />
</beans>

View File

@@ -5,6 +5,8 @@ dir.root=./alf_data
dir.contentstore=${dir.root}/contentstore
dir.contentstore.deleted=${dir.root}/contentstore.deleted
dir.auditcontentstore=${dir.root}/audit.contentstore
# The location for lucene index files
dir.indexes=${dir.root}/lucene-indexes
@@ -54,6 +56,7 @@ lucene.lock.poll.interval=100
# Database configuration
db.schema.update=true
db.driver=org.gjt.mm.mysql.Driver
db.name=alfresco
db.url=jdbc:mysql:///${db.name}

View File

@@ -1,42 +0,0 @@
<?xml version="1.0"?>
<rss version="2.0">
<channel>
<title>Alfresco</title>
<copyright>Copyright (c) 2005 Alfresco Software, Inc. All rights reserved.</copyright>
<#assign hostname="http://localhost:8080/alfresco">
<#assign spaceref="${hostname}/navigate/browse/${space.nodeRef.storeRef.protocol}/${space.nodeRef.storeRef.identifier}/${space.nodeRef.id}">
<#assign datetimeformat="EEE, dd MMM yyyy HH:mm:ss zzz">
<link>${spaceref}</link>
<description>Recent Changes to '${space.name}'</description>
<language>en-us</language>
<lastBuildDate>${date?string(datetimeformat)}</lastBuildDate>
<pubDate>${date?string(datetimeformat)}</pubDate>
<ttl>120</ttl>
<generator>Alfresco 1.2</generator>
<image>
<title>${space.name}</title>
<width>32</width>
<height>32</height>
<link>${spaceref}</link>
<url>${hostname}${space.icon32}</url>
</image>
<#assign weekms=1000*60*60*24*7>
<#list space.childrenByXPath[".//*[subtypeOf('cm:content')]"] as child>
<#if (dateCompare(child.properties["cm:modified"], date, weekms) == 1) || (dateCompare(child.properties["cm:created"], date, weekms) == 1)>
<item>
<title>${child.properties.name}</title>
<link>${hostname}${child.url}</link>
<description>
${"<a href='${hostname}${child.url}'>"?xml}${child.properties.name}${"</a>"?xml}
<#if child.properties["cm:description"]?exists && child.properties["cm:description"] != "">
${child.properties["cm:description"]}
</#if>
</description>
<pubDate>${child.properties["cm:modified"]?string(datetimeformat)}</pubDate>
<guid isPermaLink="false">${hostname}${child.url}</guid>
</item>
</#if>
</#list>
</channel>
</rss>

View File

@@ -1,20 +0,0 @@
<#-- Table of the images found in a folder under Company Home called "Company Logos" -->
<#-- Shows each image found as inline content -->
<table>
<#list companyhome.children as child>
<#if child.isContainer && child.name = "Company Logos">
<#list child.children as image>
<#switch image.mimetype>
<#case "image/jpeg">
<#case "image/gif">
<#case "image/png">
<tr>
<td><img src="/alfresco${image.url}"></td>
</tr>
<#break>
<#default>
</#switch>
</#list>
</#if>
</#list>
</table>

View File

@@ -1,18 +1,47 @@
<#-- Shows some general info about the current document, including NodeRef and aspects applied -->
<h3>General document info</h3>
<#if document?exists>
<h4>Current Document Info:</h4>
<b>Name:</b> ${document.name}<br>
<b>Ref:</b> ${document.nodeRef}<br>
<b>Type:</b> ${document.type}<br>
<b>DBID:</b> ${document.properties["sys:node-dbid"]}<br>
<b>Content URL:</b> <a href="/alfresco${document.url}">/alfresco${document.url}</a><br>
<b>Locked:</b> <#if document.isLocked>Yes<#else>No</#if><br>
<#if hasAspect(document, "cm:countable") == 1 && document.properties['cm:counter']?exists>
<b>Counter:</b> ${document.properties['cm:counter']}<br>
</#if>
<b>Aspects:</b>
<table>
<#list document.aspects as aspect>
<tr><td>${aspect}</td></tr>
</#list>
</table>
<b>Properties:</b>
<table>
<#-- Get a list of all the property names for the document -->
<#assign props = document.properties?keys>
<#list props as t>
<#-- If the property exists -->
<#if document.properties[t]?exists>
<#-- If it is a date, format it accordingly -->
<#if document.properties[t]?is_date>
<tr><td>${t} = ${document.properties[t]?datetime}</td></tr>
<#-- If it is a boolean, format it accordingly -->
<#elseif document.properties[t]?is_boolean>
<tr><td>${t} = ${document.properties[t]?string("yes", "no")}</td></tr>
<#-- If it is a collection, enumerate it -->
<#elseif document.properties[t]?is_enumerable>
<tr><td>${t} = <#list document.properties[t] as i>${i} </#list></td></tr>
<#-- Otherwise treat it as a string -->
<#else>
<tr><td>${t} = ${document.properties[t]}</td></tr>
</#if>
</#if>
</#list>
</table>
<#else>
No document found!
</#if>

View File

@@ -1,47 +0,0 @@
<h3>=====Example Template Start=====</h3>
<b>Company Home Space:</b> ${companyhome.properties.name}
<br>
<b>My Home Space:</b> ${userhome.properties.name}
<br>
<b>Company Home children count:</b> ${companyhome.children?size}
<br>
<b>Company Home first child node name:</b> ${companyhome.children[0].properties.name}
<br>
<b>Current Document Name:</b> ${document.name}
<br>
<b>Current Space Name:</b> ${space.name}
<h4>List of child spaces in my Home Space:</h4>
<table>
<#list userhome.children as child>
<#if child.isContainer>
<tr>
<td><img src="/alfresco${child.icon32}"></td>
<td><b>${child.properties.name}</b> (${child.children?size})</td>
<td><b>Path:</b> ${child.displayPath}</td>
</tr>
</#if>
</#list>
</table>
<h4>List of docs in my Home Space (text only content shown inline, JPG images shown as thumbnails):</h4>
<table>
<#list userhome.children as child>
<#if child.isDocument>
<tr><td><img src="/alfresco${child.icon16}"></td><td><a href="/alfresco${child.url}">${child.properties.name}</a></td></tr>
<#if child.mimetype = "text/plain">
<tr><td></td><td>${child.content}</td></tr>
<#elseif child.mimetype = "image/jpeg">
<tr><td></td><td><img width=100 height=65 src="/alfresco${child.url}"></td></tr>
</#if>
</#if>
</#list>
</table>
<h4>Assoc example:</h4>
<#if userhome.children[0].assocs["cm:contains"]?exists>
${userhome.children[0].assocs["cm:contains"][0].name}
</#if>
<h3>=====Example Template End=====</h3>

View File

@@ -1,22 +0,0 @@
<#-- Displays a table of all the documents from a "Press Releases" folder under Company Home -->
<#-- Obviously this folder needs to exist and the docs in it should have the title and description fields set -->
<table>
<#list companyhome.children as child>
<#if child.isContainer && child.name = "Press Releases">
<#list child.children as doc>
<#if doc.isDocument>
<tr>
<td><h3>${doc.properties.title}</h3></td>
</tr>
<tr>
<td style="padding-left:4px"><b>${doc.properties.description}</b></td>
</tr>
<tr>
<td style="padding-left:8px"><small>${doc.content}</small></td>
</tr>
<tr><td><div style="padding:6px"></div></td></tr>
</#if>
</#list>
</#if>
</#list>
</table>

View File

@@ -1,15 +0,0 @@
<#-- List of docs in the Home Space for current user -->
<#-- If the doc mimetype is plain/text then the content is shown inline -->
<#-- If the doc mimetype is JPEG then the image is shown inline as a small thumbnail image -->
<table>
<#list userhome.children as child>
<#if child.isDocument>
<tr><td>${child.properties.name}</td></tr>
<#if child.mimetype = "text/plain">
<tr><td style='padding-left:16px'>${child.content}</td></tr>
<#elseif child.mimetype = "image/jpeg">
<tr><td style='padding-left:16px'><img width=100 height=65 src="/alfresco${child.url}"><td></tr>
</#if>
</#if>
</#list>
</table>

View File

@@ -1,26 +0,0 @@
<#-- Shows use of the childByNamePath, childrenByXPath and childrenByLuceneSearch API -->
<h3>Template Documents in 'Company Home/Data Dictionary/Presentation Templates':</h3>
<table>
<#list companyhome.childByNamePath["Data Dictionary/Presentation Templates"].children as child>
<#if child.isDocument>
<tr><td><a href="/alfresco${child.url}" target="new">${child.properties.name}</a></td></tr>
</#if>
</#list>
</table>
<h3>Folders in 'Company Home/Data Dictionary/Space Templates/Software Engineering Project':</h3>
<table>
<#list companyhome.childrenByXPath["*[@cm:name='Data Dictionary']/*[@cm:name='Space Templates']/*[@cm:name='Software Engineering Project']/*"] as child>
<#if child.isContainer>
<tr><td><img src="/alfresco${child.icon32}"> ${child.properties.name}</td></tr>
</#if>
</#list>
</table>
<h3>Lucene Search - documents containing the text 'Alfresco'</h3>
<table>
<#list companyhome.childrenByLuceneSearch["TEXT:alfresco"] as child>
<tr><td><a href="/alfresco${child.url}" target="new">${child.properties.name}</a></td></tr>
</#list>
</table>

View File

@@ -7,8 +7,8 @@
</view:aspects>
<view:properties>
<app:editInline>true</app:editInline>
<cm:description>Displays basic information about the current document</cm:description>
<cm:content>contentUrl=classpath:alfresco/templates/content/examples/doc_info.ftl|mimetype=text/plain|size=636|encoding=UTF-8</cm:content>
<cm:description>Displays useful information about the current document</cm:description>
<cm:content>contentUrl=classpath:alfresco/templates/content/examples/doc_info.ftl|mimetype=text/plain|size=1884|encoding=UTF-8</cm:content>
<cm:title>doc_info.ftl</cm:title>
<cm:name>doc_info.ftl</cm:name>
</view:properties>
@@ -84,20 +84,6 @@
</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:RSS_2.0_recent_docs.ftl">
<view:aspects>
<cm:titled></cm:titled>
<app:inlineeditable></app:inlineeditable>
</view:aspects>
<view:properties>
<app:editInline>true</app:editInline>
<cm:description>Renders a valid RSS2.0 XML document showing the documents in the current space created or modified in the last 7 days. The template should be configured to use the appropriate server and port before use.</cm:description>
<cm:content>contentUrl=classpath:alfresco/templates/content/examples/RSS_2.0_recent_docs.ftl|mimetype=text/plain|size=1917|encoding=UTF-8</cm:content>
<cm:title>RSS_2.0_recent_docs.ftl</cm:title>
<cm:name>RSS_2.0_recent_docs.ftl</cm:name>
</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:recent_docs.ftl">
<view:aspects>
<cm:titled></cm:titled>
@@ -140,18 +126,4 @@
</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:xpath_search.ftl">
<view:aspects>
<cm:titled></cm:titled>
<app:inlineeditable></app:inlineeditable>
</view:aspects>
<view:properties>
<app:editInline>true</app:editInline>
<cm:description>Example of using XPath and Lucene searches within a template.</cm:description>
<cm:content>contentUrl=classpath:alfresco/templates/content/examples/xpath_search.ftl|mimetype=text/plain|size=1109|encoding=UTF-8</cm:content>
<cm:title>xpath_search.ftl</cm:title>
<cm:name>xpath_search.ftl</cm:name>
</view:properties>
<view:associations></view:associations>
</cm:content>
</view:view>

View File

@@ -7,7 +7,7 @@
version.major=1
version.minor=4
version.revision=0
version.label=Dev
version.label=Preview
# Edition label
@@ -19,4 +19,4 @@ version.build=@build-number@
# Schema number
version.schema=20
version.schema=21

View File

@@ -6,6 +6,6 @@ log4j.appender.stdout.layout.ConversionPattern=%d %5p %c{1}:%m%n
### Set log levels.
log4j.rootLogger=warn, stdout
log4j.logger.org.hibernate=fatal
log4j.logger.org.hibernate=error
log4j.logger.org.alfresco.repo.avm=info
log4j.logger.org.springframework=warn

View File

@@ -77,6 +77,7 @@ public interface ContentModel
static final QName PROP_SYS_VERSION_SCHEMA = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionSchema");
static final QName PROP_SYS_VERSION_EDITION = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "versionEdition");
//
// Content Model Definitions
//
@@ -189,6 +190,12 @@ public interface ContentModel
public static final QName ASPECT_MOUNTED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mounted");
public static final QName PROP_MOUNTPOINT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "mountpoint");
// countable aspect
public static final QName ASPECT_COUNTABLE = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "countable");
public static final QName PROP_HITS = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "hits");
public static final QName PROP_COUNTER = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "counter");
//
// Application Model Definitions
//

View File

@@ -0,0 +1,84 @@
/*
* 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.action.executer;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
/**
* Simple action to increment an integer value. The runtime NodeService is used so any user
* can increment the counter value on a node.
*
* @author Kevin Roast
*/
public class CounterIncrementActionExecuter extends ActionExecuterAbstractBase
{
/** Runtime NodeService with no permissions protection */
private NodeService nodeService;
/**
* @param nodeService The Runtime NodeService to set.
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
*/
protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
{
// add the cm:countable aspect as required
if (this.nodeService.hasAspect(actionedUponNodeRef, ContentModel.ASPECT_COUNTABLE) == false)
{
// set the value to 1 by default
Map<QName, Serializable> props = new HashMap<QName, Serializable>(1);
props.put(ContentModel.PROP_COUNTER, 1);
this.nodeService.addAspect(actionedUponNodeRef, ContentModel.ASPECT_COUNTABLE, props);
}
else
{
// increment the value and handle possibility that no value has been set yet
int resultValue = 1;
Integer value = (Integer)this.nodeService.getProperty(actionedUponNodeRef, ContentModel.PROP_COUNTER);
if (value != null)
{
resultValue = value.intValue() + 1;
}
this.nodeService.setProperty(actionedUponNodeRef, ContentModel.PROP_COUNTER, resultValue);
}
}
/**
* @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List)
*/
protected void addParameterDefinitions(List<ParameterDefinition> paramList)
{
// none required
}
}

View File

@@ -32,9 +32,13 @@ import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.PersonService;
/**
* Action to execute a JavaScript. The script has access to the default model.
* The actionedUponNodeRef is added to the default model as the 'document' and the owning
* NodeRef is added as the 'space'.
*
* @author Kevin Roast
*/
public class ScriptActionExecutor extends ActionExecuterAbstractBase
public class ScriptActionExecuter extends ActionExecuterAbstractBase
{
public static final String NAME = "script";
public static final String PARAM_SCRIPTREF = "script-ref";

View File

@@ -60,7 +60,7 @@ public class PatchExecuter implements ApplicationListener
{
logger.info(I18NUtil.getMessage(MSG_CHECKING));
Date before = new Date(System.currentTimeMillis() - 20000L); // 20 seconds ago
Date before = new Date(System.currentTimeMillis() - 60000L); // 60 seconds ago
patchService.applyOutstandingPatches();
Date after = new Date(System .currentTimeMillis() + 20000L); // 20 seconds ahead

View File

@@ -20,7 +20,7 @@ import org.alfresco.repo.admin.patch.AbstractPatch;
import org.alfresco.service.cmr.admin.PatchException;
/**
* This patch ensures that an upgrade script has been executed. Upgrade scripts
* This patch ensures that an upgrade scriptUrl has been executed. Upgrade scripts
* should create an entry for the patch with the required ID and execution status
* so that the code in this class is never called. If called, an exception message
* is always generated.
@@ -31,26 +31,37 @@ public class SchemaUpgradeScriptPatch extends AbstractPatch
{
private static final String MSG_NOT_EXECUTED = "patch.schemaUpgradeScript.err.not_executed";
private String scriptName;
private String scriptUrl;
public SchemaUpgradeScriptPatch()
{
}
/**
* Set the name of the upgrade script to execute.
*
* @param scriptName the script filename
* @return Returns the URL of the scriptUrl that has to have been run
*/
public void setScriptName(String scriptName)
public String getScriptUrl()
{
this.scriptName = scriptName;
return scriptUrl;
}
/**
* Set the URL of the upgrade scriptUrl to execute. This is the full URL of the
* file, e.g. <b>classpath:alfresco/patch/scripts/upgrade-1.4/${hibernate.dialect.class}/patchAlfrescoSchemaUpdate-1.4-2.sql</b>
* where the <b>${hibernate.dialect.class}</b> placeholder will be substituted with the Hibernate
* <code>Dialect</code> as configured for the system.
*
* @param scriptUrl the scriptUrl filename
*/
public void setScriptUrl(String script)
{
this.scriptUrl = script;
}
protected void checkProperties()
{
super.checkProperties();
checkPropertyNotNull(scriptName, "scriptName");
checkPropertyNotNull(scriptUrl, "scriptUrl");
}
/**
@@ -59,6 +70,6 @@ public class SchemaUpgradeScriptPatch extends AbstractPatch
@Override
protected String applyInternal() throws Exception
{
throw new PatchException(MSG_NOT_EXECUTED, scriptName);
throw new PatchException(MSG_NOT_EXECUTED, scriptUrl);
}
}

View File

@@ -216,6 +216,9 @@ public class UniqueChildNamePatch extends AbstractPatch
writeLine(" Replaced with: " + usedChildName);
}
}
// clear the session to preserve memory
getSession().flush();
getSession().clear();
}
}

View File

@@ -0,0 +1,60 @@
/*
* 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.audit;
import org.alfresco.service.cmr.repository.NodeRef;
public interface ApplicationAuditModel
{
/**
* Report if audit behaviour can be determined before the method call
*
* @param auditState,
* @param mi
* @return
*/
public AuditMode beforeExecution(AuditMode auditMode, String application, String description,
NodeRef key, Object... args);
/**
* Report if audit behaviour can be determined after the method call
*
* @param auditState,
* @param mi
* @return
*/
public AuditMode afterExecution(AuditMode auditMode, String application, String description,
NodeRef key, Object... args);
/**
* Report if audit behaviour should be invoked on error. It could be we look at the error and filter - this is not supported at the moment.
*
* @param auditState,
* @param mi
* @return
*/
public AuditMode onError(AuditMode auditMode, String application, String description,
NodeRef key, Object... args);
/**
* Get the optional parameters that are to be recorded
*
* @param mi
* @return
*/
public RecordOptions getAuditRecordOptions(String application);
}

View File

@@ -0,0 +1,52 @@
/*
* 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.audit;
import org.alfresco.service.cmr.repository.NodeRef;
import org.aopalliance.intercept.MethodInvocation;
/**
* The audit component.
*
* Used by the AuditService and AuditMethodInterceptor to insert audit entries.
*
* @author Andy Hind
*/
public interface AuditComponent
{
/**
* Audit entry point for method interceptors.
*
* @param methodInvocation
*/
public Object audit(MethodInvocation methodInvocation) throws Throwable;
/**
*
* @param source -
* a string that represents the application
* @param description -
* the audit entry *
* @param key -
* a node ref to use as the key for filtering etc
* @param args -
* an arbitrary list of parameters
*/
public void audit(String source, String description, NodeRef key, Object... args);
}

View File

@@ -0,0 +1,425 @@
/*
* 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.audit;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.service.Auditable;
import org.alfresco.service.NotAuditable;
import org.alfresco.service.cmr.repository.NodeRef;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* The default audit component implementation. TODO: Implement before, after and exception filtering. At the moment these filters are ignired. TODO: Respect audit internal - at the
* moment audit internal is fixed to false.
*
* @author Andy Hind
*/
public class AuditComponentImpl implements AuditComponent
{
/**
* The application name to use for audit entries generated by method interception around public services.
*/
private static final String SYSTEM_APPLICATION = "SystemMethodInterceptor";
/**
* Logging
*/
private static Log s_logger = LogFactory.getLog(AuditComponentImpl.class);
/**
* Suspend resume auditing
*/
private static ThreadLocal<Boolean> auditFlag = new ThreadLocal<Boolean>();
/**
* IOC
*/
private PublicServiceIdentifier publicServiceIdentifier;
private AuditConfiguration auditConfiguration;
private AuditDAO auditDAO;
private AuditDAO auditFailedDAO;
private AuditModel auditModel;
/**
* Keep hold of the host where the audit occurs. TODO: Check that we get the correct address ...
*/
private InetAddress auditHost;
public AuditComponentImpl()
{
super();
// Initialise the host address
try
{
auditHost = InetAddress.getLocalHost();
}
catch (UnknownHostException e)
{
s_logger.error("Failed to get local host address", e);
}
}
/*
* IOC property setters
*/
public void setAuditDAO(AuditDAO auditDAO)
{
this.auditDAO = auditDAO;
}
public void setAuditFailedDAO(AuditDAO auditFailedDAO)
{
this.auditFailedDAO = auditFailedDAO;
}
public void setAuditConfiguration(AuditConfiguration auditConfiguration)
{
this.auditConfiguration = auditConfiguration;
}
public void setPublicServiceIdentifier(PublicServiceIdentifier publicServiceIdentifier)
{
this.publicServiceIdentifier = publicServiceIdentifier;
}
public void setAuditModel(AuditModel auditModel)
{
this.auditModel = auditModel;
}
public Object audit(MethodInvocation mi) throws Throwable
{
if ((auditFlag.get() == null) || (!auditFlag.get().booleanValue()))
{
try
{
auditFlag.set(Boolean.TRUE);
Method method = mi.getMethod();
String methodName = method.getName();
String serviceName = publicServiceIdentifier.getPublicServiceName(mi);
if (method.isAnnotationPresent(Auditable.class))
{
if (serviceName != null)
{
if (s_logger.isDebugEnabled())
{
s_logger.debug("Auditing - " + serviceName + "." + methodName);
}
return auditImpl(mi);
}
else
{
if (s_logger.isDebugEnabled())
{
s_logger.debug("UnknownService." + methodName);
}
return auditImpl(mi);
}
}
else if (method.isAnnotationPresent(NotAuditable.class))
{
if (s_logger.isDebugEnabled())
{
s_logger.debug("Not Audited. " + serviceName + "." + methodName);
}
return mi.proceed();
}
else
{
if (s_logger.isDebugEnabled())
{
s_logger.debug("Unannotated service method " + serviceName + "." + methodName);
}
throw new RuntimeException("Unannotated service method " + serviceName + "." + methodName);
}
}
finally
{
auditFlag.set(Boolean.FALSE);
}
}
else
{
return mi.proceed();
}
}
/**
* Audit a method invocation
*/
public Object auditImpl(MethodInvocation mi) throws Throwable
{
AuditInfo auditInfo = new AuditInfo(auditConfiguration);
// RecordOptions recordOptions = auditModel.getAuditRecordOptions(mi);
AuditMode auditMode = AuditMode.UNSET;
try
{
auditMode = beforeInvocation(auditMode, auditInfo, mi);
Object o = mi.proceed();
auditMode = postInvocation(auditMode, auditInfo, mi, o);
if ((auditMode == AuditMode.ALL) || (auditMode == AuditMode.SUCCESS))
{
auditDAO.audit(auditInfo);
}
return o;
}
catch (Throwable t)
{
auditMode = onError(auditMode, auditInfo, mi, t);
if ((auditMode == AuditMode.ALL) || (auditMode == AuditMode.FAIL))
{
try
{
auditFailedDAO.audit(auditInfo);
}
catch (Throwable tt)
{
throw new AuditException("Failed to audit exception", new Object[] { tt }, t);
}
}
throw t;
}
}
/**
* Helper method to set auditable properties and to determine if auditing is required when an exception is caught in the audited method.
*
* @param auditMode
* @param auditInfo
* @param t
* @return
*/
private AuditMode onError(AuditMode auditMode, AuditInfo auditInfo, MethodInvocation mi, Throwable t)
{
if ((auditMode == AuditMode.ALL) || (auditMode == AuditMode.FAIL))
{
auditInfo.setFail(true);
auditInfo.setThrowable(t);
}
return auditMode;
}
/**
* Helper method to set audited information after method invocation and to determine if auditing should take place based on the method return value.
*
* @param auditMode
* @param auditInfo
* @param mi
* @param returnObject
* @return
*/
private AuditMode postInvocation(AuditMode auditMode, AuditInfo auditInfo, MethodInvocation mi, Object returnObject)
{
if (returnObject == null)
{
auditInfo.setReturnObject(null);
}
else if (returnObject instanceof Serializable)
{
auditInfo.setReturnObject((Serializable) returnObject);
}
else
{
auditInfo.setReturnObject(returnObject.toString());
}
return auditMode;
}
/**
* Set auditable information and determine if auditing is required before method invocation. This would normally be based on the method arguments.
*
* @param auditMode
* @param auditInfo
* @param mi
* @return
*/
private AuditMode beforeInvocation(AuditMode auditMode, AuditInfo auditInfo, MethodInvocation mi)
{
AuditMode effectiveAuditMode = auditModel.beforeExecution(auditMode, mi);
if (auditMode != AuditMode.NONE)
{
String methodName = mi.getMethod().getName();
String serviceName = publicServiceIdentifier.getPublicServiceName(mi);
auditInfo.setAuditApplication(SYSTEM_APPLICATION);
auditInfo.setAuditConfiguration(auditConfiguration);
auditInfo.setAuditMethod(methodName);
auditInfo.setAuditService(serviceName);
auditInfo.setClientAddress(null);
auditInfo.setDate(new Date());
auditInfo.setFail(false);
auditInfo.setFiltered(false);
auditInfo.setHostAddress(auditHost);
auditInfo.setKeyGUID(null);
auditInfo.setKeyPropertiesAfter(null);
auditInfo.setKeyPropertiesBefore(null);
auditInfo.setKeyStore(null);
auditInfo.setMessage(null);
if (mi.getArguments() != null)
{
Serializable[] serArgs = new Serializable[mi.getArguments().length];
for (int i = 0; i < mi.getArguments().length; i++)
{
if (mi.getArguments()[i] == null)
{
serArgs[i] = null;
}
else if (mi.getArguments()[i] instanceof Serializable)
{
serArgs[i] = (Serializable) mi.getArguments()[i];
}
else
{
serArgs[i] = mi.getArguments()[i].toString();
}
}
auditInfo.setMethodArguments(serArgs);
}
auditInfo.setPath(null);
auditInfo.setReturnObject(null);
auditInfo.setSessionId(null);
auditInfo.setThrowable(null);
auditInfo.setTxId(AlfrescoTransactionSupport.getTransactionId());
auditInfo.setUserIdentifier(AuthenticationUtil.getCurrentUserName());
}
return effectiveAuditMode;
}
/**
* A simple audit entry Currently we ignore filtering here.
*/
public void audit(String source, String description, NodeRef key, Object... args)
{
AuditInfo auditInfo = new AuditInfo(auditConfiguration);
// RecordOptions recordOptions = auditModel.getAuditRecordOptions(mi);
AuditMode auditMode = AuditMode.UNSET;
try
{
auditMode = onApplicationAudit(auditMode, auditInfo, source, description, key, args);
if ((auditMode == AuditMode.ALL) || (auditMode == AuditMode.SUCCESS))
{
auditDAO.audit(auditInfo);
}
}
catch (Throwable t)
{
auditMode = onError(auditMode, auditInfo, t, source, description, key, args);
if ((auditMode == AuditMode.ALL) || (auditMode == AuditMode.FAIL))
{
try
{
auditFailedDAO.audit(auditInfo);
}
catch (Throwable tt)
{
throw new AuditException("Failed to audit exception", new Object[] { tt }, t);
}
}
throw new AuditException("Application audit failed", t);
}
}
private AuditMode onApplicationAudit(AuditMode auditMode, AuditInfo auditInfo, String source, String description,
NodeRef key, Object... args)
{
AuditMode effectiveAuditMode = auditModel.beforeExecution(auditMode, source, description, key, args);
if (auditMode != AuditMode.NONE)
{
if(source.equals(SYSTEM_APPLICATION))
{
throw new AuditException("Application audit can not use the reserved identifier "+SYSTEM_APPLICATION);
}
auditInfo.setAuditApplication(source);
auditInfo.setAuditConfiguration(auditConfiguration);
auditInfo.setAuditMethod(null);
auditInfo.setAuditService(null);
auditInfo.setClientAddress(null);
auditInfo.setDate(new Date());
auditInfo.setFail(false);
auditInfo.setFiltered(false);
auditInfo.setHostAddress(auditHost);
auditInfo.setKeyGUID(null);
auditInfo.setKeyPropertiesAfter(null);
auditInfo.setKeyPropertiesBefore(null);
auditInfo.setKeyStore(null);
auditInfo.setMessage(description);
if (args != null)
{
Serializable[] serArgs = new Serializable[args.length];
for (int i = 0; i < args.length; i++)
{
if (args[i] == null)
{
serArgs[i] = null;
}
else if (args[i] instanceof Serializable)
{
serArgs[i] = (Serializable) args[i];
}
else
{
serArgs[i] = args[i].toString();
}
}
auditInfo.setMethodArguments(serArgs);
}
auditInfo.setPath(null);
auditInfo.setReturnObject(null);
auditInfo.setSessionId(null);
auditInfo.setThrowable(null);
auditInfo.setTxId(AlfrescoTransactionSupport.getTransactionId());
auditInfo.setUserIdentifier(AuthenticationUtil.getCurrentUserName());
}
return effectiveAuditMode;
}
private AuditMode onError(AuditMode auditMode, AuditInfo auditInfo, Throwable t, String source, String description,
NodeRef key, Object... args)
{
if ((auditMode == AuditMode.ALL) || (auditMode == AuditMode.FAIL))
{
auditInfo.setFail(true);
auditInfo.setThrowable(t);
}
return auditMode;
}
}

View File

@@ -0,0 +1,36 @@
/*
* 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.audit;
import java.io.InputStream;
/**
* An audit configuration is xml content from an input stream.
*
* @author Andy Hind
*/
public interface AuditConfiguration
{
/**
* Get the XML content for the configuration as a stream.
*
* @return
*/
public abstract InputStream getInputStream();
}

View File

@@ -0,0 +1,61 @@
/*
* 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.audit;
import java.io.InputStream;
import org.springframework.beans.factory.InitializingBean;
/**
* A class to read the audit configuration from the class path
*
* @author Andy Hind
*/
public class AuditConfigurationImpl implements InitializingBean, AuditConfiguration
{
private String config;
public AuditConfigurationImpl()
{
super();
}
public void setConfig(String config)
{
this.config = config;
}
/* (non-Javadoc)
* @see org.alfresco.repo.audit.getInputStream#getInputStream()
*/
/* (non-Javadoc)
* @see org.alfresco.repo.audit.AuditConfiguration#getInputStream()
*/
public InputStream getInputStream()
{
InputStream is = this.getClass().getClassLoader().getResourceAsStream(config);
return is;
}
public void afterPropertiesSet() throws Exception
{
// Read and set up the audit configuration
}
}

View File

@@ -0,0 +1,32 @@
/*
* 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.audit;
/**
* The interface to persist audit information.
*
* @author Andy Hind
*/
public interface AuditDAO
{
/**
* Create an audit entry.
*
* @param auditInfo
*/
public void audit(AuditInfo auditInfo);
}

View File

@@ -0,0 +1,54 @@
/*
* 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.audit;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* Audit related exceptions.
*
* @author Andy Hind
*/
public class AuditException extends AlfrescoRuntimeException
{
/**
* Comment for <code>serialVersionUID</code>
*/
private static final long serialVersionUID = -7947190775692164588L;
public AuditException(String msgId)
{
super(msgId);
}
public AuditException(String msgId, Object[] msgParams)
{
super(msgId, msgParams);
}
public AuditException(String msgId, Throwable cause)
{
super(msgId, cause);
}
public AuditException(String msgId, Object[] msgParams, Throwable cause)
{
super(msgId, msgParams, cause);
}
}

View File

@@ -0,0 +1,385 @@
/*
* 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.audit;
import java.io.Serializable;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Map;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.namespace.QName;
import org.apache.log4j.Logger;
/**
* A class to encapsulate audit information supplied to the DAO layer.
*
* Null entries should be stored.
*
* @author Andy Hind
*/
public class AuditInfo
{
private static Logger s_logger = Logger.getLogger(AuditInfo.class);
/**
* The user identifier for the person who caused this audit entry
*/
private String userIdentifier;
/**
* The date for this audit entry
*/
private Date date;
/**
* The transaction id in which this entry was made
*/
private String txId;
/**
* The session is for this action
*/
private String sessionId;
/**
* The store in which the action occured.
*/
private StoreRef keyStore;
/**
* For a node ref, the node for the action.
*/
private String keyGUID;
/**
* The path of the key
*/
private String keyPath;
/**
* The audit application
* Internal uses the "System" key and will only audit method information.
*/
private String auditApplication;
/**
* The service holding the audited method.
*/
private String auditService;
/**
* The name of the audited method.
*/
private String auditMethod;
/**
* Did this entry passa filter?
* If false - all entries were being recorded.
*/
private boolean filtered;
/**
* The audit configuration in use at the time.
*/
private AuditConfiguration auditConfiguration;
/**
* The object returned by the audited method.
*/
private Serializable returnObject;
/**
* The arguments to the audited method.
*/
private Serializable[] methodArguments;
/**
* Any Exception thrown by the audited method.
*/
private Throwable throwable;
/**
* Did the audited method throw an exception?
*/
private boolean fail;
/**
* The host address for where the audit was generated.
*/
private InetAddress hostAddress;
private static InetAddress s_hostAddress;
/**
* The client address causing the audit
*/
private InetAddress clientAddress;
/**
* The properties of the key node before the method execution.
*/
private Map<QName, Serializable> keyPropertiesBefore;
/**
* The properties of the key node after the method execution.
*/
private Map<QName, Serializable> keyPropertiesAfter;
/**
* For general auditing - the audit message.
*/
private String message;
static
{
try
{
s_hostAddress = InetAddress.getLocalHost();
}
catch (UnknownHostException e)
{
s_logger.error(e);
s_hostAddress = null;
}
}
public AuditInfo(AuditConfiguration auditConfiguration)
{
super();
// Add default information
userIdentifier = AuthenticationUtil.getCurrentUserName();
date = new Date();
txId = AlfrescoTransactionSupport.getTransactionId();
sessionId = "Unavailable";
hostAddress = s_hostAddress;
}
public String getAuditApplication()
{
return auditApplication;
}
public void setAuditApplication(String auditApplication)
{
this.auditApplication = auditApplication;
}
public AuditConfiguration getAuditConfiguration()
{
return auditConfiguration;
}
public void setAuditConfiguration(AuditConfiguration auditConfiguration)
{
this.auditConfiguration = auditConfiguration;
}
public String getAuditMethod()
{
return auditMethod;
}
public void setAuditMethod(String auditMethod)
{
this.auditMethod = auditMethod;
}
public String getAuditService()
{
return auditService;
}
public void setAuditService(String auditService)
{
this.auditService = auditService;
}
public InetAddress getClientAddress()
{
return clientAddress;
}
public void setClientAddress(InetAddress clientAddress)
{
this.clientAddress = clientAddress;
}
public Date getDate()
{
return date;
}
public void setDate(Date date)
{
this.date = date;
}
public boolean isFail()
{
return fail;
}
public void setFail(boolean fail)
{
this.fail = fail;
}
public boolean isFiltered()
{
return filtered;
}
public void setFiltered(boolean filtered)
{
this.filtered = filtered;
}
public InetAddress getHostAddress()
{
return hostAddress;
}
public void setHostAddress(InetAddress hostAddress)
{
this.hostAddress = hostAddress;
}
public String getKeyGUID()
{
return keyGUID;
}
public void setKeyGUID(String keyGUID)
{
this.keyGUID = keyGUID;
}
public Map<QName, Serializable> getKeyPropertiesAfter()
{
return keyPropertiesAfter;
}
public void setKeyPropertiesAfter(Map<QName, Serializable> keyPropertiesAfter)
{
this.keyPropertiesAfter = keyPropertiesAfter;
}
public Map<QName, Serializable> getKeyPropertiesBefore()
{
return keyPropertiesBefore;
}
public void setKeyPropertiesBefore(Map<QName, Serializable> keyPropertiesBefore)
{
this.keyPropertiesBefore = keyPropertiesBefore;
}
public StoreRef getKeyStore()
{
return keyStore;
}
public void setKeyStore(StoreRef keyStore)
{
this.keyStore = keyStore;
}
public String getMessage()
{
return message;
}
public void setMessage(String message)
{
this.message = message;
}
public Serializable[] getMethodArguments()
{
return methodArguments;
}
public void setMethodArguments(Serializable[] methodArguments)
{
this.methodArguments = methodArguments;
}
public String getPath()
{
return keyPath;
}
public void setPath(String keyPath)
{
this.keyPath = keyPath;
}
public Serializable getReturnObject()
{
return returnObject;
}
public void setReturnObject(Serializable returnObject)
{
this.returnObject = returnObject;
}
public String getSessionId()
{
return sessionId;
}
public void setSessionId(String sessionId)
{
this.sessionId = sessionId;
}
public Throwable getThrowable()
{
return throwable;
}
public void setThrowable(Throwable throwable)
{
this.throwable = throwable;
}
public String getTxId()
{
return txId;
}
public void setTxId(String txId)
{
this.txId = txId;
}
public String getUserIdentifier()
{
return userIdentifier;
}
public void setUserIdentifier(String userIdentifier)
{
this.userIdentifier = userIdentifier;
}
}

View File

@@ -0,0 +1,65 @@
/*
* 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.audit;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
* A method interceptor to wrap method invocations with auditing.
*
* A single instance is used to wrap all services. If the single instance is disabled
* no auditing will be carried out and there will be minimal overhead.
*
* @author Andy Hind
*/
public class AuditMethodInterceptor implements MethodInterceptor
{
//private static Log s_logger = LogFactory.getLog(AuditMethodInterceptor.class);
private AuditComponent auditComponent;
private boolean disabled = false;
public AuditMethodInterceptor()
{
super();
}
public void setDisabled(boolean disabled)
{
this.disabled = disabled;
}
public void setAuditComponent(AuditComponent auditComponent)
{
this.auditComponent = auditComponent;
}
public Object invoke(MethodInvocation mi) throws Throwable
{
if(disabled)
{
return mi.proceed();
}
else
{
return auditComponent.audit(mi);
}
}
}

View File

@@ -0,0 +1,67 @@
/*
* 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.audit;
import org.alfresco.repo.audit.model.AuditModelException;
/**
* An enum to specify the audit mode:
*
* <ol>
* <li> ALL - all calls are audited
* <li> SUCCESS - only successful calls are audited (audited in the same TX)
* <li> FAIL - only fail calls are audited (in a new transaction)
* <li> NONE - noting is audited
* <li> UNSET
* </ol>
*
* The mode is inherited from containers if nothing is specified
*
* @author Andy Hind
*/
public enum AuditMode
{
ALL, SUCCESS, FAIL, NONE, UNSET;
public static AuditMode getAuditMode(String value)
{
if(value.equalsIgnoreCase("all"))
{
return AuditMode.ALL;
}
else if(value.equalsIgnoreCase("success"))
{
return AuditMode.SUCCESS;
}
else if(value.equalsIgnoreCase("fail"))
{
return AuditMode.FAIL;
}
else if(value.equalsIgnoreCase("none"))
{
return AuditMode.NONE;
}
else if(value.equalsIgnoreCase("unset"))
{
return AuditMode.UNSET;
}
else
{
throw new AuditModelException("Invalid audit mode: "+value);
}
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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.audit;
/**
* API for querying the audit model
*
* @author Andy Hind
*/
public interface AuditModel extends ApplicationAuditModel, MethodAuditModel
{
/**
* Constants for reading the xml model definition.
*/
/* package */final static String NAME_SPACE = "http://www.alfresco.org/model/audit/1.0";
/* package */final static String EL_AUDIT = "Audit";
/* package */final static String EL_RECORD_OPTIONS = "RecordOptions";
/* package */final static String EL_RECORD_PATH = "recordPath";
/* package */final static String EL_RECORD_FILTERS = "recordFilters";
/* package */final static String EL_RECORD_SER_RETURN_VAL = "recordSerializedReturnValue";
/* package */final static String EL_RECORD_SER_EX = "recordSerializedExceptions";
/* package */final static String EL_RECORD_SER_ARGS = "recordSerializedMethodArguments";
/* package */final static String EL_RECORD_SER_PROP_BEFORE = "recordSerializedKeyPropertiesBeforeInvocation";
/* package */final static String EL_RECORD_SER_PROP_AFTER = "recordSerializedKeyPropertiesAferInvocation";
/* package */final static String EL_FILTER = "Filter";
/* package */final static String EL_METHOD = "Method";
/* package */final static String EL_SERVICE = "Service";
/* package */final static String EL_APPLICATION = "Application";
/* package */final static String EL_EXPRESSION = "Expression";
/* package */final static String EL_PARAMETER_NAME = "ParameterName";
/* package */final static String AT_MODE = "mode";
/* package */final static String AT_ENABLED = "enabled";
/* package */final static String AT_AUDIT_INTERNAL = "auditInternal";
/* package */final static String AT_NAME = "name";
/* package */final static String AT_INVERT = "invert";
/* package */final static String AT_TYPE = "type";
}

View File

@@ -0,0 +1,88 @@
/*
* 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.audit;
import javax.transaction.UserTransaction;
import org.alfresco.service.cmr.audit.AuditService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
import org.springframework.context.ApplicationContext;
/**
* The implementation of the AuditService for application auditing.
*
* @author Andy Hind
*/
public class AuditServiceImpl implements AuditService
{
private AuditComponent auditComponent;
public AuditServiceImpl()
{
super();
}
public void setAuditComponent(AuditComponent auditComponent)
{
this.auditComponent = auditComponent;
}
public void audit(String source, String description)
{
auditComponent.audit(source, description, null, (Object[]) null);
}
public void audit(String source, String description, NodeRef key)
{
auditComponent.audit(source, description, key, (Object[]) null);
}
public void audit(String source, String description, Object... args)
{
auditComponent.audit(source, description, null, args);
}
public void audit(String source, String description, NodeRef key, Object... args)
{
auditComponent.audit(source, description, key, args);
}
public static void main(String[] args) throws Exception
{
ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
AuditService as = (AuditService) ctx.getBean("AuditService");
TransactionService txs = (TransactionService) ctx.getBean("transactionComponent");
UserTransaction tx = txs.getUserTransaction();
tx.begin();
as.audit("AuditedApp", "First");
as.audit("AuditedApp", "Second", new NodeRef(new StoreRef("test", "audit"), "id"));
as.audit("AuditedApp", "Third", new Object[]{"one", "two", "three"});
as.audit("AuditedApp", "Fourth", new NodeRef(new StoreRef("test", "audit"), "id"), new Object[]{"one", "two", "three"});
as.audit("UnAuditedApp", "First");
as.audit("UnAuditedApp", "Second", new NodeRef(new StoreRef("test", "audit"), "id"));
as.audit("UnAuditedApp", "Third", new Object[]{"one", "two", "three"});
as.audit("UnAuditedApp", "Fourth", new NodeRef(new StoreRef("test", "audit"), "id"), new Object[]{"one", "two", "three"});
tx.commit();
}
}

View File

@@ -0,0 +1,57 @@
/*
* 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.audit;
import org.aopalliance.intercept.MethodInvocation;
public interface MethodAuditModel
{
/**
* Report if audit behaviour can be determined before the method call
*
* @param auditState,
* @param mi
* @return
*/
public AuditMode beforeExecution(AuditMode auditMode, MethodInvocation mi);
/**
* Report if audit behaviour can be determined after the method call
*
* @param auditState,
* @param mi
* @return
*/
public AuditMode afterExecution(AuditMode auditMode, MethodInvocation mi);
/**
* Report if audit behaviour should be invoked on error. It could be we look at the error and filter - this is not supported at the moment.
*
* @param auditState,
* @param mi
* @return
*/
public AuditMode onError(AuditMode auditMode, MethodInvocation mi);
/**
* Get the optional parameters that are to be recorded
*
* @param mi
* @return
*/
public RecordOptions getAuditRecordOptions(MethodInvocation mi);
}

View File

@@ -0,0 +1,35 @@
/*
* 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.audit;
import org.aopalliance.intercept.MethodInvocation;
/**
* This defines the API to identify the public service upon which a method invocation has been made.
*
* @author Andy Hind
*/
public interface PublicServiceIdentifier
{
/**
* Get the name of the public service for the method invocation.
*
* @param mi
* @return
*/
public String getPublicServiceName(MethodInvocation mi);
}

View File

@@ -0,0 +1,165 @@
/*
* 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.audit;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.alfresco.service.PublicService;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
/**
* Identify public services by method invocation. Look ups are cached on a thread local as they are quite expensive. All public service names end with "Service" and start with
* capital letter. This pattern is used to filter bean names. TODO: Look at pulling out all the mappings at start up.
*
* @author Andy Hind
*/
public class PublicServiceIdentifierImpl implements PublicServiceIdentifier, BeanFactoryPostProcessor
{
private static Log s_logger = LogFactory.getLog(PublicServiceIdentifierImpl.class);
private static ThreadLocal<HashMap<Method, String>> methodToServiceMap = new ThreadLocal<HashMap<Method, String>>();
private ConfigurableListableBeanFactory beanFactory;
public PublicServiceIdentifierImpl()
{
super();
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
{
this.beanFactory = beanFactory;
}
public String getPublicServiceName(MethodInvocation mi)
{
return getServiceName(mi);
}
/**
* Cache service name look up.
*
* @param mi
* @return
* @throws BeansException
*/
private String getServiceName(MethodInvocation mi) throws BeansException
{
if (methodToServiceMap.get() == null)
{
methodToServiceMap.set(new HashMap<Method, String>());
}
Method method = mi.getMethod();
String serviceName = methodToServiceMap.get().get(method);
if (serviceName == null)
{
serviceName = getServiceNameImpl(mi);
methodToServiceMap.get().put(method, serviceName);
}
else
{
if (s_logger.isDebugEnabled())
{
s_logger.debug("Cached look up for " + serviceName + "." + method.getName());
}
}
return serviceName;
}
/**
* Do the look up by interface type.
*
* @param mi
* @return
* @throws BeansException
*/
private String getServiceNameImpl(MethodInvocation mi) throws BeansException
{
Class clazz = mi.getThis().getClass();
while (clazz != null)
{
Class[] interfaces = clazz.getInterfaces();
for (Class iFace : interfaces)
{
Class publicServiceInterface = findPublicService(iFace);
if (publicServiceInterface != null)
{
Map beans = beanFactory.getBeansOfType(publicServiceInterface);
Iterator iter = beans.entrySet().iterator();
while (iter.hasNext())
{
Map.Entry entry = (Map.Entry) iter.next();
String serviceName = (String) entry.getKey();
if ((serviceName.endsWith("Service"))
&& (Character.isUpperCase(serviceName.charAt(0)))
&& !serviceName.equals("DescriptorService"))
{
return serviceName;
}
}
}
}
clazz = clazz.getSuperclass();
}
return null;
}
/**
* We use a marker annotation to identify public interfaces.
* The interfaces have to be walked to determine if a public interface is implemented.
*
* Only one public service interface is expected.
*
* @param clazz
* @return
*/
@SuppressWarnings("unchecked")
private Class findPublicService(Class clazz)
{
if (!clazz.isInterface())
{
return null;
}
if (clazz.isAnnotationPresent(PublicService.class))
{
return clazz;
}
Class[] classes = clazz.getInterfaces();
for(Class implemented: classes)
{
Class answer = findPublicService(implemented);
if(answer != null)
{
return answer;
}
}
return null;
}
}

View File

@@ -0,0 +1,38 @@
/*
* 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.audit;
import org.alfresco.repo.audit.model.TrueFalseUnset;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.dom4j.Element;
public interface RecordOptions
{
public TrueFalseUnset getRecordFilters();
public TrueFalseUnset getRecordPath();
public TrueFalseUnset getRecordSerializedExceptions();
public TrueFalseUnset getRecordSerializedKeyPropertiesAfterEvaluation();
public TrueFalseUnset getRecordSerializedKeyPropertiesBeforeEvaluation();
public TrueFalseUnset getRecordSerializedMethodArguments();
public TrueFalseUnset getRecordSerializedReturnValue();
}

View File

@@ -0,0 +1,158 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
'-//Hibernate/Hibernate Mapping DTD 3.0//EN'
'http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd'>
<!-- Hibernate mapping for storing audit information -->
<!-- -->
<!-- This generates a simple star schema for audit -->
<!-- breakdown and roll up. -->
<!-- -->
<hibernate-mapping>
<!-- The fact -->
<class name="org.alfresco.repo.audit.hibernate.AuditFactImpl" proxy="org.alfresco.repo.audit.hibernate.AuditFact" table="alf_audit_fact" dynamic-update="false" dynamic-insert="false"
select-before-update="false" lazy="true" optimistic-lock="version">
<!-- An auto-generated id -->
<id name="id" column="id" type="long">
<generator class="native"/>
</id>
<!-- Fact properties -->
<property name="userId" column="user_id" type="string" length="255" not-null="true" index="adt_user_idx"/>
<property name="date" column="timestamp" type="timestamp" not-null="true"/>
<property name="transactionId" column="transaction_id" type="string" length="56" not-null="true"/>
<property name="sessionId" column="session_id" type="string" length="56" not-null="false"/>
<property name="storeProtocol" column="store_protocol" type="string" length="50" not-null="false" index="adt_store_idx"/>
<property name="storeId" column="store_id" type="string" length="100" not-null="false" index="adt_store_idx"/>
<property name="nodeUUID" column="node_uuid" type="string" length="36" not-null="false" index="adt_store_idx"/>
<property name="path" column="path" type="string" length="512" not-null="false"/>
<property name="filtered" column="filtered" type="boolean" not-null="true"/>
<property name="returnValue" column="return_val" type="string" length="1024" not-null="false"/>
<property name="arg1" column="arg_1" type="string" length="1024" not-null="false"/>
<property name="arg2" column="arg_2" type="string" length="1024" not-null="false"/>
<property name="arg3" column="arg_3" type="string" length="1024" not-null="false"/>
<property name="arg4" column="arg_4" type="string" length="1024" not-null="false"/>
<property name="arg5" column="arg_5" type="string" length="1024" not-null="false"/>
<property name="fail" column="fail" type="boolean" not-null="true"/>
<!-- TODO: Check the URL length ...-->
<property name="serialisedURL" column="serialized_url" type="string" length="1024" not-null="false"/>
<property name="exception" column="exception" type="string" length="1024" not-null="false"/>
<property name="hostInetAddress" column="host_address" type="string" length="1024" not-null="false"/>
<property name="clientInetAddress" column="client_address" type="string" length="1024" not-null="false"/>
<property name="message" column="message" type="string" length="1024" not-null="false"/>
<!-- Links to dimensions -->
<many-to-one name="auditDate" class="org.alfresco.repo.audit.hibernate.AuditDateImpl" not-null="true" lazy="proxy" column="audit_date_id" cascade="none" optimistic-lock="true" fetch="join"/>
<many-to-one name="auditConfig" class="org.alfresco.repo.audit.hibernate.AuditConfigImpl" not-null="true" lazy="proxy" column="audit_conf_id" cascade="none" optimistic-lock="true" fetch="join"/>
<many-to-one name="auditSource" class="org.alfresco.repo.audit.hibernate.AuditSourceImpl" not-null="true" lazy="proxy" column="audit_source_id" cascade="none" optimistic-lock="true" fetch="join"/>
</class>
<!-- The audit date dimension -->
<class name="org.alfresco.repo.audit.hibernate.AuditDateImpl" proxy="org.alfresco.repo.audit.hibernate.AuditDate" table="alf_audit_date" dynamic-update="false" dynamic-insert="false"
select-before-update="false" lazy="true" optimistic-lock="version">
<!-- An auto-generated id -->
<id name="id" column="id" type="long">
<generator class="native"/>
</id>
<!-- Date is used as the key for look up -->
<property name="date" column="date" type="date" index="adt_date_idx" not-null="true"/>
<property name="dayOfYear" column="day_of_year" type="integer" index="adt_doy_idx" not-null="true"/>
<property name="dayOfMonth" column="day_of_month" type="integer" index="adt_dom_idx" not-null="true"/>
<property name="dayOfWeek" column="day_of_week" type="integer" index="adt_dow_idx" not-null="true"/>
<property name="weekOfYear" column="week_of_year" type="integer" index="adt_woy_idx" not-null="true"/>
<property name="weekOfMonth" column="week_of_month" type="integer" index="adt_wom_idx" not-null="true"/>
<property name="month" column="month" type="integer" index="adt_m_idx" not-null="true"/>
<property name="quarter" column="quarter" type="integer" index="adt_q_idx" not-null="true"/>
<property name="halfYear" column="halfYear" type="integer" index="adt_hy_idx" not-null="true"/>
<property name="year" column="year" type="integer" index="adt_y_idx" not-null="true"/>
</class>
<!-- The audit configuration dimension -->
<class name="org.alfresco.repo.audit.hibernate.AuditConfigImpl" proxy="org.alfresco.repo.audit.hibernate.AuditConfig" table="alf_audit_config" dynamic-update="false" dynamic-insert="false"
select-before-update="false" lazy="true" optimistic-lock="version">
<!-- Max id is used to find the latest audit configuration -->
<!-- An auto-generated id -->
<id name="id" column="id" type="long">
<generator class="native"/>
</id>
<property name="configURL" column="config_url" type="string" length="256" not-null="true"/>
</class>
<!-- The audit source dimension -->
<class name="org.alfresco.repo.audit.hibernate.AuditSourceImpl" proxy="org.alfresco.repo.audit.hibernate.AuditSource" table="alf_audit_source" dynamic-update="false" dynamic-insert="false"
select-before-update="false" lazy="true" optimistic-lock="version">
<!-- An auto-generated id -->
<id name="id" column="id" type="long">
<generator class="native"/>
</id>
<!-- The app_source_idx index is used to find the app source -->
<!-- The look up is always the tripple, the service and method or just the method may be null -->
<property name="application" column="application" type="string" length="256" not-null="true" index="app_source_idx"/>
<property name="service" column="service" type="string" length="256" not-null="false" index="app_source_idx"/>
<property name="method" column="method" type="string" length="256" not-null="false" index="app_source_idx"/>
</class>
<query name="audit.GetLatestAuditDate">
select
audit_date
from
org.alfresco.repo.audit.hibernate.AuditDateImpl as audit_date
where
audit_date.id = (select max(audit_date_2.id) from org.alfresco.repo.audit.hibernate.AuditDateImpl as audit_date_2)
</query>
<query name="audit.GetLatestAuditConfig">
select
audit_config
from
org.alfresco.repo.audit.hibernate.AuditConfigImpl as audit_config
where
audit_config.id = (select max(audit_config_2.id) from org.alfresco.repo.audit.hibernate.AuditConfigImpl as audit_config_2)
</query>
<query name="audit.GetAuditSourceByApplication">
select
audit_store
from
org.alfresco.repo.audit.hibernate.AuditSourceImpl as audit_store
where
audit_store.application = :application and
audit_store.service is null and
audit_store.method is null
</query>
<query name="audit.GetAuditSourceByApplicationServiceMethod">
select
audit_store
from
org.alfresco.repo.audit.hibernate.AuditSourceImpl as audit_store
where
audit_store.application = :application and
audit_store.service = :service and
audit_store.method = :method
</query>
</hibernate-mapping>

View File

@@ -0,0 +1,41 @@
/*
* 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.audit.hibernate;
/**
* Hibernate interface for audit configuration persistence.
*
* @author Andy Hind
*/
public interface AuditConfig
{
/**
* Get the content URL for a copy of the configuration file.
*
* @return
*/
public abstract String getConfigURL();
/**
* Get the surrogate key for the configuration entry.
* The creation is managed by hibernate.
*
* @return
*/
public abstract long getId();
}

View File

@@ -0,0 +1,118 @@
/*
* 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.audit.hibernate;
import org.alfresco.util.EqualsHelper;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.beans.factory.InitializingBean;
public class AuditConfigImpl implements AuditConfig, InitializingBean
{
/**
* The hibernate generated internal key.
*/
private long id;
/**
* The URL to the content that contains the configuration file
*/
private String configURL;
public AuditConfigImpl()
{
super();
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditContig#getConfigURL()
*/
public String getConfigURL()
{
return configURL;
}
public void setConfigURL(String configURL)
{
this.configURL = configURL;
}
public void afterPropertiesSet() throws Exception
{
// Read the audit configuration
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditContig#getId()
*/
public long getId()
{
return id;
}
/**
* Internal setter for hibernate.
*
* @param id
*/
@SuppressWarnings("unused")
private void setId(long id)
{
this.id = id;
}
/**
* Helper method to get the latest audit config
*/
public static AuditConfigImpl getLatestConfig(Session session)
{
Query query = session.getNamedQuery(HibernateAuditDAO.QUERY_LAST_AUDIT_CONFIG);
return (AuditConfigImpl) query.uniqueResult();
}
@Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if(!(o instanceof AuditConfigImpl))
{
return false;
}
AuditConfigImpl other = (AuditConfigImpl)o;
return EqualsHelper.nullSafeEquals(this.configURL, other.configURL);
}
@Override
public int hashCode()
{
return configURL == null ? 0 : configURL.hashCode();
}
}

View File

@@ -0,0 +1,106 @@
/*
* 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.audit.hibernate;
import java.util.Date;
/**
* Hibernate date dimension for audit roll ups
*
* @author Andy Hind
*/
public interface AuditDate
{
/**
* Get the date
*
* @return
*/
public abstract Date getDate();
/**
* Get the day of the year.
*
* @return
*/
public abstract int getDayOfYear();
/**
* Get the day of the month.
*
* @return
*/
public abstract int getDayOfMonth();
/**
* Get the day of the week
*
* @return
*/
public abstract int getDayOfWeek();
/**
* Get the half year;
*
* @return
*/
public abstract int getHalfYear();
/**
* Get the surrogate key
*
* @return
*/
public abstract long getId();
/**
* Get the month
*
* @return
*/
public abstract int getMonth();
/**
* Get the quarter
*
* @return
*/
public abstract int getQuarter();
/**
* Get the week of the month.
*
* @return
*/
public abstract int getWeekOfMonth();
/**
* Get the week of the year.
*
* @return
*/
public abstract int getWeekOfYear();
/**
* Get the year.
* @return
*/
public abstract int getYear();
}

View File

@@ -0,0 +1,289 @@
/*
* 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.audit.hibernate;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import org.alfresco.util.EqualsHelper;
import org.hibernate.Query;
import org.hibernate.Session;
/**
* Hibernate persistence for a date dimension.
*
* @author Andy Hind
*/
public class AuditDateImpl implements AuditDate
{
/**
* Surrogate key
*/
private long id;
/**
* The date
*/
private Date date;
/**
* The day
*/
private int dayOfYear;
/**
* Day of month.
*/
private int dayOfMonth;
/**
* The day of the week
*/
private int dayOfWeek;
/**
* The week in the year
*/
private int weekOfYear;
/**
* The week of the month
*/
private int weekOfMonth;
/**
* The month in the year
*/
private int month;
/**
* The quarter in the year
*/
private int quarter;
/**
* The half year in the year
*/
private int halfYear;
/**
* The year
*/
private int year;
protected AuditDateImpl()
{
super();
}
public AuditDateImpl(Date date)
{
super();
setDate(date);
}
/* (non-Javadoc)
* @see org.alfresco.repo.audit.hibernate.AuditDate#getDate()
*/
public Date getDate()
{
return date;
}
public void setDate(Date date)
{
Calendar cal = GregorianCalendar.getInstance();
cal.setTime(date);
cal.set(Calendar.MILLISECOND, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.HOUR_OF_DAY, 0);
this.date = cal.getTime();
this.setDayOfYear(cal.get(Calendar.DAY_OF_YEAR));
this.setDayOfMonth(cal.get(Calendar.DAY_OF_MONTH));
this.setDayOfWeek(cal.get(Calendar.DAY_OF_WEEK));
this.setMonth(cal.get(Calendar.MONTH));
this.setHalfYear(getMonth() <= Calendar.JUNE ? 0 : 1);
this.setQuarter((getMonth()/3));
this.setWeekOfMonth(cal.get(Calendar.WEEK_OF_MONTH));
this.setWeekOfYear(cal.get(Calendar.WEEK_OF_YEAR));
this.setYear(cal.get(Calendar.YEAR));
}
/* (non-Javadoc)
* @see org.alfresco.repo.audit.hibernate.AuditDate#getDayOfYear()
*/
public int getDayOfYear()
{
return dayOfYear;
}
protected void setDayOfYear(int dayOfYear)
{
this.dayOfYear = dayOfYear;
}
/* (non-Javadoc)
* @see org.alfresco.repo.audit.hibernate.AuditDate#getDayOfMonth()
*/
public int getDayOfMonth()
{
return dayOfMonth;
}
protected void setDayOfMonth(int dayOfMonth)
{
this.dayOfMonth = dayOfMonth;
}
/* (non-Javadoc)
* @see org.alfresco.repo.audit.hibernate.AuditDate#getDayOfWeek()
*/
public int getDayOfWeek()
{
return dayOfWeek;
}
protected void setDayOfWeek(int dayOfWeek)
{
this.dayOfWeek = dayOfWeek;
}
/* (non-Javadoc)
* @see org.alfresco.repo.audit.hibernate.AuditDate#getHalfYear()
*/
public int getHalfYear()
{
return halfYear;
}
protected void setHalfYear(int halfYear)
{
this.halfYear = halfYear;
}
/* (non-Javadoc)
* @see org.alfresco.repo.audit.hibernate.AuditDate#getId()
*/
public long getId()
{
return id;
}
protected void setId(long id)
{
this.id = id;
}
/* (non-Javadoc)
* @see org.alfresco.repo.audit.hibernate.AuditDate#getMonth()
*/
public int getMonth()
{
return month;
}
protected void setMonth(int month)
{
this.month = month;
}
/* (non-Javadoc)
* @see org.alfresco.repo.audit.hibernate.AuditDate#getQuarter()
*/
public int getQuarter()
{
return quarter;
}
protected void setQuarter(int quarter)
{
this.quarter = quarter;
}
/* (non-Javadoc)
* @see org.alfresco.repo.audit.hibernate.AuditDate#getWeekOfMonth()
*/
public int getWeekOfMonth()
{
return weekOfMonth;
}
protected void setWeekOfMonth(int weekOfMonth)
{
this.weekOfMonth = weekOfMonth;
}
/* (non-Javadoc)
* @see org.alfresco.repo.audit.hibernate.AuditDate#getWeekOfYear()
*/
public int getWeekOfYear()
{
return weekOfYear;
}
protected void setWeekOfYear(int weekOfYear)
{
this.weekOfYear = weekOfYear;
}
/* (non-Javadoc)
* @see org.alfresco.repo.audit.hibernate.AuditDate#getYear()
*/
public int getYear()
{
return year;
}
protected void setYear(int year)
{
this.year = year;
}
@Override
public boolean equals(Object o)
{
if(this == o)
{
return true;
}
if(!(o instanceof AuditDateImpl))
{
return false;
}
AuditDateImpl that = (AuditDateImpl)o;
return EqualsHelper.nullSafeEquals(this.date, that.date);
}
@Override
public int hashCode()
{
return this.date.hashCode();
}
/**
* Helper method to get the latest audit date
*/
public static AuditDateImpl getLatestDate(Session session)
{
Query query = session.getNamedQuery(HibernateAuditDAO.QUERY_LAST_AUDIT_DATE);
return (AuditDateImpl) query.uniqueResult();
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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.audit.hibernate;
import java.util.Date;
public interface AuditFact
{
public abstract String getArg1();
public abstract String getArg2();
public abstract String getArg3();
public abstract String getArg4();
public abstract String getArg5();
public abstract AuditConfig getAuditConfig();
public abstract AuditDate getAuditDate();
public abstract AuditSource getAuditSource();
public abstract String getClientInetAddress();
public abstract Date getDate();
public abstract String getException();
public abstract boolean isFail();
public abstract boolean isFiltered();
public abstract String getHostInetAddress();
public abstract long getId();
public abstract String getMessage();
public abstract String getNodeUUID();
public abstract String getPath();
public abstract String getReturnValue();
public abstract String getSerialisedURL();
public abstract String getSessionId();
public abstract String getStoreId();
public abstract String getStoreProtocol();
public abstract String getTransactionId();
public abstract String getUserId();
}

View File

@@ -0,0 +1,578 @@
/*
* 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.audit.hibernate;
import java.util.Date;
/**
* An Audit fact Rely on standard equals and hash code as they should all be unique.
*
* @author Andy Hind
*/
public class AuditFactImpl implements AuditFact
{
private long id;
private AuditDate auditDate;
private AuditConfig auditConfig;
private AuditSource auditSource;
private String userId;
private Date date;
private String transactionId;
private String sessionId;
private String storeProtocol;
private String storeId;
private String nodeUUID;
private String path;
private boolean filtered;
private String returnValue;
private String arg1;
private String arg2;
private String arg3;
private String arg4;
private String arg5;
private boolean fail;
private String serialisedURL;
private String exception;
private String hostInetAddress;
private String clientInetAddress;
private String message;
public AuditFactImpl()
{
super();
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getArg1()
*/
public String getArg1()
{
return arg1;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setArg1(java.lang.String)
*/
public void setArg1(String arg1)
{
this.arg1 = arg1;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getArg2()
*/
public String getArg2()
{
return arg2;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setArg2(java.lang.String)
*/
public void setArg2(String arg2)
{
this.arg2 = arg2;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getArg3()
*/
public String getArg3()
{
return arg3;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setArg3(java.lang.String)
*/
public void setArg3(String arg3)
{
this.arg3 = arg3;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getArg4()
*/
public String getArg4()
{
return arg4;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setArg4(java.lang.String)
*/
public void setArg4(String arg4)
{
this.arg4 = arg4;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getArg5()
*/
public String getArg5()
{
return arg5;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setArg5(java.lang.String)
*/
public void setArg5(String arg5)
{
this.arg5 = arg5;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getAuditConfig()
*/
public AuditConfig getAuditConfig()
{
return auditConfig;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setAuditConfig(org.alfresco.repo.audit.hibernate.AuditConfig)
*/
public void setAuditConfig(AuditConfig auditConfig)
{
this.auditConfig = auditConfig;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getAuditDate()
*/
public AuditDate getAuditDate()
{
return auditDate;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setAuditDate(org.alfresco.repo.audit.hibernate.AuditDate)
*/
public void setAuditDate(AuditDate auditDate)
{
this.auditDate = auditDate;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getAuditSource()
*/
public AuditSource getAuditSource()
{
return auditSource;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setAuditSource(org.alfresco.repo.audit.hibernate.AuditSource)
*/
public void setAuditSource(AuditSource auditSource)
{
this.auditSource = auditSource;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getClientInetAddress()
*/
public String getClientInetAddress()
{
return clientInetAddress;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setClientInetAddress(java.net.InetAddress)
*/
public void setClientInetAddress(String clientInetAddress)
{
this.clientInetAddress = clientInetAddress;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getDate()
*/
public Date getDate()
{
return date;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setDate(java.util.Date)
*/
public void setDate(Date date)
{
this.date = date;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getException()
*/
public String getException()
{
return exception;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setException(java.lang.String)
*/
public void setException(String exception)
{
this.exception = exception;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#isFail()
*/
public boolean isFail()
{
return fail;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setFail(boolean)
*/
public void setFail(boolean fail)
{
this.fail = fail;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#isFiltered()
*/
public boolean isFiltered()
{
return filtered;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setFiltered(boolean)
*/
public void setFiltered(boolean filtered)
{
this.filtered = filtered;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getHostInetAddress()
*/
public String getHostInetAddress()
{
return hostInetAddress;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setHostInetAddress(java.net.InetAddress)
*/
public void setHostInetAddress(String hostInetAddress)
{
this.hostInetAddress = hostInetAddress;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getId()
*/
public long getId()
{
return id;
}
protected void setId(long id)
{
this.id = id;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getMessage()
*/
public String getMessage()
{
return message;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setMessage(java.lang.String)
*/
public void setMessage(String message)
{
this.message = message;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getNodeGUID()
*/
public String getNodeUUID()
{
return nodeUUID;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setNodeGUID(java.lang.String)
*/
public void setNodeUUID(String nodeUUID)
{
this.nodeUUID = nodeUUID;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getPath()
*/
public String getPath()
{
return path;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setPath(java.lang.String)
*/
public void setPath(String path)
{
this.path = path;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getReturnValue()
*/
public String getReturnValue()
{
return returnValue;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setReturnValue(java.lang.String)
*/
public void setReturnValue(String returnValue)
{
this.returnValue = returnValue;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getSerialisedURL()
*/
public String getSerialisedURL()
{
return serialisedURL;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setSerialisedURL(java.lang.String)
*/
public void setSerialisedURL(String serialisedURL)
{
this.serialisedURL = serialisedURL;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getSessionId()
*/
public String getSessionId()
{
return sessionId;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setSessionId(java.lang.String)
*/
public void setSessionId(String sessionId)
{
this.sessionId = sessionId;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getStoreId()
*/
public String getStoreId()
{
return storeId;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setStoreId(java.lang.String)
*/
public void setStoreId(String storeId)
{
this.storeId = storeId;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getStoreProtocol()
*/
public String getStoreProtocol()
{
return storeProtocol;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setStoreProtocol(java.lang.String)
*/
public void setStoreProtocol(String storeProtocol)
{
this.storeProtocol = storeProtocol;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getTransactionId()
*/
public String getTransactionId()
{
return transactionId;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setTransactionId(java.lang.String)
*/
public void setTransactionId(String transactionId)
{
this.transactionId = transactionId;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#getUserId()
*/
public String getUserId()
{
return userId;
}
/*
* (non-Javadoc)
*
* @see org.alfresco.repo.audit.hibernate.AuditFact#setUserId(java.lang.String)
*/
public void setUserId(String userId)
{
this.userId = userId;
}
}

View File

@@ -0,0 +1,29 @@
/*
* 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.audit.hibernate;
public interface AuditSource
{
public String getApplication();
public long getId();
public String getMethod();
public String getService();
}

View File

@@ -0,0 +1,139 @@
/*
* 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.audit.hibernate;
import org.alfresco.util.EqualsHelper;
import org.hibernate.Query;
import org.hibernate.Session;
public class AuditSourceImpl implements AuditSource
{
/**
* The surrogate key
*/
private long id;
/**
* The auditing application (System for method audits)
*/
private String application;
/**
* The audited service
*/
private String service;
/**
* The audited method
*/
private String method;
public AuditSourceImpl()
{
super();
}
public String getApplication()
{
return application;
}
public void setApplication(String application)
{
this.application = application;
}
public long getId()
{
return id;
}
protected void setId(long id)
{
this.id = id;
}
public String getMethod()
{
return method;
}
public void setMethod(String method)
{
this.method = method;
}
public String getService()
{
return service;
}
public void setService(String service)
{
this.service = service;
}
public static AuditSourceImpl getApplicationSource(Session session, String application)
{
Query query = session.getNamedQuery(HibernateAuditDAO.QUERY_AUDIT_APP_SOURCE);
query.setParameter(HibernateAuditDAO.QUERY_AUDIT_APP_SOURCE_APP, application);
return (AuditSourceImpl) query.uniqueResult();
}
public static AuditSourceImpl getApplicationSource(Session session, String application, String service,
String method)
{
Query query = session.getNamedQuery(HibernateAuditDAO.QUERY_AUDIT_METHOD_SOURCE);
query.setParameter(HibernateAuditDAO.QUERY_AUDIT_APP_SOURCE_APP, application);
query.setParameter(HibernateAuditDAO.QUERY_AUDIT_APP_SOURCE_SER, service);
query.setParameter(HibernateAuditDAO.QUERY_AUDIT_APP_SOURCE_MET, method);
return (AuditSourceImpl) query.uniqueResult();
}
@Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (!(o instanceof AuditSourceImpl))
{
return false;
}
AuditSourceImpl other = (AuditSourceImpl) o;
return EqualsHelper.nullSafeEquals(this.application, other.application)
&& EqualsHelper.nullSafeEquals(this.service, other.service)
&& EqualsHelper.nullSafeEquals(this.method, other.method);
}
@Override
public int hashCode()
{
int hash = application.hashCode();
if(service != null)
{
hash = (hash * 37) + service.hashCode();
}
if(method != null)
{
hash = (hash * 37) + method.hashCode();
}
return hash;
}
}

View File

@@ -0,0 +1,439 @@
/*
* 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.audit.hibernate;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.audit.AuditConfiguration;
import org.alfresco.repo.audit.AuditDAO;
import org.alfresco.repo.audit.AuditInfo;
import org.alfresco.repo.content.AbstractContentStore;
import org.alfresco.repo.content.ContentStore;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.transaction.TransactionalDao;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.datatype.Duration;
import org.alfresco.util.EqualsHelper;
import org.alfresco.util.GUID;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
/**
* Assumes mimetype and encoding sent to the content store (we are not saving this anywhere)
*
* @author Andy Hind
*/
public class HibernateAuditDAO extends HibernateDaoSupport implements AuditDAO, TransactionalDao
{
public static final String QUERY_LAST_AUDIT_DATE = "audit.GetLatestAuditDate";
public static final String QUERY_LAST_AUDIT_CONFIG = "audit.GetLatestAuditConfig";
public static final String QUERY_AUDIT_APP_SOURCE = "audit.GetAuditSourceByApplication";
public static final String QUERY_AUDIT_METHOD_SOURCE = "audit.GetAuditSourceByApplicationServiceMethod";
public static final String QUERY_AUDIT_APP_SOURCE_APP = "application";
public static final String QUERY_AUDIT_APP_SOURCE_SER = "service";
public static final String QUERY_AUDIT_APP_SOURCE_MET = "method";
/** a uuid identifying this unique instance */
private String uuid;
private ContentStore contentStore;
private ThreadLocal<AuditConfiguration> auditConfiguration = new ThreadLocal<AuditConfiguration>();
private ThreadLocal<Long> auditConfigImplId = new ThreadLocal<Long>();
private ThreadLocal<Long> auditDateImplId = new ThreadLocal<Long>();
private ThreadLocal<HashMap<SourceKey, Long>> sourceIds = new ThreadLocal<HashMap<SourceKey, Long>>();
public HibernateAuditDAO()
{
super();
this.uuid = GUID.generate();
}
public ContentStore getContentStore()
{
return contentStore;
}
public void setContentStore(ContentStore contentStore)
{
this.contentStore = contentStore;
}
public void audit(AuditInfo auditInfo)
{
// Find/Build the configuraton entry
AuditConfigImpl auditConfig = getAuditConfig(auditInfo);
// Find/Build any dates
AuditDateImpl auditDate = getAuditDate(auditInfo);
// Find/Build the source
AuditSourceImpl auditSource = getAuditSource(auditInfo);
// Build the new audit fact information
AuditFactImpl auditFact = new AuditFactImpl();
auditFact.setAuditConfig(auditConfig);
auditFact.setAuditDate(auditDate);
auditFact.setAuditSource(auditSource);
// Properties
Serializable[] args = auditInfo.getMethodArguments();
if (args != null)
{
switch (args.length)
{
default:
case 5:
auditFact.setArg5(getStringOrNull(args[4]));
case 4:
auditFact.setArg4(getStringOrNull(args[3]));
case 3:
auditFact.setArg3(getStringOrNull(args[2]));
case 2:
auditFact.setArg2(getStringOrNull(args[1]));
case 1:
auditFact.setArg1(getStringOrNull(args[0]));
case 0:
}
}
auditFact.setClientInetAddress(auditInfo.getClientAddress() == null ? null : auditInfo.getClientAddress()
.toString());
auditFact.setDate(auditInfo.getDate());
auditFact.setException(auditInfo.getThrowable() == null ? null : auditInfo.getThrowable().getMessage());
auditFact.setFail(auditInfo.isFail());
auditFact.setFiltered(auditInfo.isFiltered());
auditFact.setHostInetAddress(auditInfo.getHostAddress() == null ? null : auditInfo.getHostAddress().toString());
auditFact.setMessage(auditInfo.getMessage());
auditFact.setNodeUUID(auditInfo.getKeyGUID());
auditFact.setPath(auditInfo.getPath());
auditFact.setReturnValue(auditInfo.getReturnObject() == null ? null : auditInfo.getReturnObject().toString());
// auditFact.setSerialisedURL()
auditFact.setSessionId(auditInfo.getSessionId());
if (auditInfo.getKeyStore() != null)
{
auditFact.setStoreId(auditInfo.getKeyStore().getIdentifier());
auditFact.setStoreProtocol(auditInfo.getKeyStore().getProtocol());
}
auditFact.setTransactionId(auditInfo.getTxId());
auditFact.setUserId(auditInfo.getUserIdentifier());
// Save
getSession().save(auditFact);
}
private String getStringOrNull(Object o)
{
if (o == null)
{
return null;
}
else
{
return o.toString();
}
}
private AuditSourceImpl getAuditSource(AuditInfo auditInfo)
{
AuditSourceImpl auditSourceImpl;
SourceKey sourceKey = new SourceKey(auditInfo.getAuditApplication(), auditInfo.getAuditService(), auditInfo.getAuditMethod());
if(sourceIds.get() == null)
{
sourceIds.set(new HashMap<SourceKey, Long>());
}
Long id = sourceIds.get().get(sourceKey);
if(id != null)
{
auditSourceImpl = (AuditSourceImpl) getSession().get(AuditSourceImpl.class, id.longValue());
if(auditSourceImpl != null)
{
return auditSourceImpl;
}
}
if ((auditInfo.getAuditService() != null)
&& (auditInfo.getAuditService().length() > 0) && (auditInfo.getAuditMethod() != null)
&& (auditInfo.getAuditMethod().length() > 0))
{
auditSourceImpl = AuditSourceImpl.getApplicationSource(getSession(), auditInfo.getAuditApplication(),
auditInfo.getAuditService(), auditInfo.getAuditMethod());
if (auditSourceImpl == null)
{
auditSourceImpl = new AuditSourceImpl();
auditSourceImpl.setApplication(auditInfo.getAuditApplication());
auditSourceImpl.setService(auditInfo.getAuditService());
auditSourceImpl.setMethod(auditInfo.getAuditMethod());
getSession().save(auditSourceImpl);
}
}
else
{
auditSourceImpl = AuditSourceImpl.getApplicationSource(getSession(), auditInfo.getAuditApplication());
if (auditSourceImpl == null)
{
auditSourceImpl = new AuditSourceImpl();
auditSourceImpl.setApplication(auditInfo.getAuditApplication());
getSession().save(auditSourceImpl);
}
}
sourceIds.get().put(sourceKey, Long.valueOf(auditSourceImpl.getId()));
return auditSourceImpl;
}
private AuditDateImpl getAuditDate(AuditInfo auditInfo)
{
Calendar cal = GregorianCalendar.getInstance();
cal.setTime(auditInfo.getDate());
cal.set(Calendar.MILLISECOND, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.HOUR_OF_DAY, 0);
Date required = cal.getTime();
AuditDateImpl auditDate;
if (auditDateImplId.get() == null)
{
auditDate = AuditDateImpl.getLatestDate(getSession());
if (auditDate == null)
{
// The first entry ever so we just make it
auditDate = new AuditDateImpl(auditInfo.getDate());
getSession().save(auditDate);
}
auditDateImplId.set(Long.valueOf(auditDate.getId()));
}
else
{
auditDate = (AuditDateImpl) getSession().get(AuditDateImpl.class, auditDateImplId.get().longValue());
if ((auditDate == null) || (!required.equals(auditDate.getDate())))
{
auditDate = AuditDateImpl.getLatestDate(getSession());
if (auditDate == null)
{
// The first entry ever so we just make it
auditDate = new AuditDateImpl(auditInfo.getDate());
getSession().save(auditDate);
}
auditDateImplId.set(Long.valueOf(auditDate.getId()));
}
}
while (!required.equals(auditDate.getDate()))
{
Date nextDate = Duration.add(auditDate.getDate(), new Duration("P1D"));
auditDate = new AuditDateImpl(nextDate);
getSession().save(auditDate);
auditDateImplId.set(Long.valueOf(auditDate.getId()));
}
return auditDate;
}
private AuditConfigImpl getAuditConfig(AuditInfo auditInfo)
{
AuditConfigImpl auditConfig;
if ((auditConfiguration.get() == null) || (auditConfiguration.get() != auditInfo.getAuditConfiguration()))
{
auditConfig = AuditConfigImpl.getLatestConfig(getSession());
if (auditConfig == null)
{
auditConfig = createNewAuditConfigImpl(auditInfo);
}
else
{
InputStream current = new BufferedInputStream(auditInfo.getAuditConfiguration().getInputStream());
ContentReader reader = contentStore.getReader(auditConfig.getConfigURL());
reader.setMimetype(MimetypeMap.MIMETYPE_XML);
reader.setEncoding("UTF-8");
InputStream last = new BufferedInputStream(reader.getContentInputStream());
int currentValue = -2;
int lastValue = -2;
try
{
while ((currentValue != -1) && (lastValue != -1) && (currentValue == lastValue))
{
currentValue = current.read();
lastValue = last.read();
}
}
catch (IOException e)
{
throw new AlfrescoRuntimeException(
"Failed to read and validate current audit configuration against the last", e);
}
if (currentValue != lastValue)
{
// Files are different - require a new entry
auditConfig = createNewAuditConfigImpl(auditInfo);
}
else
{
// No change
}
}
auditConfigImplId.set(Long.valueOf(auditConfig.getId()));
auditConfiguration.set(auditInfo.getAuditConfiguration());
}
else
{
auditConfig = (AuditConfigImpl) getSession()
.get(AuditConfigImpl.class, auditConfigImplId.get().longValue());
if (auditConfig == null)
{
auditConfig = createNewAuditConfigImpl(auditInfo);
}
}
return auditConfig;
}
private AuditConfigImpl createNewAuditConfigImpl(AuditInfo auditInfo)
{
AuditConfigImpl auditConfig = new AuditConfigImpl();
InputStream is = new BufferedInputStream(auditInfo.getAuditConfiguration().getInputStream());
String url = AbstractContentStore.createNewUrl();
ContentWriter writer = contentStore.getWriter(null, url);
writer.setMimetype(MimetypeMap.MIMETYPE_XML);
writer.setEncoding("UTF-8");
writer.putContent(is);
auditConfig.setConfigURL(url);
getSession().save(auditConfig);
return auditConfig;
}
/**
* Checks equality by type and uuid
*/
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
else if (!(obj instanceof HibernateAuditDAO))
{
return false;
}
HibernateAuditDAO that = (HibernateAuditDAO) obj;
return this.uuid.equals(that.uuid);
}
/**
* @see #uuid
*/
public int hashCode()
{
return uuid.hashCode();
}
/**
* Does this <tt>Session</tt> contain any changes which must be synchronized with the store?
*
* @return true => changes are pending
*/
public boolean isDirty()
{
// create a callback for the task
HibernateCallback callback = new HibernateCallback()
{
public Object doInHibernate(Session session)
{
return session.isDirty();
}
};
// execute the callback
return ((Boolean) getHibernateTemplate().execute(callback)).booleanValue();
}
/**
* Just flushes the session
*/
public void flush()
{
getSession().flush();
}
static class SourceKey
{
String application;
String service;
String method;
SourceKey(String application, String service, String method)
{
this.application = application;
this.service = service;
this.method = method;
}
@Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (!(this instanceof SourceKey))
{
return false;
}
SourceKey other = (SourceKey) o;
return EqualsHelper.nullSafeEquals(this.application, other.application)
&& EqualsHelper.nullSafeEquals(this.service, other.service)
&& EqualsHelper.nullSafeEquals(this.method, other.method);
}
@Override
public int hashCode()
{
int hash = application.hashCode();
if (service != null)
{
hash = (hash * 37) + service.hashCode();
}
if (method != null)
{
hash = (hash * 37) + method.hashCode();
}
return hash;
}
}
}

View File

@@ -0,0 +1,203 @@
/*
* 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.audit.model;
import org.alfresco.repo.audit.AuditMode;
import org.alfresco.repo.audit.AuditModel;
import org.alfresco.repo.audit.PublicServiceIdentifier;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Attribute;
import org.dom4j.Element;
public abstract class AbstractAuditEntry
{
private static Log s_logger = LogFactory.getLog(AbstractAuditEntry.class);
private RecordOptionsImpl recordOptions = null;
private AbstractFilter filter = null;
private AuditMode auditMode = AuditMode.UNSET;
private TrueFalseUnset enabled = TrueFalseUnset.UNSET;
private TrueFalseUnset auditInternal = TrueFalseUnset.UNSET;
private AbstractAuditEntry parent;
private PublicServiceIdentifier publicServiceIdentifier;
public AbstractAuditEntry()
{
super();
}
PublicServiceIdentifier getPublicServiceIdentifier()
{
return publicServiceIdentifier;
}
public void setPublicServiceIdentifier(PublicServiceIdentifier publicServiceIdentifier)
{
this.publicServiceIdentifier = publicServiceIdentifier;
}
void configure(AbstractAuditEntry parent, Element element, NamespacePrefixResolver namespacePrefixResolver)
{
this.parent = parent;
Attribute auditModeAttribute = element.attribute(AuditModel.AT_MODE);
if (auditModeAttribute != null)
{
auditMode = AuditMode.getAuditMode(auditModeAttribute.getValue());
}
if(s_logger.isDebugEnabled())
{
s_logger.debug("Audit Mode = "+auditMode);
}
Attribute enabledAttribute = element.attribute(AuditModel.AT_ENABLED);
if (enabledAttribute != null)
{
enabled = TrueFalseUnset.getTrueFalseUnset(enabledAttribute.getValue());
}
if(s_logger.isDebugEnabled())
{
s_logger.debug("Enabled = "+enabled);
}
Attribute auditInternalAttribute = element.attribute(AuditModel.AT_AUDIT_INTERNAL);
if (auditInternalAttribute != null)
{
auditInternal = TrueFalseUnset.getTrueFalseUnset(auditInternalAttribute.getValue());
}
if(s_logger.isDebugEnabled())
{
s_logger.debug("Audit Internal = "+auditInternal);
}
// Make record options
Element recordOptionElement = element.element(AuditModel.EL_RECORD_OPTIONS);
if (recordOptionElement != null)
{
recordOptions = new RecordOptionsImpl();
recordOptions.configure(recordOptionElement, namespacePrefixResolver);
}
if(s_logger.isDebugEnabled())
{
s_logger.debug("Record Options = "+recordOptions);
}
// Make filters
Element filterElement = element.element(AuditModel.EL_FILTER);
if (filterElement != null)
{
filter = AbstractFilter.createFilter(filterElement, namespacePrefixResolver);
}
if(s_logger.isDebugEnabled())
{
s_logger.debug("Filter = "+filter);
}
}
/* package */TrueFalseUnset getAuditInternal()
{
return auditInternal;
}
/* package */AuditMode getAuditMode()
{
return auditMode;
}
/* package */TrueFalseUnset getEnabled()
{
return enabled;
}
/* package */AbstractFilter getFilter()
{
return filter;
}
/* package */AbstractAuditEntry getParent()
{
return parent;
}
/* package */RecordOptionsImpl getRecordOptions()
{
return recordOptions;
}
protected AuditMode getEffectiveAuditMode()
{
AuditMode auditMode;
if (checkEnabled() == TrueFalseUnset.TRUE)
{
auditMode = getAuditModeOrParentAuditMode();
}
else
{
auditMode = AuditMode.NONE;
}
if(s_logger.isDebugEnabled())
{
s_logger.debug("... Effective audit mode is = "+auditMode);
}
return auditMode;
}
private AuditMode getAuditModeOrParentAuditMode()
{
AuditMode auditMode = getAuditMode();
if(s_logger.isDebugEnabled())
{
s_logger.debug("... ... audit mode is = "+auditMode);
}
if (auditMode == AuditMode.UNSET)
{
if (getParent() == null)
{
return AuditMode.UNSET;
}
else
{
return getParent().getAuditModeOrParentAuditMode();
}
}
else
{
return auditMode;
}
}
private TrueFalseUnset checkEnabled()
{
TrueFalseUnset effective = getEnabled();
if (getParent() != null)
{
if ((getParent().checkEnabled() == TrueFalseUnset.TRUE) && (effective != TrueFalseUnset.FALSE))
{
return TrueFalseUnset.TRUE;
}
}
else
{
if (effective == TrueFalseUnset.TRUE)
{
return TrueFalseUnset.TRUE;
}
}
return TrueFalseUnset.FALSE;
}
}

View File

@@ -0,0 +1,92 @@
/*
* 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.audit.model;
import org.alfresco.repo.audit.AuditModel;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Attribute;
import org.dom4j.Element;
/**
* The base class for filtering.
*
* This supports negating the filter, ie NOT.
*
* @author Andy Hind
*/
public abstract class AbstractFilter implements XMLModelElement
{
private static Log s_logger = LogFactory.getLog(AbstractFilter.class);
private boolean invert = false;
public AbstractFilter()
{
super();
}
public static AbstractFilter createFilter(Element filterElement, NamespacePrefixResolver namespacePrefixResolver)
{
AbstractFilter filter;
Attribute typeAttribute = filterElement.attribute(AuditModel.AT_TYPE);
if (typeAttribute == null)
{
throw new AuditModelException("A filter must specify it concrete type using xsi:type");
}
if (typeAttribute.getStringValue().endsWith("FilterSet"))
{
filter = new FilterSet();
}
else if (typeAttribute.getStringValue().endsWith("KeyFilter"))
{
filter = new KeyFilter();
}
else if (typeAttribute.getStringValue().endsWith("ParameterFilter"))
{
filter = new ParameterFilter();
}
else
{
throw new AuditModelException(
"Invalid filter type. It must be one of: FilterSet, KeyFilter, ParameterFilter ");
}
filter.configure(filterElement, namespacePrefixResolver);
return filter;
}
public void configure(Element element, NamespacePrefixResolver namespacePrefixResolver)
{
Attribute invertAttribute = element.attribute(AuditModel.AT_INVERT);
if (invertAttribute != null)
{
invert = Boolean.valueOf(invertAttribute.getStringValue()).booleanValue();
}
else
{
invert = false;
}
}
/* package */boolean isInvert()
{
return invert;
}
}

View File

@@ -0,0 +1,63 @@
/*
* 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.audit.model;
import org.alfresco.repo.audit.AuditModel;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Attribute;
import org.dom4j.Element;
public abstract class AbstractNamedAuditEntry extends AbstractAuditEntry
{
private static Log s_logger = LogFactory.getLog(AbstractNamedAuditEntry.class);
private String name;
public AbstractNamedAuditEntry()
{
super();
}
@Override
void configure(AbstractAuditEntry parent, Element element, NamespacePrefixResolver namespacePrefixResolver)
{
Attribute nameAttribute = element.attribute(AuditModel.AT_NAME);
if (nameAttribute != null)
{
name = nameAttribute.getStringValue();
}
else
{
throw new AuditModelException("The name attribute is mandatory");
}
if(s_logger.isDebugEnabled())
{
s_logger.debug("Name = "+name);
}
super.configure(parent, element, namespacePrefixResolver);
}
/* package */String getName()
{
return name;
}
}

View File

@@ -0,0 +1,60 @@
/*
* 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.audit.model;
import org.alfresco.repo.audit.ApplicationAuditModel;
import org.alfresco.repo.audit.AuditMode;
import org.alfresco.repo.audit.RecordOptions;
import org.alfresco.service.cmr.repository.NodeRef;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class ApplicationAuditEntry extends AbstractNamedAuditEntry implements ApplicationAuditModel
{
private static Log s_logger = LogFactory.getLog(ApplicationAuditEntry.class);
public ApplicationAuditEntry()
{
super();
}
public AuditMode beforeExecution(AuditMode auditMode, String application, String description, NodeRef key, Object... args)
{
if(s_logger.isDebugEnabled())
{
s_logger.debug("Evaluating if application is audited ..."+application);
}
return getEffectiveAuditMode();
}
public AuditMode afterExecution(AuditMode auditMode, String application, String description, NodeRef key, Object... args)
{
throw new UnsupportedOperationException();
}
public AuditMode onError(AuditMode auditMode, String application, String description, NodeRef key, Object... args)
{
throw new UnsupportedOperationException();
}
public RecordOptions getAuditRecordOptions(String application)
{
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,220 @@
/*
* 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.audit.model;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.alfresco.repo.audit.AuditConfiguration;
import org.alfresco.repo.audit.AuditMode;
import org.alfresco.repo.audit.AuditModel;
import org.alfresco.repo.audit.RecordOptions;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.InitializingBean;
public class AuditEntry extends AbstractAuditEntry implements InitializingBean, AuditModel
{
private static Log s_logger = LogFactory.getLog(AuditEntry.class);
private Map<String, ServiceAuditEntry> services = new HashMap<String, ServiceAuditEntry>();
private Map<String, ApplicationAuditEntry> applications = new HashMap<String, ApplicationAuditEntry>();
private AuditConfiguration auditConfiguration;
private NamespacePrefixResolver namespacePrefixResolver;
public AuditEntry()
{
super();
}
public AuditConfiguration getAuditConfiguration()
{
return auditConfiguration;
}
public void setAuditConfiguration(AuditConfiguration auditConfiguration)
{
this.auditConfiguration = auditConfiguration;
}
public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver)
{
this.namespacePrefixResolver = namespacePrefixResolver;
}
public void afterPropertiesSet() throws Exception
{
Document document = createDocument();
Element root = document.getRootElement();
// Check it is the correct thing
configure(null, root, namespacePrefixResolver);
}
@Override
void configure(AbstractAuditEntry parent, Element element, NamespacePrefixResolver namespacePrefixResolver)
{
if (!element.getNamespaceURI().equals(AuditModel.NAME_SPACE))
{
throw new AuditModelException("Audit model has incorrect name space");
}
if (!element.getName().equals(AuditModel.EL_AUDIT))
{
throw new AuditModelException("Audit model has incorrect root node");
}
if(s_logger.isDebugEnabled())
{
s_logger.debug("Audit configuration");
}
super.configure(parent, element, namespacePrefixResolver);
// Add services
if(s_logger.isDebugEnabled())
{
s_logger.debug("Adding services ...");
}
for (Iterator nsit = element.elementIterator(AuditModel.EL_SERVICE); nsit.hasNext(); /**/)
{
Element serviceElement = (Element) nsit.next();
ServiceAuditEntry service = new ServiceAuditEntry();
service.configure(this, serviceElement, namespacePrefixResolver);
services.put(service.getName(), service);
}
// Add Applications
if(s_logger.isDebugEnabled())
{
s_logger.debug("Adding applications ...");
}
for (Iterator nsit = element.elementIterator(AuditModel.EL_APPLICATION); nsit.hasNext(); /**/)
{
Element applicationElement = (Element) nsit.next();
ApplicationAuditEntry application = new ApplicationAuditEntry();
application.configure(this, applicationElement, namespacePrefixResolver);
applications.put(application.getName(), application);
}
}
public AuditMode beforeExecution(AuditMode auditMode, MethodInvocation mi)
{
String serviceName = getPublicServiceIdentifier().getPublicServiceName(mi);
ServiceAuditEntry service = services.get(serviceName);
if(service != null)
{
return service.beforeExecution(auditMode, mi);
}
else
{
if(s_logger.isDebugEnabled())
{
s_logger.debug("No specific audit entry for service "+serviceName);
}
return getEffectiveAuditMode();
}
}
public AuditMode afterExecution(AuditMode auditMode, MethodInvocation mi)
{
throw new UnsupportedOperationException();
}
public RecordOptions getAuditRecordOptions(MethodInvocation mi)
{
throw new UnsupportedOperationException();
}
public AuditMode onError(AuditMode auditMode, MethodInvocation mi)
{
throw new UnsupportedOperationException();
}
private Document createDocument()
{
InputStream is = auditConfiguration.getInputStream();
if (is == null)
{
throw new AuditModelException("Audit configuration could not be opened");
}
SAXReader reader = new SAXReader();
try
{
Document document = reader.read(is);
is.close();
return document;
}
catch (DocumentException e)
{
throw new AuditModelException("Failed to create audit model document ", e);
}
catch (IOException e)
{
throw new AuditModelException("Failed to close audit model document ", e);
}
}
public AuditMode beforeExecution(AuditMode auditMode, String application, String description, NodeRef key, Object... args)
{
ApplicationAuditEntry aae = applications.get(application);
if(aae != null)
{
return aae.beforeExecution(auditMode, application, description, key, args);
}
else
{
if(s_logger.isDebugEnabled())
{
s_logger.debug("No specific audit entry for application "+application);
}
return getEffectiveAuditMode();
}
}
public AuditMode afterExecution(AuditMode auditMode, String application, String description, NodeRef key, Object... args)
{
throw new UnsupportedOperationException();
}
public AuditMode onError(AuditMode auditMode, String application, String description, NodeRef key, Object... args)
{
throw new UnsupportedOperationException();
}
public RecordOptions getAuditRecordOptions(String application)
{
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,54 @@
/*
* 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.audit.model;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* Exceptions from the audit model package.
*
* @author Andy Hind
*/
public class AuditModelException extends AlfrescoRuntimeException
{
/**
* Comment for <code>serialVersionUID</code>
*/
private static final long serialVersionUID = -2527034441058184109L;
public AuditModelException(String msgId)
{
super(msgId);
}
public AuditModelException(String msgId, Object[] msgParams)
{
super(msgId, msgParams);
}
public AuditModelException(String msgId, Throwable cause)
{
super(msgId, cause);
}
public AuditModelException(String msgId, Object[] msgParams, Throwable cause)
{
super(msgId, msgParams, cause);
}
}

View File

@@ -0,0 +1,72 @@
/*
* 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.audit.model;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.alfresco.repo.audit.AuditModel;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Attribute;
import org.dom4j.Element;
/**
* This groups a set of filters together using AND or OR. They are evaluated in definition order with short cut evaluation if possible. The default beahviour is to or Filters
* together.
*
* @author Andy Hind
*/
public class FilterSet extends AbstractFilter implements XMLModelElement
{
private static Log s_logger = LogFactory.getLog(FilterSet.class);
private List<AbstractFilter> filters = new ArrayList<AbstractFilter>();
private FilterSetMode mode = FilterSetMode.OR;
public FilterSet()
{
super();
}
@Override
public void configure(Element element, NamespacePrefixResolver namespacePrefixResolver)
{
super.configure(element, namespacePrefixResolver);
// Mode
Attribute modeAttribute = element.attribute(AuditModel.AT_MODE);
if (modeAttribute != null)
{
mode = FilterSetMode.getFilterSetMode(modeAttribute.getStringValue());
}
// Filters
for (Iterator nsit = element.elementIterator(AuditModel.EL_FILTER); nsit.hasNext(); /**/)
{
Element filterElement = (Element) nsit.next();
AbstractFilter filter = AbstractFilter.createFilter(filterElement, namespacePrefixResolver);
filters.add(filter);
}
}
}

View File

@@ -0,0 +1,43 @@
/*
* 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.audit.model;
/**
* The enum to define if elements of a filter set are combined using AND or OR.
*
* @author Andy Hind
*/
public enum FilterSetMode
{
AND, OR;
public static FilterSetMode getFilterSetMode(String value)
{
if(value.equalsIgnoreCase("or"))
{
return FilterSetMode.OR;
}
else if(value.equalsIgnoreCase("or"))
{
return FilterSetMode.AND;
}
else
{
throw new AuditModelException("Invalid FilterSetMode: "+value);
}
}
}

View File

@@ -0,0 +1,70 @@
/*
* 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.audit.model;
import org.alfresco.repo.audit.AuditModel;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Attribute;
import org.dom4j.Element;
public class KeyFilter extends AbstractFilter
{
private static Log s_logger = LogFactory.getLog(KeyFilter.class);
private String expression;
private KeyFilterMode keyFilterMode;
public KeyFilter()
{
super();
}
@Override
public void configure(Element element, NamespacePrefixResolver namespacePrefixResolver)
{
super.configure(element, namespacePrefixResolver);
// Filter mode
Attribute keyFilterTypeAttribute = element.attribute(AuditModel.AT_MODE);
if(keyFilterTypeAttribute != null)
{
keyFilterMode = KeyFilterMode.getKeyFilterMode(keyFilterTypeAttribute.getStringValue());
}
else
{
keyFilterMode = KeyFilterMode.ALL;
}
// Expression
Element expressionElement = element.element(AuditModel.EL_EXPRESSION);
if(expressionElement == null)
{
throw new AuditModelException("An expression is mandatory for a key filter");
}
else
{
expression = expressionElement.getText();
}
}
}

View File

@@ -0,0 +1,86 @@
/*
* 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.audit.model;
/**
* This enum defines the type of restriction to apply to filter based on the key node ref.
*
* This restriction can be based upon:
*
* <ol>
* <li> The path to the node
* <li> The type of the node
* <li> The presence of an aspect
* <li> The NodeRef of the node
* <li> An XPATH expression evaluated in the context of the node with the return tested for the node.
* e.g. ".[@cm:content = 'woof']"
* <li> A simple value for equality tests given a non node argument
* <li> The protocol of the store containing the node
* <li> The identifier of the store containing the node
* <li> Or no restriction
* </ol>
*
* @author Andy Hind
*/
public enum KeyFilterMode
{
PATH, TYPE, ASPECT, NODE_REF, ALL, XPATH, VALUE, STORE_PROTOCOL, STORE_IDENTIFIER;
public static KeyFilterMode getKeyFilterMode(String value)
{
if(value.equalsIgnoreCase("path"))
{
return KeyFilterMode.PATH;
}
else if(value.equalsIgnoreCase("type"))
{
return KeyFilterMode.TYPE;
}
else if(value.equalsIgnoreCase("aspect"))
{
return KeyFilterMode.ASPECT;
}
else if(value.equalsIgnoreCase("node_ref"))
{
return KeyFilterMode.NODE_REF;
}
else if(value.equalsIgnoreCase("all"))
{
return KeyFilterMode.ALL;
}
else if(value.equalsIgnoreCase("xpath"))
{
return KeyFilterMode.XPATH;
}
else if(value.equalsIgnoreCase("value"))
{
return KeyFilterMode.VALUE;
}
else if(value.equalsIgnoreCase("store_protocol"))
{
return KeyFilterMode.STORE_PROTOCOL;
}
else if(value.equalsIgnoreCase("store_identifier"))
{
return KeyFilterMode.STORE_IDENTIFIER;
}
else
{
throw new AuditModelException("Unknown KeyFilterMode: "+value);
}
}
}

View File

@@ -0,0 +1,59 @@
/*
* 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.audit.model;
import org.alfresco.repo.audit.AuditMode;
import org.alfresco.repo.audit.MethodAuditModel;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class MethodAuditEntry extends AbstractNamedAuditEntry implements MethodAuditModel
{
private static Log s_logger = LogFactory.getLog(MethodAuditEntry.class);
public MethodAuditEntry()
{
super();
// TODO Auto-generated constructor stub
}
public AuditMode beforeExecution(AuditMode auditMode, MethodInvocation mi)
{
if(s_logger.isDebugEnabled())
{
s_logger.debug("Evaluating if method is audited ..."+((ServiceAuditEntry)getParent()).getName()+"."+getName());
}
return getEffectiveAuditMode();
}
public AuditMode afterExecution(AuditMode auditMode, MethodInvocation mi)
{
throw new UnsupportedOperationException();
}
public AuditMode onError(AuditMode auditMode, MethodInvocation mi)
{
throw new UnsupportedOperationException();
}
public RecordOptionsImpl getAuditRecordOptions(MethodInvocation mi)
{
throw new UnsupportedOperationException();
}
}

View File

@@ -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.audit.model;
import org.alfresco.repo.audit.AuditModel;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Element;
public class ParameterFilter extends KeyFilter implements XMLModelElement
{
private static Log s_logger = LogFactory.getLog(ParameterFilter.class);
private QName parameterName;
public ParameterFilter()
{
super();
}
@Override
public void configure(Element element, NamespacePrefixResolver namespacePrefixResolver)
{
super.configure(element, namespacePrefixResolver);
Element parameterNameElement = element.element(AuditModel.EL_PARAMETER_NAME);
if(parameterNameElement == null)
{
throw new AuditModelException("A parameter is mandatory for a parameter filter");
}
else
{
String stringQName = parameterNameElement.getStringValue();
if (stringQName.charAt(1) == '{')
{
parameterName = QName.createQName(stringQName);
}
else
{
parameterName = QName.createQName(stringQName);
}
}
}
}

View File

@@ -0,0 +1,189 @@
/*
* 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.audit.model;
import org.alfresco.repo.audit.AuditModel;
import org.alfresco.repo.audit.RecordOptions;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Element;
public class RecordOptionsImpl implements XMLModelElement, RecordOptions
{
private static Log s_logger = LogFactory.getLog(RecordOptionsImpl.class);
private TrueFalseUnset recordPath = TrueFalseUnset.UNSET;
private TrueFalseUnset recordFilters = TrueFalseUnset.UNSET;
private TrueFalseUnset recordSerializedReturnValue = TrueFalseUnset.UNSET;
private TrueFalseUnset recordSerializedExceptions = TrueFalseUnset.UNSET;
private TrueFalseUnset recordSerializedMethodArguments = TrueFalseUnset.UNSET;
private TrueFalseUnset recordSerializedKeyPropertiesBeforeEvaluation = TrueFalseUnset.UNSET;
private TrueFalseUnset recordSerializedKeyPropertiesAfterEvaluation = TrueFalseUnset.UNSET;
public RecordOptionsImpl()
{
super();
}
public static RecordOptionsImpl mergeRecordOptions(RecordOptions primary, RecordOptions secondary)
{
RecordOptionsImpl answer = new RecordOptionsImpl();
setOptions(answer, primary, true);
setOptions(answer, secondary, false);
return answer;
}
private static void setOptions(RecordOptionsImpl on, RecordOptions from, boolean force)
{
if(force || on.recordFilters.equals( TrueFalseUnset.UNSET))
{
on.recordFilters = from.getRecordFilters();
}
if(force || on.recordPath.equals( TrueFalseUnset.UNSET))
{
on.recordPath = from.getRecordPath();
}
if(force || on.recordSerializedExceptions.equals( TrueFalseUnset.UNSET))
{
on.recordSerializedExceptions = from.getRecordSerializedExceptions();
}
if(force || on.recordSerializedKeyPropertiesAfterEvaluation.equals( TrueFalseUnset.UNSET))
{
on.recordSerializedKeyPropertiesAfterEvaluation = from.getRecordSerializedKeyPropertiesAfterEvaluation();
}
if(force || on.recordSerializedKeyPropertiesBeforeEvaluation.equals( TrueFalseUnset.UNSET))
{
on.recordSerializedKeyPropertiesBeforeEvaluation = from.getRecordSerializedKeyPropertiesBeforeEvaluation();
}
if(force || on.recordSerializedMethodArguments.equals( TrueFalseUnset.UNSET))
{
on.recordSerializedMethodArguments = from.getRecordSerializedMethodArguments();
}
if(force || on.recordSerializedReturnValue.equals( TrueFalseUnset.UNSET))
{
on.recordSerializedReturnValue = from.getRecordSerializedReturnValue();
}
}
public TrueFalseUnset getRecordFilters()
{
return recordFilters;
}
public TrueFalseUnset getRecordPath()
{
return recordPath;
}
public TrueFalseUnset getRecordSerializedExceptions()
{
return recordSerializedExceptions;
}
public TrueFalseUnset getRecordSerializedKeyPropertiesAfterEvaluation()
{
return recordSerializedKeyPropertiesAfterEvaluation;
}
public TrueFalseUnset getRecordSerializedKeyPropertiesBeforeEvaluation()
{
return recordSerializedKeyPropertiesBeforeEvaluation;
}
public TrueFalseUnset getRecordSerializedMethodArguments()
{
return recordSerializedMethodArguments;
}
public TrueFalseUnset getRecordSerializedReturnValue()
{
return recordSerializedReturnValue;
}
public void configure(Element recordOptionElement, NamespacePrefixResolver namespacePrefixResolver)
{
Element recordFiltersElement = recordOptionElement.element(AuditModel.EL_RECORD_FILTERS);
if (recordFiltersElement != null)
{
recordFilters = TrueFalseUnset.getTrueFalseUnset(recordFiltersElement.getStringValue());
}
Element recordPathElement = recordOptionElement.element(AuditModel.EL_RECORD_PATH);
if (recordPathElement != null)
{
recordPath = TrueFalseUnset.getTrueFalseUnset(recordPathElement.getStringValue());
}
Element recordSerAgrsElement = recordOptionElement.element(AuditModel.EL_RECORD_SER_ARGS);
if (recordSerAgrsElement != null)
{
recordSerializedMethodArguments = TrueFalseUnset.getTrueFalseUnset(recordSerAgrsElement.getStringValue());
}
Element recordSerExElement = recordOptionElement.element(AuditModel.EL_RECORD_SER_EX);
if (recordSerExElement != null)
{
recordSerializedExceptions = TrueFalseUnset.getTrueFalseUnset(recordSerExElement.getStringValue());
}
Element recordSerPropAfterElement = recordOptionElement.element(AuditModel.EL_RECORD_SER_PROP_AFTER);
if (recordSerPropAfterElement != null)
{
recordSerializedKeyPropertiesAfterEvaluation = TrueFalseUnset.getTrueFalseUnset(recordSerPropAfterElement
.getStringValue());
}
Element recordSerPropBeforeElement = recordOptionElement.element(AuditModel.EL_RECORD_SER_PROP_BEFORE);
if (recordSerPropBeforeElement != null)
{
recordSerializedKeyPropertiesBeforeEvaluation = TrueFalseUnset.getTrueFalseUnset(recordSerPropBeforeElement
.getStringValue());
}
Element recordSerRetElement = recordOptionElement.element(AuditModel.EL_RECORD_SER_RETURN_VAL);
if (recordSerRetElement != null)
{
recordSerializedReturnValue = TrueFalseUnset.getTrueFalseUnset(recordSerRetElement.getStringValue());
}
}
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("Record Options(");
builder.append("Filters=").append(getRecordFilters());
builder.append(",Path=").append(getRecordPath());
builder.append(",Exception=").append(getRecordSerializedExceptions());
builder.append(",PropertiesBefore=").append(getRecordSerializedKeyPropertiesAfterEvaluation());
builder.append(",PropertiesAfter=").append(getRecordSerializedKeyPropertiesBeforeEvaluation());
builder.append(",Args=").append(getRecordSerializedMethodArguments());
builder.append(",Return=").append(getRecordSerializedReturnValue());
builder.append(")");
return builder.toString();
}
}

View File

@@ -0,0 +1,100 @@
/*
* 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.audit.model;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.alfresco.repo.audit.AuditMode;
import org.alfresco.repo.audit.AuditModel;
import org.alfresco.repo.audit.MethodAuditModel;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Element;
public class ServiceAuditEntry extends AbstractNamedAuditEntry implements MethodAuditModel
{
private static Log s_logger = LogFactory.getLog(ServiceAuditEntry.class);
private Map<String, MethodAuditEntry> methods = new HashMap<String, MethodAuditEntry>();
public ServiceAuditEntry()
{
super();
}
@Override
void configure(AbstractAuditEntry parent, Element element, NamespacePrefixResolver namespacePrefixResolver)
{
super.configure(parent, element, namespacePrefixResolver);
// Add Methods
if(s_logger.isDebugEnabled())
{
s_logger.debug("Adding methods to service "+getName());
}
for (Iterator nsit = element.elementIterator(AuditModel.EL_METHOD); nsit.hasNext(); /**/)
{
Element methodElement = (Element) nsit.next();
MethodAuditEntry method = new MethodAuditEntry();
method.configure(this, methodElement, namespacePrefixResolver);
methods.put(method.getName(), method);
}
if(s_logger.isDebugEnabled())
{
s_logger.debug("...added methods for service "+getName());
}
}
public AuditMode beforeExecution(AuditMode auditMode, MethodInvocation mi)
{
String methodName = mi.getMethod().getName();
MethodAuditEntry method = methods.get(methodName);
if (method != null)
{
return method.beforeExecution(auditMode, mi);
}
else
{
if(s_logger.isDebugEnabled())
{
s_logger.debug("Evaluating if service is audited (no specific setting) for "+getName()+"."+methodName);
}
return getEffectiveAuditMode();
}
}
public AuditMode afterExecution(AuditMode auditMode, MethodInvocation mi)
{
throw new UnsupportedOperationException();
}
public AuditMode onError(AuditMode auditMode, MethodInvocation mi)
{
throw new UnsupportedOperationException();
}
public RecordOptionsImpl getAuditRecordOptions(MethodInvocation mi)
{
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,52 @@
/*
* 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.audit.model;
/**
* An enum for the values
* <ol>
* <li> TRUE
* <li> FALSE
* <li> UNSET
* </ol>
*
* @author Andy Hind
*/
public enum TrueFalseUnset
{
TRUE, FALSE, UNSET;
public static TrueFalseUnset getTrueFalseUnset(String value)
{
if(value.equalsIgnoreCase("true"))
{
return TrueFalseUnset.TRUE;
}
else if(value.equalsIgnoreCase("false"))
{
return TrueFalseUnset.FALSE;
}
else if(value.equalsIgnoreCase("unset"))
{
return TrueFalseUnset.UNSET;
}
else
{
throw new AuditModelException("Invalid value for TrueFalseUnset: "+value);
}
}
}

View File

@@ -0,0 +1,25 @@
/*
* 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.audit.model;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.dom4j.Element;
public interface XMLModelElement
{
void configure(Element element, NamespacePrefixResolver namespacePrefixResolver );
}

View File

@@ -99,14 +99,7 @@ public class EhCacheAdapter<K extends Serializable, V extends Serializable>
}
public void clear()
{
try
{
cache.removeAll();
}
catch (IOException e)
{
throw new AlfrescoRuntimeException("Failed to clear cache", e);
}
}
}

View File

@@ -0,0 +1,84 @@
/*
* 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.cache;
import java.io.IOException;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import org.alfresco.util.PropertyCheck;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
/**
* This is virtually a copy of the Springframework version, with the exception
* that it uses the newer constructors for the <code>EHCacheManager</code>
* instances.
*
* @author Derek Hulley
*/
public class EhCacheManagerFactoryBean implements FactoryBean, InitializingBean, DisposableBean
{
protected final Log logger = LogFactory.getLog(EhCacheManagerFactoryBean.class);
private Resource configLocation;
private CacheManager cacheManager;
/**
*
* @param configLocation a resource location using the <b>file:</b> or <b>classpath:</b> prefix
*/
public void setConfigLocation(Resource configLocation)
{
this.configLocation = configLocation;
}
public void afterPropertiesSet() throws IOException, CacheException
{
PropertyCheck.mandatory(this, "configLocation", configLocation);
logger.info("Initializing EHCache CacheManager");
this.cacheManager = new CacheManager(this.configLocation.getURL());
}
public Object getObject()
{
return this.cacheManager;
}
public Class getObjectType()
{
return (this.cacheManager != null ? this.cacheManager.getClass() : CacheManager.class);
}
public boolean isSingleton()
{
return true;
}
public void destroy()
{
logger.info("Shutting down EHCache CacheManager");
this.cacheManager.shutdown();
}
}

View File

@@ -16,7 +16,6 @@
*/
package org.alfresco.repo.cache;
import java.io.IOException;
import java.io.Serializable;
import java.util.List;
@@ -438,16 +437,9 @@ public class TransactionalCache<K extends Serializable, V extends Serializable>
// and also serves to ensure that the shared cache will be ignored
// for the remainder of the transaction
txnData.isClearOn = true;
try
{
txnData.updatedItemsCache.removeAll();
txnData.removedItemsCache.removeAll();
}
catch (IOException e)
{
throw new AlfrescoRuntimeException("Failed to clear caches", e);
}
}
else // no transaction
{
if (logger.isDebugEnabled())

View File

@@ -29,7 +29,6 @@ import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
@@ -130,7 +129,8 @@ public class MailMetadataExtracter extends AbstractMetadataExtracter
private static final String ENCODING_UNICODE = "001F";
private static final String SUBSTG_MESSAGEBODY = "1000";
private static final String SUBSTG_RECIPIENTEMAIL = "39FE";
private static final String SUBSTG_RECIPIENTEMAIL = "39FE"; // 7bit email address
private static final String SUBSTG_RECIPIENTSEARCH = "300B"; // address 'search' variant
private static final String SUBSTG_RECEIVEDEMAIL = "0076";
private static final String SUBSTG_SENDEREMAIL = "0C1F";
private static final String SUBSTG_DATE = "0047";
@@ -159,6 +159,27 @@ public class MailMetadataExtracter extends AbstractMetadataExtracter
{
receipientEmails.get().add(convertExchangeAddress(extractText()));
}
else if (type.equals(SUBSTG_RECIPIENTSEARCH))
{
String email = extractText(ENCODING_TEXT);
int smptIndex = email.indexOf("SMTP:");
if (smptIndex != -1)
{
/* also may be used for SUBSTG_RECIPIENTTRANSPORT = "5FF7";
with search for SMPT followed by a null char */
// this is a secondary mechanism for encoding a receipient email address
// the 7 bit email address may not have been set by Outlook - so this is needed instead
// handle null character at end of string
int endIndex = email.length();
if (email.codePointAt(email.length() - 1) == 0)
{
endIndex--;
}
email = email.substring(smptIndex + 5, endIndex);
receipientEmails.get().add(email);
}
}
else if (type.equals(SUBSTG_RECEIVEDEMAIL))
{
destination.put(ContentModel.PROP_ADDRESSEE, convertExchangeAddress(extractText()));
@@ -169,8 +190,8 @@ public class MailMetadataExtracter extends AbstractMetadataExtracter
}
else if (type.equals(SUBSTG_DATE))
{
// the date is not really plain text - but it's easier to parse as such
String date = extractText();
// the date is not "really" plain text - but it's appropriate to parse as such
String date = extractText(ENCODING_TEXT);
int valueIndex = date.indexOf("l=");
if (valueIndex != -1)
{
@@ -203,15 +224,28 @@ public class MailMetadataExtracter extends AbstractMetadataExtracter
*/
private String extractText()
throws IOException
{
return extractText(this.encoding);
}
/**
* Extract the text from the stream based on the encoding
*
* @return String
*
* @throws IOException
*/
private String extractText(String encoding)
throws IOException
{
byte[] data = new byte[stream.available()];
stream.read(data);
if (this.encoding.equals(ENCODING_TEXT) || this.encoding.equals(ENCODING_BINARY))
if (encoding.equals(ENCODING_TEXT) || encoding.equals(ENCODING_BINARY))
{
return new String(data);
}
else if (this.encoding.equals(ENCODING_UNICODE))
else if (encoding.equals(ENCODING_UNICODE))
{
// convert double-byte encoding to single byte for String conversion
byte[] b = new byte[data.length >> 1];

View File

@@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.policy.ClassPolicyDelegate;
import org.alfresco.repo.policy.JavaBehaviour;
@@ -31,6 +32,7 @@ import org.alfresco.repo.policy.PolicyComponent;
import org.alfresco.repo.policy.PolicyScope;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
@@ -401,6 +403,23 @@ public class CopyServiceImpl implements CopyService
}
}
// if the parent node is the same, then remove the name property - it will have to
// be changed by the client code
AssociationDefinition assocDef = dictionaryService.getAssociation(destinationAssocTypeQName);
if (!assocDef.isChild())
{
throw new AlfrescoRuntimeException("Association is not a child association: " + destinationAssocTypeQName);
}
else
{
ChildAssociationDefinition childAssocDef = (ChildAssociationDefinition) assocDef;
if (!childAssocDef.getDuplicateChildNamesAllowed())
{
// duplicate children are not allowed.
properties.remove(ContentModel.PROP_NAME);
}
}
// Create the new node
ChildAssociationRef destinationChildAssocRef = this.nodeService.createNode(
destinationParent,

View File

@@ -41,9 +41,9 @@ public interface NodeStatus
public void setNode(Node node);
public String getChangeTxnId();
public Transaction getTransaction();
public void setChangeTxnId(String txnId);
public void setTransaction(Transaction transaction);
public boolean isDeleted();
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) 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.repo.domain;
/**
* Interface for persistent <b>server</b> objects. These persist
* details of the servers that have committed transactions to the
* database, for instance.
*
* @author Derek Hulley
*/
public interface Server
{
public Long getId();
public String getIpAddress();
public void setIpAddress(String ipAddress);
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 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.repo.domain;
/**
* Interface for persistent <b>transaction</b> objects.
*
* @author Derek Hulley
*/
public interface Transaction
{
public Long getId();
public String getChangeTxnId();
public void setChangeTxnId(String changeTxnId);
public Server getServer();
public void setServer(Server server);
}

View File

@@ -31,8 +31,10 @@ import org.alfresco.repo.domain.Node;
import org.alfresco.repo.domain.NodeKey;
import org.alfresco.repo.domain.NodeStatus;
import org.alfresco.repo.domain.PropertyValue;
import org.alfresco.repo.domain.Server;
import org.alfresco.repo.domain.Store;
import org.alfresco.repo.domain.StoreKey;
import org.alfresco.repo.domain.Transaction;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.repository.StoreRef;
@@ -53,8 +55,11 @@ import org.hibernate.exception.ConstraintViolationException;
public class HibernateNodeTest extends BaseSpringTest
{
private static final String TEST_NAMESPACE = "http://www.alfresco.org/test/HibernateNodeTest";
private static int i = 0;
private Store store;
private Server server;
private Transaction transaction;
public HibernateNodeTest()
{
@@ -68,6 +73,18 @@ public class HibernateNodeTest extends BaseSpringTest
store.setKey(storeKey);
// persist so that it is present in the hibernate cache
getSession().save(store);
server = (Server) getSession().get(ServerImpl.class, new Long(1));
if (server == null)
{
server = new ServerImpl();
server.setIpAddress("" + "i_" + System.currentTimeMillis());
getSession().save(server);
}
transaction = new TransactionImpl();
transaction.setServer(server);
transaction.setChangeTxnId(AlfrescoTransactionSupport.getTransactionId());
getSession().save(transaction);
}
protected void onTearDownInTransaction()
@@ -108,7 +125,7 @@ public class HibernateNodeTest extends BaseSpringTest
// create the node status
NodeStatus nodeStatus = new NodeStatusImpl();
nodeStatus.setKey(key);
nodeStatus.setChangeTxnId("txn:123");
nodeStatus.setTransaction(transaction);
getSession().save(nodeStatus);
// create a new Node
@@ -131,7 +148,7 @@ public class HibernateNodeTest extends BaseSpringTest
node = nodeStatus.getNode();
assertNotNull("Node was not attached to status", node);
// change the values
nodeStatus.setChangeTxnId("txn:456");
transaction.setChangeTxnId("txn:456");
// delete the node
getSession().delete(node);
@@ -351,7 +368,7 @@ public class HibernateNodeTest extends BaseSpringTest
NodeStatus containerNodeStatus = new NodeStatusImpl();
containerNodeStatus.setKey(containerNodeKey);
containerNodeStatus.setNode(containerNode);
containerNodeStatus.setChangeTxnId(AlfrescoTransactionSupport.getTransactionId());
containerNodeStatus.setTransaction(transaction);
getSession().save(containerNodeStatus);
// make content node 1
Node contentNode1 = new NodeImpl();
@@ -366,7 +383,7 @@ public class HibernateNodeTest extends BaseSpringTest
NodeStatus contentNodeStatus1 = new NodeStatusImpl();
contentNodeStatus1.setKey(contentNodeKey1);
contentNodeStatus1.setNode(contentNode1);
contentNodeStatus1.setChangeTxnId(AlfrescoTransactionSupport.getTransactionId());
contentNodeStatus1.setTransaction(transaction);
getSession().save(contentNodeStatus1);
// make content node 2
Node contentNode2 = new NodeImpl();
@@ -381,7 +398,7 @@ public class HibernateNodeTest extends BaseSpringTest
NodeStatus contentNodeStatus2 = new NodeStatusImpl();
contentNodeStatus2.setKey(contentNodeKey2);
contentNodeStatus2.setNode(contentNode2);
contentNodeStatus2.setChangeTxnId(AlfrescoTransactionSupport.getTransactionId());
contentNodeStatus2.setTransaction(transaction);
getSession().save(contentNodeStatus2);
// create an association to content 1
ChildAssoc assoc1 = new ChildAssocImpl();

View File

@@ -113,6 +113,16 @@
<key-property name="identifier" length="100" />
<key-property name="guid" length="36" />
</composite-id>
<!-- forward assoc to transaction -->
<many-to-one
name="transaction"
class="org.alfresco.repo.domain.hibernate.TransactionImpl"
column="transaction_id"
lazy="proxy"
fetch="select"
unique="false"
not-null="true"
cascade="none" />
<!-- forward assoc to node (optional) -->
<many-to-one
name="node"
@@ -122,7 +132,6 @@
fetch="join"
unique="false"
not-null="false" />
<property name="changeTxnId" column="change_txn_id" type="string" length="56" not-null="true" index="CHANGE_TXN_ID"/>
</class>
<class
@@ -137,7 +146,6 @@
<id name="id" column="id" type="long" >
<generator class="native" />
</id>
<natural-id mutable="true">
<!-- forward assoc to parent node -->
<many-to-one
name="parent"
@@ -160,10 +168,9 @@
<column name="child_node_id" />
</many-to-one>
<property name="typeQName" column="type_qname" type="QName" length="255" not-null="true" unique-key="UIDX_CHILD_NAME" />
</natural-id>
<property name="qname" column="qname" type="QName" length="255" not-null="true" />
<property name="childNodeName" column="child_node_name" type="string" length="50" not-null="true" unique-key="UIDX_CHILD_NAME" />
<property name="childNodeNameCrc" column="child_node_name_crc" type="long" not-null="true" unique-key="UIDX_CHILD_NAME" />
<property name="qname" column="qname" type="QName" length="255" not-null="true" />
<property name="isPrimary" column="is_primary" />
<property name="index" column="assoc_index" />
</class>
@@ -309,25 +316,26 @@
<query name="node.GetNextChangeTxnIds">
select distinct
status.changeTxnId
transaction.changeTxnId
from
org.alfresco.repo.domain.hibernate.NodeStatusImpl as status
org.alfresco.repo.domain.hibernate.TransactionImpl as transaction
where
status.changeTxnId > :currentTxnId
transaction.changeTxnId > :currentTxnId
order by
status.changeTxnId
transaction.changeTxnId
</query>
<query name="node.GetChangedNodeStatusesCount">
select
count(status.changeTxnId)
count(transaction.changeTxnId)
from
org.alfresco.repo.domain.hibernate.NodeStatusImpl as status
join status.transaction as transaction
where
status.key.protocol = :storeProtocol and
status.key.identifier = :storeIdentifier and
status.node.id is not null and
status.changeTxnId = :changeTxnId
transaction.changeTxnId = :changeTxnId
</query>
<query name="node.GetChangedNodeStatuses">
@@ -335,11 +343,12 @@
status
from
org.alfresco.repo.domain.hibernate.NodeStatusImpl as status
join status.transaction as transaction
where
status.key.protocol = :storeProtocol and
status.key.identifier = :storeIdentifier and
status.node.id is not null and
status.changeTxnId = :changeTxnId
transaction.changeTxnId = :changeTxnId
</query>
<query name="node.GetDeletedNodeStatuses">
@@ -347,11 +356,12 @@
status
from
org.alfresco.repo.domain.hibernate.NodeStatusImpl as status
join status.transaction as transaction
where
status.key.protocol = :storeProtocol and
status.key.identifier = :storeIdentifier and
status.node.id is null and
status.changeTxnId = :changeTxnId
transaction.changeTxnId = :changeTxnId
</query>
<query name="node.GetContentDataStrings">

View File

@@ -21,6 +21,7 @@ import java.io.Serializable;
import org.alfresco.repo.domain.Node;
import org.alfresco.repo.domain.NodeKey;
import org.alfresco.repo.domain.NodeStatus;
import org.alfresco.repo.domain.Transaction;
import org.alfresco.util.EqualsHelper;
/**
@@ -34,15 +35,16 @@ public class NodeStatusImpl implements NodeStatus, Serializable
private NodeKey key;
private Node node;
private String changeTxnId;
private Transaction transaction;
@Override
public String toString()
{
StringBuilder sb = new StringBuilder(50);
sb.append("NodeStatus")
.append("[key=").append(key)
.append(", node=").append(node == null ? null : node.getNodeRef())
.append(", txn=").append(changeTxnId)
.append(", txn=").append(transaction)
.append("]");
return sb.toString();
}
@@ -85,14 +87,14 @@ public class NodeStatusImpl implements NodeStatus, Serializable
this.node = node;
}
public String getChangeTxnId()
public Transaction getTransaction()
{
return changeTxnId;
return transaction;
}
public void setChangeTxnId(String txnId)
public void setTransaction(Transaction transaction)
{
this.changeTxnId = txnId;
this.transaction = transaction;
}
public boolean isDeleted()

View File

@@ -0,0 +1,76 @@
/*
* 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.domain.hibernate;
import java.io.Serializable;
import org.alfresco.repo.domain.Server;
/**
* Bean containing all the persistence data representing a <b>Server</b>.
* <p>
* This implementation of the {@link org.alfresco.repo.domain.Service Service} interface is
* Hibernate specific.
*
* @author Derek Hulley
*/
public class ServerImpl extends LifecycleAdapter implements Server, Serializable
{
private static final long serialVersionUID = 8063452519040344479L;
private Long id;
private String ipAddress;
public ServerImpl()
{
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder(50);
sb.append("Server")
.append("[id=").append(id)
.append(", ipAddress=").append(ipAddress)
.append("]");
return sb.toString();
}
public Long getId()
{
return id;
}
/**
* For Hibernate use
*/
@SuppressWarnings("unused")
private void setId(Long id)
{
this.id = id;
}
public String getIpAddress()
{
return ipAddress;
}
public void setIpAddress(String ipAddress)
{
this.ipAddress = ipAddress;
}
}

View File

@@ -0,0 +1,62 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
'-//Hibernate/Hibernate Mapping DTD 3.0//EN'
'http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd'>
<hibernate-mapping>
<class
name="org.alfresco.repo.domain.hibernate.TransactionImpl"
proxy="org.alfresco.repo.domain.Transaction"
table="alf_transaction"
dynamic-update="false"
dynamic-insert="false"
select-before-update="false"
lazy="true"
optimistic-lock="version" >
<!-- auto-generated ID -->
<id name="id" column="id" type="long" >
<generator class="native" />
</id>
<!-- forward assoc to server IP -->
<many-to-one
name="server"
class="org.alfresco.repo.domain.hibernate.ServerImpl"
column="server_id"
lazy="proxy"
fetch="select"
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"/>
</class>
<class
name="org.alfresco.repo.domain.hibernate.ServerImpl"
proxy="org.alfresco.repo.domain.Server"
table="alf_server"
dynamic-update="false"
dynamic-insert="false"
select-before-update="false"
lazy="true"
optimistic-lock="version" >
<!-- auto-generated ID -->
<id name="id" column="id" type="long" >
<generator class="native" />
</id>
<natural-id>
<property name="ipAddress" column="ip_address" type="string" length="15" not-null="true" />
</natural-id>
</class>
<query name="server.getServerByIpAddress">
select
server
from
org.alfresco.repo.domain.hibernate.ServerImpl as server
where
server.ipAddress = :ipAddress
</query>
</hibernate-mapping>

View File

@@ -0,0 +1,88 @@
/*
* 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.domain.hibernate;
import java.io.Serializable;
import org.alfresco.repo.domain.Server;
import org.alfresco.repo.domain.Transaction;
/**
* Bean containing all the persistence data representing a <b>Transaction</b>.
* <p>
* This implementation of the {@link org.alfresco.repo.domain.Transaction Transaction} interface is
* Hibernate specific.
*
* @author Derek Hulley
*/
public class TransactionImpl extends LifecycleAdapter implements Transaction, Serializable
{
private static final long serialVersionUID = -8264339795578077552L;
private Long id;
private String changeTxnId;
private Server server;
public TransactionImpl()
{
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder(50);
sb.append("Transaction")
.append("[id=").append(id)
.append(", changeTxnId=").append(changeTxnId)
.append("]");
return sb.toString();
}
public Long getId()
{
return id;
}
/**
* For Hibernate use
*/
@SuppressWarnings("unused")
private void setId(Long id)
{
this.id = id;
}
public String getChangeTxnId()
{
return changeTxnId;
}
public void setChangeTxnId(String changeTransactionId)
{
this.changeTxnId = changeTransactionId;
}
public Server getServer()
{
return server;
}
public void setServer(Server server)
{
this.server = server;
}
}

View File

@@ -0,0 +1,529 @@
/*
* Copyright (C) 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.repo.domain.schema;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.Writer;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
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.util.TempFileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.Dialect;
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.orm.hibernate3.LocalSessionFactoryBean;
import org.springframework.util.ResourceUtils;
/**
* Bootstraps the schema and schema update. The schema is considered missing if the applied patch table
* is not present, and the schema is considered empty if the applied patch table is empty.
*
* @author Derek Hulley
*/
public class SchemaBootstrap implements ApplicationListener
{
/** 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 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";
private static final String ERR_SCRIPT_NOT_FOUND = "schema.update.err.script_not_found";
private static final String ERR_STATEMENT_TERMINATOR = "schema.update.err.statement_terminator";
private static Log logger = LogFactory.getLog(SchemaBootstrap.class);
private LocalSessionFactoryBean localSessionFactory;
private String schemaOuputFilename;
private boolean updateSchema;
private List<String> postCreateScriptUrls;
private List<SchemaUpgradeScriptPatch> validateUpdateScriptPatches;
private List<SchemaUpgradeScriptPatch> applyUpdateScriptPatches;
public SchemaBootstrap()
{
postCreateScriptUrls = new ArrayList<String>(1);
validateUpdateScriptPatches = new ArrayList<SchemaUpgradeScriptPatch>(4);
applyUpdateScriptPatches = new ArrayList<SchemaUpgradeScriptPatch>(4);
}
public void setLocalSessionFactory(LocalSessionFactoryBean localSessionFactory) throws BeansException
{
this.localSessionFactory = localSessionFactory;
}
/**
* Set this to output the full database creation script
*
* @param schemaOuputFilename the name of a file to dump the schema to, or null to ignore
*/
public void setSchemaOuputFilename(String schemaOuputFilename)
{
this.schemaOuputFilename = schemaOuputFilename;
}
/**
* Set whether to modify the schema or not. Either way, the schema will be validated.
*
* @param updateSchema true to update and validate the schema, otherwise false to just
* validate the schema. Default is <b>true</b>.
*/
public void setUpdateSchema(boolean updateSchema)
{
this.updateSchema = updateSchema;
}
/**
* Set the scripts that must be executed after the schema has been created.
*
* @param postCreateScriptUrls file URLs
*
* @see #PLACEHOLDER_SCRIPT_DIALECT
*/
public void setPostCreateScriptUrls(List<String> postUpdateScriptUrls)
{
this.postCreateScriptUrls = postUpdateScriptUrls;
}
/**
* Set the schema script patches that must have been applied. These will not be
* applied to the database. These can be used where the script <u>cannot</u> be
* applied automatically or where a particular upgrade path is no longer supported.
* For example, at version 3.0, the upgrade scripts for version 1.4 may be considered
* unsupported - this doesn't prevent the manual application of the scripts, though.
*
* @param applyUpdateScriptPatches a list of schema patches to check
*/
public void setValidateUpdateScriptPatches(List<SchemaUpgradeScriptPatch> scriptPatches)
{
this.validateUpdateScriptPatches = scriptPatches;
}
/**
* Set the schema script patches that may be executed during an update.
*
* @param applyUpdateScriptPatches a list of schema patches to check
*/
public void setApplyUpdateScriptPatches(List<SchemaUpgradeScriptPatch> scriptPatches)
{
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
if (schemaOutputFile.exists())
{
schemaOutputFile.delete();
}
SchemaExport schemaExport = new SchemaExport(cfg)
.setFormat(true)
.setHaltOnError(true)
.setOutputFile(schemaOutputFile.getAbsolutePath())
.setDelimiter(";");
schemaExport.execute(false, false, false, true);
}
private SessionFactory getLocalSessionFactory()
{
return (SessionFactory) localSessionFactory.getObject();
}
/**
* @return Returns the number of applied patches
*/
private int countAppliedPatches(Connection connection) throws Exception
{
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;
}
catch (Throwable e)
{
// we'll try another table name
}
finally
{
try { stmt.close(); } catch (Throwable e) {}
}
// for pre-1.4 databases, the table was named differently
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) {}
}
}
/**
* @return Returns the number of applied patches
*/
private boolean didPatchSucceed(Connection connection, String patchId) throws Exception
{
Statement stmt = connection.createStatement();
try
{
ResultSet rs = stmt.executeQuery("select succeeded from alf_applied_patch where id = '" + patchId + "'");
if (!rs.next())
{
return false;
}
boolean succeeded = rs.getBoolean(1);
return succeeded;
}
catch (Throwable e)
{
// we'll try another table name
}
finally
{
try { stmt.close(); } catch (Throwable e) {}
}
// for pre-1.4 databases, the table was named differently
stmt = connection.createStatement();
try
{
ResultSet rs = stmt.executeQuery("select succeeded from applied_patch where id = '" + patchId + "'");
if (!rs.next())
{
return false;
}
boolean succeeded = rs.getBoolean(1);
return succeeded;
}
finally
{
try { stmt.close(); } catch (Throwable e) {}
}
}
/**
* Builds the schema from scratch or applies the necessary patches to the schema.
*/
private void updateSchema(Configuration cfg, Session session, Connection connection) throws Exception
{
boolean create = false;
try
{
countAppliedPatches(connection);
}
catch (Throwable e)
{
create = true;
}
if (create)
{
// 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", ".sql");
dumpSchemaCreate(cfg, tempFile);
executeScriptFile(cfg, connection, tempFile);
// execute post-create scripts (not patches)
for (String scriptUrl : this.postCreateScriptUrls)
{
executeScriptUrl(cfg, connection, scriptUrl);
}
}
else
{
// we have a database, so just run the update scripts
checkSchemaPatchScripts(cfg, session, connection, validateUpdateScriptPatches, false); // check for scripts that must have been run
checkSchemaPatchScripts(cfg, session, connection, applyUpdateScriptPatches, true); // execute scripts as required
// let Hibernate do any required updates
File tempFile = null;
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");
writer = new BufferedWriter(new FileWriter(tempFile));
for (String sql : sqls)
{
writer.append(sql);
writer.append(";\n");
}
}
}
finally
{
if (writer != null)
{
try {writer.close();} catch (Throwable e) {}
}
}
// execute if there were changes raised by Hibernate
if (tempFile != null)
{
executeScriptFile(cfg, connection, tempFile);
}
}
}
/**
* Check that the necessary scripts have been executed against the database
*/
private void checkSchemaPatchScripts(
Configuration cfg,
Session session,
Connection connection,
List<SchemaUpgradeScriptPatch> scriptPatches,
boolean apply) throws Exception
{
// first check if there have been any applied patches
int appliedPatchCount = countAppliedPatches(connection);
if (appliedPatchCount == 0)
{
// This is a new schema, so upgrade scripts are irrelevant
// and patches will not have been applied yet
return;
}
for (SchemaUpgradeScriptPatch patch : scriptPatches)
{
final String patchId = patch.getId();
final String scriptUrl = patch.getScriptUrl();
// check if the script was successfully executed
boolean wasSuccessfullyApplied = didPatchSucceed(connection, patchId);
if (wasSuccessfullyApplied)
{
// nothing to do - it has been done before
continue;
}
else if (!apply)
{
// the script was not run and may not be run automatically
throw AlfrescoRuntimeException.create(ERR_SCRIPT_NOT_RUN, scriptUrl);
}
// it wasn't run and it can be run now
executeScriptUrl(cfg, connection, scriptUrl);
}
}
private void executeScriptUrl(Configuration cfg, Connection connection, String scriptUrl) throws Exception
{
Dialect dialect = Dialect.getDialect(cfg.getProperties());
File scriptFile = getScriptFile(dialect.getClass(), scriptUrl);
// check that it exists
if (scriptFile == null)
{
throw AlfrescoRuntimeException.create(ERR_SCRIPT_NOT_FOUND, scriptUrl);
}
// now execute it
executeScriptFile(cfg, connection, scriptFile);
}
/**
* Replaces the dialect placeholder in the script URL and attempts to find a file for
* it. If not found, the dialect hierarchy will be walked until a compatible script is
* found. This makes it possible to have scripts that are generic to all dialects.
*
* @return Returns the file if found, otherwise null
*/
private File getScriptFile(Class dialectClazz, String scriptUrl) throws Exception
{
// replace the dialect placeholder
String dialectScriptUrl = scriptUrl.replaceAll(PLACEHOLDER_SCRIPT_DIALECT, dialectClazz.getName());
// get a handle on the resource
try
{
File scriptFile = ResourceUtils.getFile(dialectScriptUrl);
if (scriptFile.exists())
{
// found a compatible dialect version
return scriptFile;
}
}
catch (FileNotFoundException e)
{
// doesn't exist
}
// it wasn't found. Get the superclass of the dialect and try again
Class superClazz = dialectClazz.getSuperclass();
if (Dialect.class.isAssignableFrom(superClazz))
{
// we still have a Dialect - try again
return getScriptFile(superClazz, scriptUrl);
}
else
{
// we have exhausted all options
return null;
}
}
private void executeScriptFile(Configuration cfg, Connection connection, File scriptFile) throws Exception
{
logger.info(I18NUtil.getMessage(MSG_EXECUTING_SCRIPT, scriptFile));
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(scriptFile), "UTF8"));
try
{
int line = 0;
// loop through all statements
StringBuilder sb = new StringBuilder(1024);
while(true)
{
String sql = reader.readLine();
line++;
if (sql == null)
{
// nothing left in the file
break;
}
// trim it
sql = sql.trim();
if (sql.length() == 0 ||
sql.startsWith( "--" ) ||
sql.startsWith( "//" ) ||
sql.startsWith( "/*" ) )
{
if (sb.length() > 0)
{
// we have an unterminated statement
throw AlfrescoRuntimeException.create(ERR_STATEMENT_TERMINATOR, (line - 1), scriptFile);
}
// there has not been anything to execute - it's just a comment line
continue;
}
// have we reached the end of a statement?
boolean execute = false;
if (sql.endsWith(";"))
{
sql = sql.substring(0, sql.length() - 1);
execute = 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) {}
}
}
}
}
finally
{
try { reader.close(); } catch (Throwable e) {}
}
}
}

Some files were not shown because too many files have changed in this diff Show More