diff --git a/migration/i1.0a-release/oracle/201212051000_IDEMPIERE_390.sql b/migration/i1.0a-release/oracle/201212051000_IDEMPIERE_390.sql
new file mode 100644
index 0000000000..71fe6e45ee
--- /dev/null
+++ b/migration/i1.0a-release/oracle/201212051000_IDEMPIERE_390.sql
@@ -0,0 +1,277 @@
+-- Nov 30, 2012 5:06:08 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+INSERT INTO AD_Element (ColumnName,AD_Element_ID,EntityType,Name,PrintName,AD_Element_UU,AD_Client_ID,Created,Updated,AD_Org_ID,CreatedBy,UpdatedBy,IsActive) VALUES ('StorageArchive',200257,'D','StorageArchive','Storage Archive','766f13f0-dd9f-4a36-8540-f9f990a81f25',0,TO_DATE('2012-11-30 17:06:06','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2012-11-30 17:06:06','YYYY-MM-DD HH24:MI:SS'),0,100,100,'Y')
+;
+
+-- Nov 30, 2012 5:06:08 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+INSERT INTO AD_Element_Trl (AD_Language,AD_Element_ID, Help,PO_Description,PO_Help,Name,Description,PrintName,PO_Name,PO_PrintName, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy,AD_Element_Trl_UU ) SELECT l.AD_Language,t.AD_Element_ID, t.Help,t.PO_Description,t.PO_Help,t.Name,t.Description,t.PrintName,t.PO_Name,t.PO_PrintName, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy,Generate_UUID() FROM AD_Language l, AD_Element t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Element_ID=200257 AND NOT EXISTS (SELECT * FROM AD_Element_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.AD_Element_ID=t.AD_Element_ID)
+;
+
+-- Nov 30, 2012 5:11:05 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Element SET ColumnName='StorageArchive_ID', Name='StorageArchive_ID', PrintName='Storage Archive_ID',Updated=TO_DATE('2012-11-30 17:11:05','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Element_ID=200257
+;
+
+-- Nov 30, 2012 5:11:05 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Element_Trl SET IsTranslated='N' WHERE AD_Element_ID=200257
+;
+
+-- Nov 30, 2012 5:11:05 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Column SET ColumnName='StorageArchive_ID', Name='StorageArchive_ID', Description=NULL, Help=NULL WHERE AD_Element_ID=200257
+;
+
+-- Nov 30, 2012 5:11:05 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Process_Para SET ColumnName='StorageArchive_ID', Name='StorageArchive_ID', Description=NULL, Help=NULL, AD_Element_ID=200257 WHERE UPPER(ColumnName)='STORAGEARCHIVE_ID' AND IsCentrallyMaintained='Y' AND AD_Element_ID IS NULL
+;
+
+-- Nov 30, 2012 5:11:05 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Process_Para SET ColumnName='StorageArchive_ID', Name='StorageArchive_ID', Description=NULL, Help=NULL WHERE AD_Element_ID=200257 AND IsCentrallyMaintained='Y'
+;
+
+-- Nov 30, 2012 5:11:05 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET Name='StorageArchive_ID', Description=NULL, Help=NULL WHERE AD_Column_ID IN (SELECT AD_Column_ID FROM AD_Column WHERE AD_Element_ID=200257) AND IsCentrallyMaintained='Y'
+;
+
+-- Nov 30, 2012 5:11:05 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_PrintFormatItem pi SET PrintName='Storage Archive_ID', Name='StorageArchive_ID' WHERE IsCentrallyMaintained='Y' AND EXISTS (SELECT * FROM AD_Column c WHERE c.AD_Column_ID=pi.AD_Column_ID AND c.AD_Element_ID=200257)
+;
+
+-- Nov 30, 2012 5:11:22 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+INSERT INTO AD_Column (SeqNoSelection,IsSyncDatabase,IsEncrypted,Version,AD_Table_ID,AD_Column_ID,EntityType,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsParent,FieldLength,IsSelectionColumn,AD_Reference_ID,IsKey,AD_Element_ID,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsUpdateable,IsAlwaysUpdateable,ColumnName,Name,IsAllowCopy,Updated,CreatedBy,AD_Org_ID,IsActive,Created,UpdatedBy,AD_Client_ID,IsToolbarButton) VALUES (0,'N','N',0,227,201007,'U','N','N','N',0,'N',22,'N',18,'N',200257,'N','Y','764723f1-4251-4153-8198-0615453fa358','Y','N','StorageArchive_ID','StorageArchive_ID','Y',TO_DATE('2012-11-30 17:11:21','YYYY-MM-DD HH24:MI:SS'),100,0,'Y',TO_DATE('2012-11-30 17:11:21','YYYY-MM-DD HH24:MI:SS'),100,0,'N')
+;
+
+-- Nov 30, 2012 5:11:22 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+INSERT INTO AD_Column_Trl (AD_Language,AD_Column_ID, Name, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy,AD_Column_Trl_UU ) SELECT l.AD_Language,t.AD_Column_ID, t.Name, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy,Generate_UUID() FROM AD_Language l, AD_Column t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Column_ID=201007 AND NOT EXISTS (SELECT * FROM AD_Column_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.AD_Column_ID=t.AD_Column_ID)
+;
+
+-- Nov 30, 2012 5:14:08 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE C_AcctProcessor SET DateNextRun=TO_DATE('2012-11-30 17:24:08','YYYY-MM-DD HH24:MI:SS'), DateLastRun=TO_DATE('2012-11-30 17:14:08','YYYY-MM-DD HH24:MI:SS'),Updated=TO_DATE('2012-11-30 17:14:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE C_AcctProcessor_ID=100
+;
+
+-- Nov 30, 2012 5:16:08 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+INSERT INTO AD_Reference (AD_Reference_ID,Name,EntityType,AD_Reference_UU,IsOrderByValue,Description,ValidationType,AD_Client_ID,AD_Org_ID,CreatedBy,Updated,IsActive,Created,UpdatedBy) VALUES (200023,'AD_StorageProvider_ID','D','2dc5386f-d9db-4758-a03e-e8695a286ff2','N','AD_StorageProvider_ID','T',0,0,100,TO_DATE('2012-11-30 17:16:07','YYYY-MM-DD HH24:MI:SS'),'Y',TO_DATE('2012-11-30 17:16:07','YYYY-MM-DD HH24:MI:SS'),100)
+;
+
+-- Nov 30, 2012 5:16:08 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+INSERT INTO AD_Reference_Trl (AD_Language,AD_Reference_ID, Help,Name,Description, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy,AD_Reference_Trl_UU ) SELECT l.AD_Language,t.AD_Reference_ID, t.Help,t.Name,t.Description, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy,Generate_UUID() FROM AD_Language l, AD_Reference t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Reference_ID=200023 AND NOT EXISTS (SELECT * FROM AD_Reference_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.AD_Reference_ID=t.AD_Reference_ID)
+;
+
+-- Nov 30, 2012 5:17:00 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+INSERT INTO AD_Ref_Table (IsValueDisplayed,AD_Reference_ID,AD_Key,AD_Display,EntityType,AD_Table_ID,AD_Ref_Table_UU,CreatedBy,Updated,Created,AD_Client_ID,UpdatedBy,AD_Org_ID,IsActive) VALUES ('N',200023,200961,200969,'D',200037,'2d31b980-72b5-4c2e-964b-91fa288f0a12',100,TO_DATE('2012-11-30 17:17:00','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2012-11-30 17:17:00','YYYY-MM-DD HH24:MI:SS'),0,100,0,'Y')
+;
+
+-- Nov 30, 2012 5:17:57 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Column SET AD_Reference_Value_ID=200023,Updated=TO_DATE('2012-11-30 17:17:57','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=201007
+;
+
+-- Nov 30, 2012 5:18:10 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+ALTER TABLE AD_ClientInfo ADD StorageArchive_ID NUMBER(10) DEFAULT NULL
+;
+
+-- Nov 30, 2012 5:20:25 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+INSERT INTO AD_Field (ColumnSpan,NumLines,SortNo,IsEncrypted,AD_Tab_ID,DisplayLength,IsSameLine,IsHeading,AD_Column_ID,SeqNo,IsCentrallyMaintained,AD_Field_ID,IsReadOnly,EntityType,Name,AD_Field_UU,IsDisplayed,IsFieldOnly,UpdatedBy,AD_Org_ID,Created,AD_Client_ID,CreatedBy,Updated,IsActive,IsDisplayedGrid,SeqNoGrid,XPosition,IsQuickEntry) VALUES (1,1,0,'N',169,0,'N','N',201007,240,'Y',200949,'N','D','StorageArchive_ID','40744096-6d57-48e7-8931-6c237ee9ac3c','Y','N',100,0,TO_DATE('2012-11-30 17:20:24','YYYY-MM-DD HH24:MI:SS'),0,100,TO_DATE('2012-11-30 17:20:24','YYYY-MM-DD HH24:MI:SS'),'Y','Y',320,1,'N')
+;
+
+-- Nov 30, 2012 5:20:25 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+INSERT INTO AD_Field_Trl (AD_Language,AD_Field_ID, Help,Description,Name, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy,AD_Field_Trl_UU ) SELECT l.AD_Language,t.AD_Field_ID, t.Help,t.Description,t.Name, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy,Generate_UUID() FROM AD_Language l, AD_Field t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Field_ID=200949 AND NOT EXISTS (SELECT * FROM AD_Field_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.AD_Field_ID=t.AD_Field_ID)
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET ColumnSpan=2, SeqNo=120, IsDisplayed='Y', XPosition=4,Updated=TO_DATE('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=200949
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=130,Updated=TO_DATE('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=9201
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=140,Updated=TO_DATE('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=1564
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=150,Updated=TO_DATE('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=1563
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=160,Updated=TO_DATE('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=1562
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=170,Updated=TO_DATE('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=1565
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=180,Updated=TO_DATE('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=1566
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=190,Updated=TO_DATE('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=1567
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=200,Updated=TO_DATE('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=10319
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=210,Updated=TO_DATE('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=10320
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=220,Updated=TO_DATE('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=57531
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=230,Updated=TO_DATE('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=57534
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=240,Updated=TO_DATE('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=57535
+;
+
+-- Nov 30, 2012 5:30:06 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Ref_Table SET IsValueDisplayed='Y', AD_Display=200961,Updated=TO_DATE('2012-11-30 17:30:06','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Reference_ID=200023
+;
+
+-- Nov 30, 2012 5:34:49 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Ref_Table SET IsValueDisplayed='N',Updated=TO_DATE('2012-11-30 17:34:49','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Reference_ID=200023
+;
+
+INSERT INTO ad_storageprovider
+ (ad_client_id,
+ ad_org_id,
+ ad_storageprovider_id,
+ ad_storageprovider_uu,
+ created,
+ createdby,
+ folder,
+ isactive,
+ method,
+ name,
+ password,
+ updated,
+ updatedby,
+ url,
+ username)
+SELECT
+ ad_client_id,
+ 0,
+ nextidfunc(200033,'N'),
+ generate_uuid(),
+ sysdate,
+ 100,
+ coalesce(windowsarchivepath, unixarchivepath),
+ 'Y',
+ 'FileSystem',
+ 'Folder',
+ null,
+ sysdate,
+ 100,
+ null,
+ null
+FROM ad_client
+WHERE storearchiveonfilesystem='Y' AND (windowsarchivepath is not null or unixarchivepath is not null)
+;
+
+UPDATE ad_clientinfo
+ SET storagearchive_id = (SELECT ad_storageprovider_id FROM ad_storageprovider JOIN ad_client ON ad_client.ad_client_id=ad_storageprovider.ad_client_id
+ WHERE ad_storageprovider.ad_client_id=ad_clientinfo.ad_client_id
+ AND coalesce(ad_client.windowsarchivepath, ad_client.unixarchivepath)=ad_storageprovider.folder)
+WHERE ad_clientinfo.ad_client_id IN
+ (SELECT ad_client_id FROM ad_client WHERE storearchiveonfilesystem='Y' AND (windowsarchivepath is not null or unixarchivepath is not null))
+;
+
+-- Dec 5, 2012 6:49:08 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Column SET IsActive='N',Updated=TO_DATE('2012-12-05 18:49:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=50215
+;
+
+-- Dec 5, 2012 6:49:14 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Column SET IsActive='N',Updated=TO_DATE('2012-12-05 18:49:14','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=50216
+;
+
+-- Dec 5, 2012 6:49:18 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Column SET IsActive='N',Updated=TO_DATE('2012-12-05 18:49:18','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=50214
+;
+
+-- Dec 5, 2012 6:55:57 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Field SET IsCentrallyMaintained='N', Name='Attachment Store',Updated=TO_DATE('2012-12-05 18:55:57','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=200948
+;
+
+-- Dec 5, 2012 6:55:57 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Field_Trl SET IsTranslated='N' WHERE AD_Field_ID=200948
+;
+
+-- Dec 5, 2012 6:56:36 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Element SET Name='Archive Store', PrintName='Archive Store',Updated=TO_DATE('2012-12-05 18:56:36','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Element_ID=200257
+;
+
+-- Dec 5, 2012 6:56:36 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Element_Trl SET IsTranslated='N' WHERE AD_Element_ID=200257
+;
+
+-- Dec 5, 2012 6:56:36 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Column SET ColumnName='StorageArchive_ID', Name='Archive Store', Description=NULL, Help=NULL WHERE AD_Element_ID=200257
+;
+
+-- Dec 5, 2012 6:56:36 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Process_Para SET ColumnName='StorageArchive_ID', Name='Archive Store', Description=NULL, Help=NULL, AD_Element_ID=200257 WHERE UPPER(ColumnName)='STORAGEARCHIVE_ID' AND IsCentrallyMaintained='Y' AND AD_Element_ID IS NULL
+;
+
+-- Dec 5, 2012 6:56:36 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Process_Para SET ColumnName='StorageArchive_ID', Name='Archive Store', Description=NULL, Help=NULL WHERE AD_Element_ID=200257 AND IsCentrallyMaintained='Y'
+;
+
+-- Dec 5, 2012 6:56:36 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Field SET Name='Archive Store', Description=NULL, Help=NULL WHERE AD_Column_ID IN (SELECT AD_Column_ID FROM AD_Column WHERE AD_Element_ID=200257) AND IsCentrallyMaintained='Y'
+;
+
+-- Dec 5, 2012 6:56:36 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_PrintFormatItem pi SET PrintName='Archive Store', Name='Archive Store' WHERE IsCentrallyMaintained='Y' AND EXISTS (SELECT * FROM AD_Column c WHERE c.AD_Column_ID=pi.AD_Column_ID AND c.AD_Element_ID=200257)
+;
+
+SELECT register_migration_script('201212051000_IDEMPIERE_390.sql') FROM dual
+;
+
diff --git a/migration/i1.0a-release/postgresql/201212051000_IDEMPIERE_390.sql b/migration/i1.0a-release/postgresql/201212051000_IDEMPIERE_390.sql
new file mode 100644
index 0000000000..94f91c95d4
--- /dev/null
+++ b/migration/i1.0a-release/postgresql/201212051000_IDEMPIERE_390.sql
@@ -0,0 +1,277 @@
+-- Nov 30, 2012 5:06:08 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+INSERT INTO AD_Element (ColumnName,AD_Element_ID,EntityType,Name,PrintName,AD_Element_UU,AD_Client_ID,Created,Updated,AD_Org_ID,CreatedBy,UpdatedBy,IsActive) VALUES ('StorageArchive',200257,'D','StorageArchive','Storage Archive','766f13f0-dd9f-4a36-8540-f9f990a81f25',0,TO_TIMESTAMP('2012-11-30 17:06:06','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2012-11-30 17:06:06','YYYY-MM-DD HH24:MI:SS'),0,100,100,'Y')
+;
+
+-- Nov 30, 2012 5:06:08 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+INSERT INTO AD_Element_Trl (AD_Language,AD_Element_ID, Help,PO_Description,PO_Help,Name,Description,PrintName,PO_Name,PO_PrintName, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy,AD_Element_Trl_UU ) SELECT l.AD_Language,t.AD_Element_ID, t.Help,t.PO_Description,t.PO_Help,t.Name,t.Description,t.PrintName,t.PO_Name,t.PO_PrintName, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy,Generate_UUID() FROM AD_Language l, AD_Element t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Element_ID=200257 AND NOT EXISTS (SELECT * FROM AD_Element_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.AD_Element_ID=t.AD_Element_ID)
+;
+
+-- Nov 30, 2012 5:11:05 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Element SET ColumnName='StorageArchive_ID', Name='StorageArchive_ID', PrintName='Storage Archive_ID',Updated=TO_TIMESTAMP('2012-11-30 17:11:05','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Element_ID=200257
+;
+
+-- Nov 30, 2012 5:11:05 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Element_Trl SET IsTranslated='N' WHERE AD_Element_ID=200257
+;
+
+-- Nov 30, 2012 5:11:05 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Column SET ColumnName='StorageArchive_ID', Name='StorageArchive_ID', Description=NULL, Help=NULL WHERE AD_Element_ID=200257
+;
+
+-- Nov 30, 2012 5:11:05 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Process_Para SET ColumnName='StorageArchive_ID', Name='StorageArchive_ID', Description=NULL, Help=NULL, AD_Element_ID=200257 WHERE UPPER(ColumnName)='STORAGEARCHIVE_ID' AND IsCentrallyMaintained='Y' AND AD_Element_ID IS NULL
+;
+
+-- Nov 30, 2012 5:11:05 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Process_Para SET ColumnName='StorageArchive_ID', Name='StorageArchive_ID', Description=NULL, Help=NULL WHERE AD_Element_ID=200257 AND IsCentrallyMaintained='Y'
+;
+
+-- Nov 30, 2012 5:11:05 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET Name='StorageArchive_ID', Description=NULL, Help=NULL WHERE AD_Column_ID IN (SELECT AD_Column_ID FROM AD_Column WHERE AD_Element_ID=200257) AND IsCentrallyMaintained='Y'
+;
+
+-- Nov 30, 2012 5:11:05 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_PrintFormatItem SET PrintName='Storage Archive_ID', Name='StorageArchive_ID' WHERE IsCentrallyMaintained='Y' AND EXISTS (SELECT * FROM AD_Column c WHERE c.AD_Column_ID=AD_PrintFormatItem.AD_Column_ID AND c.AD_Element_ID=200257)
+;
+
+-- Nov 30, 2012 5:11:22 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+INSERT INTO AD_Column (SeqNoSelection,IsSyncDatabase,IsEncrypted,Version,AD_Table_ID,AD_Column_ID,EntityType,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsParent,FieldLength,IsSelectionColumn,AD_Reference_ID,IsKey,AD_Element_ID,IsAutocomplete,IsAllowLogging,AD_Column_UU,IsUpdateable,IsAlwaysUpdateable,ColumnName,Name,IsAllowCopy,Updated,CreatedBy,AD_Org_ID,IsActive,Created,UpdatedBy,AD_Client_ID,IsToolbarButton) VALUES (0,'N','N',0,227,201007,'U','N','N','N',0,'N',22,'N',18,'N',200257,'N','Y','764723f1-4251-4153-8198-0615453fa358','Y','N','StorageArchive_ID','StorageArchive_ID','Y',TO_TIMESTAMP('2012-11-30 17:11:21','YYYY-MM-DD HH24:MI:SS'),100,0,'Y',TO_TIMESTAMP('2012-11-30 17:11:21','YYYY-MM-DD HH24:MI:SS'),100,0,'N')
+;
+
+-- Nov 30, 2012 5:11:22 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+INSERT INTO AD_Column_Trl (AD_Language,AD_Column_ID, Name, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy,AD_Column_Trl_UU ) SELECT l.AD_Language,t.AD_Column_ID, t.Name, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy,Generate_UUID() FROM AD_Language l, AD_Column t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Column_ID=201007 AND NOT EXISTS (SELECT * FROM AD_Column_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.AD_Column_ID=t.AD_Column_ID)
+;
+
+-- Nov 30, 2012 5:14:08 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE C_AcctProcessor SET DateNextRun=TO_TIMESTAMP('2012-11-30 17:24:08','YYYY-MM-DD HH24:MI:SS'), DateLastRun=TO_TIMESTAMP('2012-11-30 17:14:08','YYYY-MM-DD HH24:MI:SS'),Updated=TO_TIMESTAMP('2012-11-30 17:14:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE C_AcctProcessor_ID=100
+;
+
+-- Nov 30, 2012 5:16:08 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+INSERT INTO AD_Reference (AD_Reference_ID,Name,EntityType,AD_Reference_UU,IsOrderByValue,Description,ValidationType,AD_Client_ID,AD_Org_ID,CreatedBy,Updated,IsActive,Created,UpdatedBy) VALUES (200023,'AD_StorageProvider_ID','D','2dc5386f-d9db-4758-a03e-e8695a286ff2','N','AD_StorageProvider_ID','T',0,0,100,TO_TIMESTAMP('2012-11-30 17:16:07','YYYY-MM-DD HH24:MI:SS'),'Y',TO_TIMESTAMP('2012-11-30 17:16:07','YYYY-MM-DD HH24:MI:SS'),100)
+;
+
+-- Nov 30, 2012 5:16:08 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+INSERT INTO AD_Reference_Trl (AD_Language,AD_Reference_ID, Help,Name,Description, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy,AD_Reference_Trl_UU ) SELECT l.AD_Language,t.AD_Reference_ID, t.Help,t.Name,t.Description, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy,Generate_UUID() FROM AD_Language l, AD_Reference t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Reference_ID=200023 AND NOT EXISTS (SELECT * FROM AD_Reference_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.AD_Reference_ID=t.AD_Reference_ID)
+;
+
+-- Nov 30, 2012 5:17:00 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+INSERT INTO AD_Ref_Table (IsValueDisplayed,AD_Reference_ID,AD_Key,AD_Display,EntityType,AD_Table_ID,AD_Ref_Table_UU,CreatedBy,Updated,Created,AD_Client_ID,UpdatedBy,AD_Org_ID,IsActive) VALUES ('N',200023,200961,200969,'D',200037,'2d31b980-72b5-4c2e-964b-91fa288f0a12',100,TO_TIMESTAMP('2012-11-30 17:17:00','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2012-11-30 17:17:00','YYYY-MM-DD HH24:MI:SS'),0,100,0,'Y')
+;
+
+-- Nov 30, 2012 5:17:57 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Column SET AD_Reference_Value_ID=200023,Updated=TO_TIMESTAMP('2012-11-30 17:17:57','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=201007
+;
+
+-- Nov 30, 2012 5:18:10 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+ALTER TABLE AD_ClientInfo ADD COLUMN StorageArchive_ID NUMERIC(10) DEFAULT NULL
+;
+
+-- Nov 30, 2012 5:20:25 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+INSERT INTO AD_Field (ColumnSpan,NumLines,SortNo,IsEncrypted,AD_Tab_ID,DisplayLength,IsSameLine,IsHeading,AD_Column_ID,SeqNo,IsCentrallyMaintained,AD_Field_ID,IsReadOnly,EntityType,Name,AD_Field_UU,IsDisplayed,IsFieldOnly,UpdatedBy,AD_Org_ID,Created,AD_Client_ID,CreatedBy,Updated,IsActive,IsDisplayedGrid,SeqNoGrid,XPosition,IsQuickEntry) VALUES (1,1,0,'N',169,0,'N','N',201007,240,'Y',200949,'N','D','StorageArchive_ID','40744096-6d57-48e7-8931-6c237ee9ac3c','Y','N',100,0,TO_TIMESTAMP('2012-11-30 17:20:24','YYYY-MM-DD HH24:MI:SS'),0,100,TO_TIMESTAMP('2012-11-30 17:20:24','YYYY-MM-DD HH24:MI:SS'),'Y','Y',320,1,'N')
+;
+
+-- Nov 30, 2012 5:20:25 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+INSERT INTO AD_Field_Trl (AD_Language,AD_Field_ID, Help,Description,Name, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy,AD_Field_Trl_UU ) SELECT l.AD_Language,t.AD_Field_ID, t.Help,t.Description,t.Name, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy,Generate_UUID() FROM AD_Language l, AD_Field t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Field_ID=200949 AND NOT EXISTS (SELECT * FROM AD_Field_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.AD_Field_ID=t.AD_Field_ID)
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET ColumnSpan=2, SeqNo=120, IsDisplayed='Y', XPosition=4,Updated=TO_TIMESTAMP('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=200949
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=130,Updated=TO_TIMESTAMP('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=9201
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=140,Updated=TO_TIMESTAMP('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=1564
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=150,Updated=TO_TIMESTAMP('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=1563
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=160,Updated=TO_TIMESTAMP('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=1562
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=170,Updated=TO_TIMESTAMP('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=1565
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=180,Updated=TO_TIMESTAMP('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=1566
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=190,Updated=TO_TIMESTAMP('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=1567
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=200,Updated=TO_TIMESTAMP('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=10319
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=210,Updated=TO_TIMESTAMP('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=10320
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=220,Updated=TO_TIMESTAMP('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=57531
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=230,Updated=TO_TIMESTAMP('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=57534
+;
+
+-- Nov 30, 2012 5:20:54 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Field SET SeqNo=240,Updated=TO_TIMESTAMP('2012-11-30 17:20:54','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=57535
+;
+
+-- Nov 30, 2012 5:30:06 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Ref_Table SET IsValueDisplayed='Y', AD_Display=200961,Updated=TO_TIMESTAMP('2012-11-30 17:30:06','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Reference_ID=200023
+;
+
+-- Nov 30, 2012 5:34:49 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario
+UPDATE AD_Ref_Table SET IsValueDisplayed='N',Updated=TO_TIMESTAMP('2012-11-30 17:34:49','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Reference_ID=200023
+;
+
+INSERT INTO ad_storageprovider
+ (ad_client_id,
+ ad_org_id,
+ ad_storageprovider_id,
+ ad_storageprovider_uu,
+ created,
+ createdby,
+ folder,
+ isactive,
+ method,
+ name,
+ password,
+ updated,
+ updatedby,
+ url,
+ username)
+SELECT
+ ad_client_id,
+ 0,
+ nextidfunc(200033,'N'),
+ generate_uuid(),
+ now(),
+ 100,
+ coalesce(windowsarchivepath, unixarchivepath),
+ 'Y',
+ 'FileSystem',
+ 'Folder',
+ null,
+ now(),
+ 100,
+ null,
+ null
+FROM ad_client
+WHERE storearchiveonfilesystem='Y' AND (windowsarchivepath is not null or unixarchivepath is not null)
+;
+
+UPDATE ad_clientinfo
+ SET storagearchive_id = (SELECT ad_storageprovider_id FROM ad_storageprovider JOIN ad_client ON ad_client.ad_client_id=ad_storageprovider.ad_client_id
+ WHERE ad_storageprovider.ad_client_id=ad_clientinfo.ad_client_id
+ AND coalesce(ad_client.windowsarchivepath, ad_client.unixarchivepath)=ad_storageprovider.folder)
+WHERE ad_clientinfo.ad_client_id IN
+ (SELECT ad_client_id FROM ad_client WHERE storearchiveonfilesystem='Y' AND (windowsarchivepath is not null or unixarchivepath is not null))
+;
+
+-- Dec 5, 2012 6:49:08 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Column SET IsActive='N',Updated=TO_TIMESTAMP('2012-12-05 18:49:08','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=50215
+;
+
+-- Dec 5, 2012 6:49:14 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Column SET IsActive='N',Updated=TO_TIMESTAMP('2012-12-05 18:49:14','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=50216
+;
+
+-- Dec 5, 2012 6:49:18 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Column SET IsActive='N',Updated=TO_TIMESTAMP('2012-12-05 18:49:18','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=50214
+;
+
+-- Dec 5, 2012 6:55:57 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Field SET IsCentrallyMaintained='N', Name='Attachment Store',Updated=TO_TIMESTAMP('2012-12-05 18:55:57','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=200948
+;
+
+-- Dec 5, 2012 6:55:57 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Field_Trl SET IsTranslated='N' WHERE AD_Field_ID=200948
+;
+
+-- Dec 5, 2012 6:56:36 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Element SET Name='Archive Store', PrintName='Archive Store',Updated=TO_TIMESTAMP('2012-12-05 18:56:36','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Element_ID=200257
+;
+
+-- Dec 5, 2012 6:56:36 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Element_Trl SET IsTranslated='N' WHERE AD_Element_ID=200257
+;
+
+-- Dec 5, 2012 6:56:36 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Column SET ColumnName='StorageArchive_ID', Name='Archive Store', Description=NULL, Help=NULL WHERE AD_Element_ID=200257
+;
+
+-- Dec 5, 2012 6:56:36 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Process_Para SET ColumnName='StorageArchive_ID', Name='Archive Store', Description=NULL, Help=NULL, AD_Element_ID=200257 WHERE UPPER(ColumnName)='STORAGEARCHIVE_ID' AND IsCentrallyMaintained='Y' AND AD_Element_ID IS NULL
+;
+
+-- Dec 5, 2012 6:56:36 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Process_Para SET ColumnName='StorageArchive_ID', Name='Archive Store', Description=NULL, Help=NULL WHERE AD_Element_ID=200257 AND IsCentrallyMaintained='Y'
+;
+
+-- Dec 5, 2012 6:56:36 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_Field SET Name='Archive Store', Description=NULL, Help=NULL WHERE AD_Column_ID IN (SELECT AD_Column_ID FROM AD_Column WHERE AD_Element_ID=200257) AND IsCentrallyMaintained='Y'
+;
+
+-- Dec 5, 2012 6:56:36 PM COT
+-- IDEMPIERE-390 Attachments/archives on load balancer scenario / Implement archive part
+UPDATE AD_PrintFormatItem SET PrintName='Archive Store', Name='Archive Store' WHERE IsCentrallyMaintained='Y' AND EXISTS (SELECT * FROM AD_Column c WHERE c.AD_Column_ID=AD_PrintFormatItem.AD_Column_ID AND c.AD_Element_ID=200257)
+;
+
+SELECT register_migration_script('201212051000_IDEMPIERE_390.sql') FROM dual
+;
+
diff --git a/org.adempiere.base.process/src/org/compiere/process/ImportProduct.java b/org.adempiere.base.process/src/org/compiere/process/ImportProduct.java
index 3b2c644945..884b94f9c5 100644
--- a/org.adempiere.base.process/src/org/compiere/process/ImportProduct.java
+++ b/org.adempiere.base.process/src/org/compiere/process/ImportProduct.java
@@ -75,6 +75,23 @@ public class ImportProduct extends SvrProcess implements ImportProcess
m_DateValue = new Timestamp (System.currentTimeMillis());
} // prepare
+ // Field to copy From Product if Import does not have value
+ private String[] strFieldsToCopy = new String[] {
+ "Value",
+ "Name",
+ "Description",
+ "DocumentNote",
+ "Help",
+ "UPC",
+ "SKU",
+ "Classification",
+ "ProductType",
+ "Discontinued",
+ "DiscontinuedBy",
+ "DiscontinuedAt",
+ "ImageURL",
+ "DescriptionURL"
+ };
/**
* Perform process.
@@ -183,20 +200,17 @@ public class ImportProduct extends SvrProcess implements ImportProcess
// Copy From Product if Import does not have value
- String[] strFields = new String[] {"Value","Name","Description","DocumentNote","Help",
- "UPC","SKU","Classification","ProductType",
- "Discontinued","DiscontinuedBy","DiscontinuedAt","ImageURL","DescriptionURL"};
- for (int i = 0; i < strFields.length; i++)
+ for (int i = 0; i < strFieldsToCopy.length; i++)
{
sql = new StringBuilder ("UPDATE I_Product i ")
- .append("SET ").append(strFields[i]).append(" = (SELECT ").append(strFields[i]).append(" FROM M_Product p")
+ .append("SET ").append(strFieldsToCopy[i]).append(" = (SELECT ").append(strFieldsToCopy[i]).append(" FROM M_Product p")
.append(" WHERE i.M_Product_ID=p.M_Product_ID AND i.AD_Client_ID=p.AD_Client_ID) ")
.append("WHERE M_Product_ID IS NOT NULL")
- .append(" AND ").append(strFields[i]).append(" IS NULL")
+ .append(" AND ").append(strFieldsToCopy[i]).append(" IS NULL")
.append(" AND I_IsImported='N'").append(clientCheck);
no = DB.executeUpdate(sql.toString(), get_TrxName());
if (no != 0)
- log.fine(strFields[i] + " - default from existing Product=" + no);
+ log.fine(strFieldsToCopy[i] + " - default from existing Product=" + no);
}
String[] numFields = new String[] {"C_UOM_ID","M_Product_Category_ID",
"Volume","Weight","ShelfWidth","ShelfHeight","ShelfDepth","UnitsPerPallet"};
diff --git a/org.adempiere.base/META-INF/MANIFEST.MF b/org.adempiere.base/META-INF/MANIFEST.MF
index 8480db8d8c..266ab82c21 100644
--- a/org.adempiere.base/META-INF/MANIFEST.MF
+++ b/org.adempiere.base/META-INF/MANIFEST.MF
@@ -291,6 +291,6 @@ Import-Package: com.sun.mail.auth;version="1.4.5",
Eclipse-BuddyPolicy: registered
Eclipse-ExtensibleAPI: true
Bundle-Activator: org.adempiere.base.BaseActivator
-Service-Component: OSGI-INF/eventmanager.xml, OSGI-INF/dslocator.xml, OSGI-INF/extensionlocator.xml, OSGI-INF/serverbean.xml, OSGI-INF/statusbean.xml, OSGI-INF/defaultmodelfactory.xml, OSGI-INF/defaultdocfactory.xml, OSGI-INF/AttachmentFile.xml, OSGI-INF/AttachmentDB.xml
+Service-Component: OSGI-INF/eventmanager.xml, OSGI-INF/dslocator.xml, OSGI-INF/extensionlocator.xml, OSGI-INF/serverbean.xml, OSGI-INF/statusbean.xml, OSGI-INF/defaultmodelfactory.xml, OSGI-INF/defaultdocfactory.xml, OSGI-INF/attachmentfile.xml, OSGI-INF/attachmentdb.xml,OSGI-INF/archivedb.xml,OSGI-INF/archivefile.xml
Bundle-ActivationPolicy: lazy
Require-Bundle: org.eclipse.equinox.app;bundle-version="1.3.1"
diff --git a/org.adempiere.base/OSGI-INF/archivedb.xml b/org.adempiere.base/OSGI-INF/archivedb.xml
new file mode 100644
index 0000000000..6f526e94a3
--- /dev/null
+++ b/org.adempiere.base/OSGI-INF/archivedb.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/org.adempiere.base/OSGI-INF/archivefile.xml b/org.adempiere.base/OSGI-INF/archivefile.xml
new file mode 100644
index 0000000000..8db2274033
--- /dev/null
+++ b/org.adempiere.base/OSGI-INF/archivefile.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/org.adempiere.base/OSGI-INF/AttachmentDB.xml b/org.adempiere.base/OSGI-INF/attachmentdb.xml
similarity index 85%
rename from org.adempiere.base/OSGI-INF/AttachmentDB.xml
rename to org.adempiere.base/OSGI-INF/attachmentdb.xml
index 51232ec3a1..9a8be1e7b0 100644
--- a/org.adempiere.base/OSGI-INF/AttachmentDB.xml
+++ b/org.adempiere.base/OSGI-INF/attachmentdb.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/org.adempiere.base/OSGI-INF/AttachmentFile.xml b/org.adempiere.base/OSGI-INF/attachmentfile.xml
similarity index 85%
rename from org.adempiere.base/OSGI-INF/AttachmentFile.xml
rename to org.adempiere.base/OSGI-INF/attachmentfile.xml
index 41b3a0535b..f04bf80d2f 100644
--- a/org.adempiere.base/OSGI-INF/AttachmentFile.xml
+++ b/org.adempiere.base/OSGI-INF/attachmentfile.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/org.adempiere.base/src/org/adempiere/util/ProcessUtil.java b/org.adempiere.base/src/org/adempiere/util/ProcessUtil.java
index df25e38c2b..c26e3d1c4b 100644
--- a/org.adempiere.base/src/org/adempiere/util/ProcessUtil.java
+++ b/org.adempiere.base/src/org/adempiere/util/ProcessUtil.java
@@ -219,13 +219,16 @@ public final class ProcessUtil {
{
pi.setSummary (Msg.getMsg(Env.getCtx(), "ProcessError") + " " + e.getLocalizedMessage(), true);
log.log(Level.SEVERE, pi.getClassName(), e);
+ success = false;
return false;
}
finally
{
if (trx != null && managedTrx)
{
- trx.rollback();
+ if (!success) {
+ trx.rollback();
+ }
trx.close();
trx = null;
}
diff --git a/org.adempiere.base/src/org/compiere/acct/Doc_Production.java b/org.adempiere.base/src/org/compiere/acct/Doc_Production.java
index c99f1b985a..334459ddc2 100644
--- a/org.adempiere.base/src/org/compiere/acct/Doc_Production.java
+++ b/org.adempiere.base/src/org/compiere/acct/Doc_Production.java
@@ -197,12 +197,12 @@ public class Doc_Production extends Doc
fl = fact.createLine(line,
account,
as.getC_Currency_ID(), variance.negate());
- fl.setQty(Env.ZERO);
if (fl == null)
{
p_Error = "Couldn't post variance " + line.getLine() + " - " + line;
return null;
}
+ fl.setQty(Env.ZERO);
}
// costs = bomCost.negate();
}
diff --git a/org.adempiere.base/src/org/compiere/db/CConnection.java b/org.adempiere.base/src/org/compiere/db/CConnection.java
index 6f77bc3a57..c74ec35c95 100644
--- a/org.adempiere.base/src/org/compiere/db/CConnection.java
+++ b/org.adempiere.base/src/org/compiere/db/CConnection.java
@@ -871,8 +871,9 @@ public class CConnection implements Serializable, Cloneable
// System.out.println ("CConnection.setDataSource - " + m_ds + " - Client=" + Ini.isClient());
if (m_ds == null && Ini.isClient())
{
- if (getDatabase() != null) // no db selected
- m_ds = getDatabase().getDataSource(this);
+ AdempiereDatabase getDB = getDatabase();
+ if (getDB != null) // no db selected
+ m_ds = getDB.getDataSource(this);
// System.out.println ("CConnection.setDataSource - " + m_ds);
}
return m_ds != null;
diff --git a/org.adempiere.base/src/org/compiere/dbPort/Convert.java b/org.adempiere.base/src/org/compiere/dbPort/Convert.java
index 349694dd12..6c94b6114a 100644
--- a/org.adempiere.base/src/org/compiere/dbPort/Convert.java
+++ b/org.adempiere.base/src/org/compiere/dbPort/Convert.java
@@ -477,51 +477,54 @@ public abstract class Convert
}
}
+
+ private static String [] dontLogTables = new String[] {
+ "AD_ACCESSLOG",
+ "AD_ALERTPROCESSORLOG",
+ "AD_CHANGELOG",
+ "AD_DOCUMENT_ACTION_ACCESS",
+ "AD_FORM_ACCESS",
+ "AD_ISSUE",
+ "AD_LDAPPROCESSORLOG",
+ "AD_PACKAGE_IMP",
+ "AD_PACKAGE_IMP_BACKUP",
+ "AD_PACKAGE_IMP_DETAIL",
+ "AD_PACKAGE_IMP_INST",
+ "AD_PACKAGE_IMP_PROC",
+ "AD_PINSTANCE",
+ "AD_PINSTANCE_LOG",
+ "AD_PINSTANCE_PARA",
+ "AD_PROCESS_ACCESS",
+ "AD_RECENTITEM",
+ "AD_REPLICATION_LOG",
+ "AD_SCHEDULERLOG",
+ "AD_SESSION",
+ "AD_WINDOW_ACCESS",
+ "AD_WORKFLOW_ACCESS",
+ "AD_WORKFLOWPROCESSORLOG",
+ "CM_WEBACCESSLOG",
+ "C_ACCTPROCESSORLOG",
+ "K_INDEXLOG",
+ "R_REQUESTPROCESSORLOG",
+ "T_AGING",
+ "T_ALTER_COLUMN",
+ "T_DISTRIBUTIONRUNDETAIL",
+ "T_INVENTORYVALUE",
+ "T_INVOICEGL",
+ "T_REPLENISH",
+ "T_REPORT",
+ "T_REPORTSTATEMENT",
+ "T_SELECTION",
+ "T_SELECTION2",
+ "T_SPOOL",
+ "T_TRANSACTION",
+ "T_TRIALBALANCE"
+ };
+
private static boolean dontLog(String statement) {
// Do not log *Access records - teo_Sarca BF [ 2782095 ]
// IDEMPIERE-323 Migration script log AD_Document_Action_Access (nmicoud / CarlosRuiz_globalqss)
- String [] exceptionTables = new String[] {
- "AD_ACCESSLOG",
- "AD_ALERTPROCESSORLOG",
- "AD_CHANGELOG",
- "AD_DOCUMENT_ACTION_ACCESS",
- "AD_FORM_ACCESS",
- "AD_ISSUE",
- "AD_LDAPPROCESSORLOG",
- "AD_PACKAGE_IMP",
- "AD_PACKAGE_IMP_BACKUP",
- "AD_PACKAGE_IMP_DETAIL",
- "AD_PACKAGE_IMP_INST",
- "AD_PACKAGE_IMP_PROC",
- "AD_PINSTANCE",
- "AD_PINSTANCE_LOG",
- "AD_PINSTANCE_PARA",
- "AD_PROCESS_ACCESS",
- "AD_RECENTITEM",
- "AD_REPLICATION_LOG",
- "AD_SCHEDULERLOG",
- "AD_SESSION",
- "AD_WINDOW_ACCESS",
- "AD_WORKFLOW_ACCESS",
- "AD_WORKFLOWPROCESSORLOG",
- "CM_WEBACCESSLOG",
- "C_ACCTPROCESSORLOG",
- "K_INDEXLOG",
- "R_REQUESTPROCESSORLOG",
- "T_AGING",
- "T_ALTER_COLUMN",
- "T_DISTRIBUTIONRUNDETAIL",
- "T_INVENTORYVALUE",
- "T_INVOICEGL",
- "T_REPLENISH",
- "T_REPORT",
- "T_REPORTSTATEMENT",
- "T_SELECTION",
- "T_SELECTION2",
- "T_SPOOL",
- "T_TRANSACTION",
- "T_TRIALBALANCE"
- };
+
String uppStmt = statement.toUpperCase().trim();
// don't log selects
if (uppStmt.startsWith("SELECT "))
@@ -532,16 +535,16 @@ public abstract class Convert
// Don't log DELETE FROM Some_Table WHERE AD_Table_ID=? AND Record_ID=?
if (uppStmt.startsWith("DELETE FROM ") && uppStmt.endsWith(" WHERE AD_TABLE_ID=? AND RECORD_ID=?"))
return true;
- for (int i = 0; i < exceptionTables.length; i++) {
- if (uppStmt.startsWith("INSERT INTO " + exceptionTables[i] + " "))
+ for (int i = 0; i < dontLogTables.length; i++) {
+ if (uppStmt.startsWith("INSERT INTO " + dontLogTables[i] + " "))
return true;
- if (uppStmt.startsWith("DELETE FROM " + exceptionTables[i] + " "))
+ if (uppStmt.startsWith("DELETE FROM " + dontLogTables[i] + " "))
return true;
- if (uppStmt.startsWith("DELETE " + exceptionTables[i] + " "))
+ if (uppStmt.startsWith("DELETE " + dontLogTables[i] + " "))
return true;
- if (uppStmt.startsWith("UPDATE " + exceptionTables[i] + " "))
+ if (uppStmt.startsWith("UPDATE " + dontLogTables[i] + " "))
return true;
- if (uppStmt.startsWith("INSERT INTO " + exceptionTables[i] + "("))
+ if (uppStmt.startsWith("INSERT INTO " + dontLogTables[i] + "("))
return true;
}
diff --git a/org.adempiere.base/src/org/compiere/model/ArchiveDB.java b/org.adempiere.base/src/org/compiere/model/ArchiveDB.java
new file mode 100644
index 0000000000..455498d024
--- /dev/null
+++ b/org.adempiere.base/src/org/compiere/model/ArchiveDB.java
@@ -0,0 +1,110 @@
+/******************************************************************************
+ * Product: iDempiere ERP & CRM Smart Business Solution *
+ * Copyright (C) 2012 Trek Global *
+ * This program is free software; you can redistribute it and/or modify it *
+ * under the terms version 2 of the GNU General Public License as published *
+ * by the Free Software Foundation. This program is distributed in the hope *
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
+ * See the GNU General Public License for more details. *
+ * You should have received a copy of the GNU General Public License along *
+ * with this program; if not, write to the Free Software Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
+ *****************************************************************************/
+package org.compiere.model;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.logging.Level;
+import java.util.zip.Deflater;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+import org.compiere.util.CLogger;
+
+/**
+ * @author juliana
+ *
+ */
+public class ArchiveDB implements IArchiveStore {
+
+
+ private final CLogger log = CLogger.getCLogger(getClass());
+
+ /* (non-Javadoc)
+ * @see org.compiere.model.IArchiveStore#loadLOBData(org.compiere.model.MArchive, org.compiere.model.MStorageProvider)
+ */
+ @Override
+ public byte[] loadLOBData(MArchive archive, MStorageProvider prov) {
+ byte[] deflatedData = archive.getByteData();
+ if (deflatedData == null)
+ return null;
+ //
+ log.fine("ZipSize=" + deflatedData.length);
+ if (deflatedData.length == 0)
+ return null;
+
+ byte[] inflatedData = null;
+ try {
+ ByteArrayInputStream in = new ByteArrayInputStream(deflatedData);
+ ZipInputStream zip = new ZipInputStream(in);
+ ZipEntry entry = zip.getNextEntry();
+ if (entry != null) // just one entry
+ {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ byte[] buffer = new byte[2048];
+ int length = zip.read(buffer);
+ while (length != -1) {
+ out.write(buffer, 0, length);
+ length = zip.read(buffer);
+ }
+ //
+ inflatedData = out.toByteArray();
+ log.fine("Size=" + inflatedData.length + " - zip=" + entry.getCompressedSize()
+ + "(" + entry.getSize() + ") "
+ + (entry.getCompressedSize() * 100 / entry.getSize()) + "%");
+ }
+ } catch (Exception e) {
+ log.log(Level.SEVERE, "", e);
+ inflatedData = null;
+ }
+ return inflatedData;
+ }
+
+ /* (non-Javadoc)
+ * @see org.compiere.model.IArchiveStore#save(org.compiere.model.MArchive, org.compiere.model.MStorageProvider, byte[])
+ */
+ @Override
+ public void save(MArchive archive, MStorageProvider prov,byte[] inflatedData) {
+ if (inflatedData == null || inflatedData.length == 0)
+ throw new IllegalArgumentException("InflatedData is NULL");
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ZipOutputStream zip = new ZipOutputStream(out);
+ zip.setMethod(ZipOutputStream.DEFLATED);
+ zip.setLevel(Deflater.BEST_COMPRESSION);
+ zip.setComment("idempiere");
+ //
+ byte[] deflatedData = null;
+ try {
+ ZipEntry entry = new ZipEntry("IdempiereArchive");
+ entry.setTime(System.currentTimeMillis());
+ entry.setMethod(ZipEntry.DEFLATED);
+ zip.putNextEntry(entry);
+ zip.write(inflatedData, 0, inflatedData.length);
+ zip.closeEntry();
+ log.fine(entry.getCompressedSize() + " (" + entry.getSize() + ") "
+ + (entry.getCompressedSize() * 100 / entry.getSize()) + "%");
+ //
+ // zip.finish();
+ zip.close();
+ deflatedData = out.toByteArray();
+ log.fine("Length=" + inflatedData.length);
+ } catch (Exception e) {
+ log.log(Level.SEVERE, "saveLOBData", e);
+ deflatedData = null;
+ }
+ archive.setByteData(deflatedData);
+ }
+
+}
diff --git a/org.adempiere.base/src/org/compiere/model/ArchiveFileSystem.java b/org.adempiere.base/src/org/compiere/model/ArchiveFileSystem.java
new file mode 100644
index 0000000000..c7b38dac9a
--- /dev/null
+++ b/org.adempiere.base/src/org/compiere/model/ArchiveFileSystem.java
@@ -0,0 +1,229 @@
+/******************************************************************************
+ * Product: iDempiere ERP & CRM Smart Business Solution *
+ * Copyright (C) 2012 Trek Global *
+ * This program is free software; you can redistribute it and/or modify it *
+ * under the terms version 2 of the GNU General Public License as published *
+ * by the Free Software Foundation. This program is distributed in the hope *
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
+ * See the GNU General Public License for more details. *
+ * You should have received a copy of the GNU General Public License along *
+ * with this program; if not, write to the Free Software Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
+ *****************************************************************************/
+
+package org.compiere.model;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.logging.Level;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.Result;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+
+import org.compiere.util.CLogger;
+import org.compiere.util.Util;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+import org.w3c.dom.Element;
+
+/**
+ * @author juliana
+ *
+ */
+public class ArchiveFileSystem implements IArchiveStore {
+
+ private String ARCHIVE_FOLDER_PLACEHOLDER = "%ARCHIVE_FOLDER%";
+
+ private final CLogger log = CLogger.getCLogger(getClass());
+
+
+ /* (non-Javadoc)
+ * @see org.compiere.model.IArchiveStore#loadLOBData(org.compiere.model.MArchive, org.compiere.model.MStorageProvider)
+ */
+ @Override
+ public byte[] loadLOBData(MArchive archive, MStorageProvider prov) {
+ String archivePathRoot = getArchivePathRoot(prov);
+ if ("".equals(archivePathRoot)) {
+ throw new IllegalArgumentException("no attachmentPath defined");
+ }
+ byte[] data = archive.getByteData();
+ if (data == null) {
+ return null;
+ }
+
+ final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+
+ try {
+ final DocumentBuilder builder = factory.newDocumentBuilder();
+ final Document document = builder.parse(new ByteArrayInputStream(data));
+ final NodeList entries = document.getElementsByTagName("entry");
+ if(entries.getLength()!=1){
+ log.severe("no archive entry found");
+ }
+ final Node entryNode = entries.item(0);
+ final NamedNodeMap attributes = entryNode.getAttributes();
+ final Node fileNode = attributes.getNamedItem("file");
+ if(fileNode==null ){
+ log.severe("no filename for entry");
+ return null;
+ }
+ String filePath = fileNode.getNodeValue();
+ log.fine("filePath: " + filePath);
+ if(filePath!=null){
+ filePath = filePath.replaceFirst(ARCHIVE_FOLDER_PLACEHOLDER, archivePathRoot.replaceAll("\\\\","\\\\\\\\"));
+ //just to be shure...
+ String replaceSeparator = File.separator;
+ if(!replaceSeparator.equals("/")){
+ replaceSeparator = "\\\\";
+ }
+ filePath = filePath.replaceAll("/", replaceSeparator);
+ filePath = filePath.replaceAll("\\\\", replaceSeparator);
+ }
+ log.fine("filePath: " + filePath);
+ final File file = new File(filePath);
+ if (file.exists()) {
+ // read files into byte[]
+ final byte[] dataEntry = new byte[(int) file.length()];
+ try {
+ final FileInputStream fileInputStream = new FileInputStream(file);
+ fileInputStream.read(dataEntry);
+ fileInputStream.close();
+ } catch (FileNotFoundException e) {
+ log.severe("File Not Found.");
+ e.printStackTrace();
+ } catch (IOException e1) {
+ log.severe("Error Reading The File.");
+ e1.printStackTrace();
+ }
+ return dataEntry;
+ } else {
+ log.severe("file not found: " + file.getAbsolutePath());
+ return null;
+ }
+
+ } catch (SAXException sxe) {
+ // Error generated during parsing)
+ Exception x = sxe;
+ if (sxe.getException() != null)
+ x = sxe.getException();
+ x.printStackTrace();
+ log.severe(x.getMessage());
+
+ } catch (ParserConfigurationException pce) {
+ // Parser with specified options can't be built
+ pce.printStackTrace();
+ log.severe(pce.getMessage());
+
+ } catch (IOException ioe) {
+ // I/O error
+ ioe.printStackTrace();
+ log.severe(ioe.getMessage());
+ }
+
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.compiere.model.IArchiveStore#save(org.compiere.model.MArchive, org.compiere.model.MStorageProvider)
+ */
+ @Override
+ public void save(MArchive archive, MStorageProvider prov,byte[] inflatedData) {
+ String archivePathRoot = getArchivePathRoot(prov);
+ if ("".equals(archivePathRoot)) {
+ throw new IllegalArgumentException("no attachmentPath defined");
+ }
+ if (inflatedData == null || inflatedData.length == 0) {
+ throw new IllegalArgumentException("InflatedData is NULL");
+ }
+ if(archive.get_ID()==0){
+ //set binary data otherwise save will fail
+ archive.setByteData(new byte[]{'0'});
+ if(!archive.save()) {
+ throw new IllegalArgumentException("unable to save MArchive");
+ }
+ }
+ final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ BufferedOutputStream out = null;
+ try {
+ // create destination folder
+ StringBuilder msgfile = new StringBuilder().append(archivePathRoot).append(File.separator)
+ .append(archive.getArchivePathSnippet());
+ final File destFolder = new File(msgfile.toString());
+ if (!destFolder.exists()) {
+ if (!destFolder.mkdirs()) {
+ log.warning("unable to create folder: " + destFolder.getPath());
+ }
+ }
+ // write to pdf
+ msgfile = new StringBuilder().append(archivePathRoot).append(File.separator)
+ .append(archive.getArchivePathSnippet()).append(archive.get_ID()).append(".pdf");
+ final File destFile = new File(msgfile.toString());
+
+ out = new BufferedOutputStream(new FileOutputStream(destFile));
+ out.write(inflatedData);
+ out.flush();
+
+ //create xml entry
+ final DocumentBuilder builder = factory.newDocumentBuilder();
+ final Document document = builder.newDocument();
+ final Element root = document.createElement("archive");
+ document.appendChild(root);
+ document.setXmlStandalone(true);
+ final Element entry = document.createElement("entry");
+ StringBuilder msgsat = new StringBuilder(ARCHIVE_FOLDER_PLACEHOLDER).append(archive.getArchivePathSnippet()).append(archive.get_ID()).append(".pdf");
+ entry.setAttribute("file", msgsat.toString());
+ root.appendChild(entry);
+ final Source source = new DOMSource(document);
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ final Result result = new StreamResult(bos);
+ final Transformer xformer = TransformerFactory.newInstance().newTransformer();
+ xformer.transform(source, result);
+ final byte[] xmlData = bos.toByteArray();
+ log.fine(bos.toString());
+ //store xml in db
+ archive.setByteData(xmlData);
+
+ } catch (Exception e) {
+ log.log(Level.SEVERE, "saveLOBData", e);
+ archive.setByteData(null);
+ } finally {
+ if(out != null){
+ try {
+ out.close();
+ } catch (Exception e) { }
+ }
+ }
+
+ }
+
+ private String getArchivePathRoot(MStorageProvider prov) {
+ String archivePathRoot = prov.getFolder();
+ if (archivePathRoot == null)
+ archivePathRoot = "";
+ if (Util.isEmpty(archivePathRoot)) {
+ log.severe("no archivePath defined");
+ } else if (!archivePathRoot.endsWith(File.separator)){
+ archivePathRoot = archivePathRoot + File.separator;
+ log.fine(archivePathRoot);
+ }
+ return archivePathRoot;
+ }
+
+}
diff --git a/org.adempiere.base/src/org/compiere/model/AttachmentFileSystem.java b/org.adempiere.base/src/org/compiere/model/AttachmentFileSystem.java
index ca45f68490..72fb98be88 100644
--- a/org.adempiere.base/src/org/compiere/model/AttachmentFileSystem.java
+++ b/org.adempiere.base/src/org/compiere/model/AttachmentFileSystem.java
@@ -35,6 +35,7 @@ import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.compiere.util.CLogger;
+import org.compiere.util.Util;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
@@ -50,24 +51,9 @@ public class AttachmentFileSystem implements IAttachmentStore {
private final CLogger log = CLogger.getCLogger(getClass());
- public String m_attachmentPathRoot;
-
@Override
public boolean save(MAttachment attach,MStorageProvider prov) {
-
- /*if(File.separatorChar == '\\'){
- m_attachmentPathRoot = prov.getWi;
- } else {
- m_attachmentPathRoot = prov.getUnixAttachmentPath();
- }*/
- m_attachmentPathRoot=prov.getFolder();
- if("".equals(m_attachmentPathRoot)){
- log.severe("no attachmentPath defined");
- } else if (!m_attachmentPathRoot.endsWith(File.separator)){
- m_attachmentPathRoot = m_attachmentPathRoot + File.separator;
- log.fine(m_attachmentPathRoot);
- }
-
+ String attachmentPathRoot = getAttachmentPathRoot(prov);
if (attach.m_items == null || attach.m_items.size() == 0) {
attach.setBinaryData(null);
return true;
@@ -85,21 +71,21 @@ public class AttachmentFileSystem implements IAttachmentStore {
File entryFile = attach.m_items.get(i).getFile();
final String path = entryFile.getAbsolutePath();
// if local file - copy to central attachment folder
- log.fine(path + " - " + attach.m_attachmentPathRoot);
- if (!path.startsWith(attach.m_attachmentPathRoot)) {
+ log.fine(path + " - " + attachmentPathRoot);
+ if (!path.startsWith(attachmentPathRoot)) {
log.fine("move file: " + path);
FileChannel in = null;
FileChannel out = null;
try {
//create destination folder
- StringBuilder msgfile = new StringBuilder().append(attach.m_attachmentPathRoot).append(File.separator).append(getAttachmentPathSnippet(attach));
+ StringBuilder msgfile = new StringBuilder().append(attachmentPathRoot).append(File.separator).append(getAttachmentPathSnippet(attach));
final File destFolder = new File(msgfile.toString());
if(!destFolder.exists()){
if(!destFolder.mkdirs()){
log.warning("unable to create folder: " + destFolder.getPath());
}
}
- msgfile = new StringBuilder().append(attach.m_attachmentPathRoot).append(File.separator)
+ msgfile = new StringBuilder().append(attachmentPathRoot).append(File.separator)
.append(getAttachmentPathSnippet(attach)).append(File.separator).append(entryFile.getName());
final File destFile = new File(msgfile.toString());
in = new FileInputStream(entryFile).getChannel();
@@ -117,7 +103,7 @@ public class AttachmentFileSystem implements IAttachmentStore {
} catch (IOException e) {
e.printStackTrace();
log.severe("unable to copy file " + entryFile.getAbsolutePath() + " to "
- + attach.m_attachmentPathRoot + File.separator +
+ + attachmentPathRoot + File.separator +
getAttachmentPathSnippet(attach) + File.separator + entryFile.getName());
} finally {
if (in != null && in.isOpen()) {
@@ -132,7 +118,7 @@ public class AttachmentFileSystem implements IAttachmentStore {
//entry.setAttribute("name", m_items.get(i).getName());
entry.setAttribute("name", attach.getEntryName(i));
String filePathToStore = entryFile.getAbsolutePath();
- filePathToStore = filePathToStore.replaceFirst(attach.m_attachmentPathRoot.replaceAll("\\\\","\\\\\\\\"), attach.ATTACHMENT_FOLDER_PLACEHOLDER);
+ filePathToStore = filePathToStore.replaceFirst(attachmentPathRoot.replaceAll("\\\\","\\\\\\\\"), attach.ATTACHMENT_FOLDER_PLACEHOLDER);
log.fine(filePathToStore);
entry.setAttribute("file", filePathToStore);
root.appendChild(entry);
@@ -158,7 +144,8 @@ public class AttachmentFileSystem implements IAttachmentStore {
@Override
public boolean loadLOBData(MAttachment attach,MStorageProvider prov) {
- if("".equals(attach.m_attachmentPathRoot)){
+ String attachmentPathRoot = getAttachmentPathRoot(prov);
+ if (Util.isEmpty(attachmentPathRoot)) {
log.severe("no attachmentPath defined");
return false;
}
@@ -192,7 +179,7 @@ public class AttachmentFileSystem implements IAttachmentStore {
String filePath = fileNode.getNodeValue();
log.fine("filePath: " + filePath);
if(filePath!=null){
- filePath = filePath.replaceFirst(attach.ATTACHMENT_FOLDER_PLACEHOLDER, attach.m_attachmentPathRoot.replaceAll("\\\\","\\\\\\\\"));
+ filePath = filePath.replaceFirst(attach.ATTACHMENT_FOLDER_PLACEHOLDER, attachmentPathRoot.replaceAll("\\\\","\\\\\\\\"));
//just to be shure...
String replaceSeparator = File.separator;
if(!replaceSeparator.equals("/")){
@@ -271,7 +258,8 @@ public class AttachmentFileSystem implements IAttachmentStore {
}
}
}
- final File folder = new File(m_attachmentPathRoot + getAttachmentPathSnippet(attach));
+ String attachmentPathRoot = getAttachmentPathRoot(prov);
+ final File folder = new File(attachmentPathRoot + getAttachmentPathSnippet(attach));
if (folder.exists()) {
if (!folder.delete()) {
log.warning("unable to delete " + folder.getAbsolutePath());
@@ -295,5 +283,18 @@ public class AttachmentFileSystem implements IAttachmentStore {
log.config("Index=" + index + " - NewSize=" + attach.m_items.size());
return true;
}
-
+
+ private String getAttachmentPathRoot(MStorageProvider prov) {
+ String attachmentPathRoot = prov.getFolder();
+ if (attachmentPathRoot == null)
+ attachmentPathRoot = "";
+ if (Util.isEmpty(attachmentPathRoot)) {
+ log.severe("no attachmentPath defined");
+ } else if (!attachmentPathRoot.endsWith(File.separator)){
+ attachmentPathRoot = attachmentPathRoot + File.separator;
+ log.fine(attachmentPathRoot);
+ }
+ return attachmentPathRoot;
+ }
+
}
diff --git a/org.adempiere.base/src/org/compiere/model/IArchiveStore.java b/org.adempiere.base/src/org/compiere/model/IArchiveStore.java
new file mode 100644
index 0000000000..f3a7ea92ea
--- /dev/null
+++ b/org.adempiere.base/src/org/compiere/model/IArchiveStore.java
@@ -0,0 +1,23 @@
+/******************************************************************************
+ * Product: iDempiere ERP & CRM Smart Business Solution *
+ * Copyright (C) 2012 Trek Global *
+ * This program is free software; you can redistribute it and/or modify it *
+ * under the terms version 2 of the GNU General Public License as published *
+ * by the Free Software Foundation. This program is distributed in the hope *
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
+ * See the GNU General Public License for more details. *
+ * You should have received a copy of the GNU General Public License along *
+ * with this program; if not, write to the Free Software Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
+ *****************************************************************************/
+package org.compiere.model;
+
+public interface IArchiveStore {
+
+ public byte[] loadLOBData(MArchive archive,MStorageProvider prov);
+
+ public void save(MArchive archive, MStorageProvider prov,byte[] inflatedData);
+
+
+}
diff --git a/org.adempiere.base/src/org/compiere/model/I_AD_Client.java b/org.adempiere.base/src/org/compiere/model/I_AD_Client.java
index 376ca28e16..5aad041fc2 100644
--- a/org.adempiere.base/src/org/compiere/model/I_AD_Client.java
+++ b/org.adempiere.base/src/org/compiere/model/I_AD_Client.java
@@ -399,24 +399,6 @@ public interface I_AD_Client
*/
public int getSMTPPort();
- /** Column name StoreArchiveOnFileSystem */
- public static final String COLUMNNAME_StoreArchiveOnFileSystem = "StoreArchiveOnFileSystem";
-
- /** Set Store Archive On File System */
- public void setStoreArchiveOnFileSystem (boolean StoreArchiveOnFileSystem);
-
- /** Get Store Archive On File System */
- public boolean isStoreArchiveOnFileSystem();
-
- /** Column name UnixArchivePath */
- public static final String COLUMNNAME_UnixArchivePath = "UnixArchivePath";
-
- /** Set Unix Archive Path */
- public void setUnixArchivePath (String UnixArchivePath);
-
- /** Get Unix Archive Path */
- public String getUnixArchivePath();
-
/** Column name Updated */
public static final String COLUMNNAME_Updated = "Updated";
@@ -445,13 +427,4 @@ public interface I_AD_Client
* Search key for the record in the format required - must be unique
*/
public String getValue();
-
- /** Column name WindowsArchivePath */
- public static final String COLUMNNAME_WindowsArchivePath = "WindowsArchivePath";
-
- /** Set Windows Archive Path */
- public void setWindowsArchivePath (String WindowsArchivePath);
-
- /** Get Windows Archive Path */
- public String getWindowsArchivePath();
}
diff --git a/org.adempiere.base/src/org/compiere/model/I_AD_ClientInfo.java b/org.adempiere.base/src/org/compiere/model/I_AD_ClientInfo.java
index e7dbd8fee7..84f5c931ab 100644
--- a/org.adempiere.base/src/org/compiere/model/I_AD_ClientInfo.java
+++ b/org.adempiere.base/src/org/compiere/model/I_AD_ClientInfo.java
@@ -74,10 +74,10 @@ public interface I_AD_ClientInfo
/** Column name AD_StorageProvider_ID */
public static final String COLUMNNAME_AD_StorageProvider_ID = "AD_StorageProvider_ID";
- /** Set AD_StorageProvider_ID */
+ /** Set Storage Provider */
public void setAD_StorageProvider_ID (int AD_StorageProvider_ID);
- /** Get AD_StorageProvider_ID */
+ /** Get Storage Provider */
public int getAD_StorageProvider_ID();
public org.compiere.model.I_AD_StorageProvider getAD_StorageProvider() throws RuntimeException;
@@ -400,6 +400,17 @@ public interface I_AD_ClientInfo
public org.compiere.model.I_M_Product getM_ProductFreight() throws RuntimeException;
+ /** Column name StorageArchive_ID */
+ public static final String COLUMNNAME_StorageArchive_ID = "StorageArchive_ID";
+
+ /** Set StorageArchive_ID */
+ public void setStorageArchive_ID (int StorageArchive_ID);
+
+ /** Get StorageArchive_ID */
+ public int getStorageArchive_ID();
+
+ public org.compiere.model.I_AD_StorageProvider getStorageArchive() throws RuntimeException;
+
/** Column name Updated */
public static final String COLUMNNAME_Updated = "Updated";
diff --git a/org.adempiere.base/src/org/compiere/model/MArchive.java b/org.adempiere.base/src/org/compiere/model/MArchive.java
index 4d3b747fa6..dd496b914e 100644
--- a/org.adempiere.base/src/org/compiere/model/MArchive.java
+++ b/org.adempiere.base/src/org/compiere/model/MArchive.java
@@ -16,44 +16,18 @@
*****************************************************************************/
package org.compiere.model;
-import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
import java.io.InputStream;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Properties;
import java.util.logging.Level;
-import java.util.zip.Deflater;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-import java.util.zip.ZipOutputStream;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.Result;
-import javax.xml.transform.Source;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.Env;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.xml.sax.SAXException;
/**
* Archive Model
@@ -65,7 +39,7 @@ public class MArchive extends X_AD_Archive {
/**
*
*/
- private static final long serialVersionUID = -3476918478008050158L;
+ private static final long serialVersionUID = 3217541537768473865L;
/**
* Get Archives
@@ -116,10 +90,6 @@ public class MArchive extends X_AD_Archive {
/** Logger */
private static CLogger s_log = CLogger.getCLogger(MArchive.class);
- private Integer m_inflated = null;
-
- private Integer m_deflated = null;
-
/***************************************************************************
* Standard Constructor
*
@@ -169,21 +139,9 @@ public class MArchive extends X_AD_Archive {
setAD_Table_ID(info.getAD_Table_ID());
setRecord_ID(info.getRecord_ID());
setC_BPartner_ID(info.getC_BPartner_ID());
- initArchiveStoreDetails(ctx, trxName);
} // MArchive
- /** is this client using the file system for archive */
- private boolean isStoreArchiveOnFileSystem = false;
-
- /** archive (root) path - if file system is used */
- private String m_archivePathRoot = "";
-
- /**
- * string replaces the archive root in stored xml file to allow the
- * changing of the attachment root.
- */
- private final String ARCHIVE_FOLDER_PLACEHOLDER = "%ARCHIVE_FOLDER%";
-
+ public MStorageProvider provider;
/**
* Get the isStoreArchiveOnFileSystem and archivePath for the client.
*
@@ -191,22 +149,8 @@ public class MArchive extends X_AD_Archive {
* @param trxName
*/
private void initArchiveStoreDetails(Properties ctx, String trxName) {
- final MClient client = new MClient(ctx, this.getAD_Client_ID(), trxName);
- isStoreArchiveOnFileSystem = client.isStoreArchiveOnFileSystem();
- if (isStoreArchiveOnFileSystem) {
- if (File.separatorChar == '\\') {
- m_archivePathRoot = client.getWindowsArchivePath();
- } else {
- m_archivePathRoot = client.getUnixArchivePath();
- }
- if ("".equals(m_archivePathRoot)) {
- log.severe("no archivePath defined");
- } else if (!m_archivePathRoot.endsWith(File.separator)) {
- log.warning("archive path doesn't end with " + File.separator);
- m_archivePathRoot = m_archivePathRoot + File.separator;
- log.fine(m_archivePathRoot);
- }
- }
+ MClientInfo clientInfo = MClientInfo.get(ctx);
+ provider=new MStorageProvider(ctx, clientInfo.getStorageArchive_ID(), trxName);
}
/**
@@ -217,151 +161,18 @@ public class MArchive extends X_AD_Archive {
public String toString() {
StringBuilder sb = new StringBuilder("MArchive[");
sb.append(get_ID()).append(",Name=").append(getName());
- if (m_inflated != null)
- sb.append(",Inflated=").append(m_inflated);
- if (m_deflated != null)
- sb.append(",Deflated=").append(m_deflated);
sb.append("]");
return sb.toString();
} // toString
public byte[] getBinaryData() {
- if (isStoreArchiveOnFileSystem) {
- return getBinaryDataFromFileSystem();
- }
- return getBinaryDataFromDB();
- }
-
- /**
- * @return attachment data
- */
- private byte[] getBinaryDataFromFileSystem() {
- if ("".equals(m_archivePathRoot)) {
- throw new IllegalArgumentException("no attachmentPath defined");
- }
- byte[] data = super.getBinaryData();
- m_deflated = null;
- m_inflated = null;
- if (data == null) {
- return null;
- }
-
- final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-
- try {
- final DocumentBuilder builder = factory.newDocumentBuilder();
- final Document document = builder.parse(new ByteArrayInputStream(data));
- final NodeList entries = document.getElementsByTagName("entry");
- if(entries.getLength()!=1){
- log.severe("no archive entry found");
- }
- final Node entryNode = entries.item(0);
- final NamedNodeMap attributes = entryNode.getAttributes();
- final Node fileNode = attributes.getNamedItem("file");
- if(fileNode==null ){
- log.severe("no filename for entry");
- return null;
- }
- String filePath = fileNode.getNodeValue();
- log.fine("filePath: " + filePath);
- if(filePath!=null){
- filePath = filePath.replaceFirst(ARCHIVE_FOLDER_PLACEHOLDER, m_archivePathRoot.replaceAll("\\\\","\\\\\\\\"));
- //just to be shure...
- String replaceSeparator = File.separator;
- if(!replaceSeparator.equals("/")){
- replaceSeparator = "\\\\";
- }
- filePath = filePath.replaceAll("/", replaceSeparator);
- filePath = filePath.replaceAll("\\\\", replaceSeparator);
- }
- log.fine("filePath: " + filePath);
- final File file = new File(filePath);
- if (file.exists()) {
- // read files into byte[]
- final byte[] dataEntry = new byte[(int) file.length()];
- try {
- final FileInputStream fileInputStream = new FileInputStream(file);
- fileInputStream.read(dataEntry);
- fileInputStream.close();
- } catch (FileNotFoundException e) {
- log.severe("File Not Found.");
- e.printStackTrace();
- } catch (IOException e1) {
- log.severe("Error Reading The File.");
- e1.printStackTrace();
- }
- return dataEntry;
- } else {
- log.severe("file not found: " + file.getAbsolutePath());
- return null;
- }
-
- } catch (SAXException sxe) {
- // Error generated during parsing)
- Exception x = sxe;
- if (sxe.getException() != null)
- x = sxe.getException();
- x.printStackTrace();
- log.severe(x.getMessage());
-
- } catch (ParserConfigurationException pce) {
- // Parser with specified options can't be built
- pce.printStackTrace();
- log.severe(pce.getMessage());
-
- } catch (IOException ioe) {
- // I/O error
- ioe.printStackTrace();
- log.severe(ioe.getMessage());
- }
+
+ IArchiveStore prov = provider.getArchiveStore();
+ if (prov != null)
+ return prov.loadLOBData(this,provider);
return null;
}
- /**
- * Get Binary Data. (inflate)
- *
- * @return inflated data
- */
- private byte[] getBinaryDataFromDB() {
- byte[] deflatedData = super.getBinaryData();
- m_deflated = null;
- m_inflated = null;
- if (deflatedData == null)
- return null;
- //
- log.fine("ZipSize=" + deflatedData.length);
- m_deflated = new Integer(deflatedData.length);
- if (deflatedData.length == 0)
- return null;
-
- byte[] inflatedData = null;
- try {
- ByteArrayInputStream in = new ByteArrayInputStream(deflatedData);
- ZipInputStream zip = new ZipInputStream(in);
- ZipEntry entry = zip.getNextEntry();
- if (entry != null) // just one entry
- {
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] buffer = new byte[2048];
- int length = zip.read(buffer);
- while (length != -1) {
- out.write(buffer, 0, length);
- length = zip.read(buffer);
- }
- //
- inflatedData = out.toByteArray();
- log.fine("Size=" + inflatedData.length + " - zip=" + entry.getCompressedSize()
- + "(" + entry.getSize() + ") "
- + (entry.getCompressedSize() * 100 / entry.getSize()) + "%");
- m_inflated = new Integer(inflatedData.length);
- }
- } catch (Exception e) {
- log.log(Level.SEVERE, "", e);
- inflatedData = null;
- }
- return inflatedData;
- } // getBinaryData
-
/**
* Get Data as Input Stream
*
@@ -381,127 +192,11 @@ public class MArchive extends X_AD_Archive {
* inflated data
*/
public void setBinaryData(byte[] inflatedData) {
- if (isStoreArchiveOnFileSystem) {
- saveBinaryDataIntoFileSystem(inflatedData);
- } else {
- saveBinaryDataIntoDB(inflatedData);
- }
+ IArchiveStore prov = provider.getArchiveStore();
+ if (prov != null)
+ prov.save(this,provider,inflatedData);
}
- /**
- * Save to file system. If the MArchive is not saved yet (id==0) it will
- * first save the MArchive object because it uses the id as filename.
- * @param inflatedData
- */
- private void saveBinaryDataIntoFileSystem(byte[] inflatedData) {
- if ("".equals(m_archivePathRoot)) {
- throw new IllegalArgumentException("no attachmentPath defined");
- }
- if (inflatedData == null || inflatedData.length == 0) {
- throw new IllegalArgumentException("InflatedData is NULL");
- }
- if(this.get_ID()==0){
- //set binary data otherwise save will fail
- super.setBinaryData(new byte[]{'0'});
- if(!this.save()) {
- throw new IllegalArgumentException("unable to save MArchive");
- }
- }
- final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- BufferedOutputStream out = null;
- try {
- // create destination folder
- StringBuilder msgfile = new StringBuilder().append(m_archivePathRoot).append(File.separator)
- .append(getArchivePathSnippet());
- final File destFolder = new File(msgfile.toString());
- if (!destFolder.exists()) {
- if (!destFolder.mkdirs()) {
- log.warning("unable to create folder: " + destFolder.getPath());
- }
- }
- // write to pdf
- msgfile = new StringBuilder().append(m_archivePathRoot).append(File.separator)
- .append(getArchivePathSnippet()).append(this.get_ID()).append(".pdf");
- final File destFile = new File(msgfile.toString());
-
- out = new BufferedOutputStream(new FileOutputStream(destFile));
- out.write(inflatedData);
- out.flush();
-
- //create xml entry
- final DocumentBuilder builder = factory.newDocumentBuilder();
- final Document document = builder.newDocument();
- final Element root = document.createElement("archive");
- document.appendChild(root);
- document.setXmlStandalone(true);
- final Element entry = document.createElement("entry");
- StringBuilder msgsat = new StringBuilder(ARCHIVE_FOLDER_PLACEHOLDER).append(getArchivePathSnippet()).append(this.get_ID()).append(".pdf");
- entry.setAttribute("file", msgsat.toString());
- root.appendChild(entry);
- final Source source = new DOMSource(document);
- final ByteArrayOutputStream bos = new ByteArrayOutputStream();
- final Result result = new StreamResult(bos);
- final Transformer xformer = TransformerFactory.newInstance().newTransformer();
- xformer.transform(source, result);
- final byte[] xmlData = bos.toByteArray();
- log.fine(bos.toString());
- //store xml in db
- super.setBinaryData(xmlData);
-
- } catch (Exception e) {
- log.log(Level.SEVERE, "saveLOBData", e);
- m_deflated = null;
- super.setBinaryData(null);
- } finally {
- if(out != null){
- try {
- out.close();
- } catch (Exception e) { }
- }
- }
-
- }
-
- /**
- * Save Binary Data to database.
- *
- * @param inflatedData
- * inflated data
- */
- private void saveBinaryDataIntoDB(byte[] inflatedData) {
- if (inflatedData == null || inflatedData.length == 0)
- throw new IllegalArgumentException("InflatedData is NULL");
- m_inflated = new Integer(inflatedData.length);
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ZipOutputStream zip = new ZipOutputStream(out);
- zip.setMethod(ZipOutputStream.DEFLATED);
- zip.setLevel(Deflater.BEST_COMPRESSION);
- zip.setComment("adempiere");
- //
- byte[] deflatedData = null;
- try {
- ZipEntry entry = new ZipEntry("AdempiereArchive");
- entry.setTime(System.currentTimeMillis());
- entry.setMethod(ZipEntry.DEFLATED);
- zip.putNextEntry(entry);
- zip.write(inflatedData, 0, inflatedData.length);
- zip.closeEntry();
- log.fine(entry.getCompressedSize() + " (" + entry.getSize() + ") "
- + (entry.getCompressedSize() * 100 / entry.getSize()) + "%");
- //
- // zip.finish();
- zip.close();
- deflatedData = out.toByteArray();
- log.fine("Length=" + inflatedData.length);
- m_deflated = new Integer(deflatedData.length);
- } catch (Exception e) {
- log.log(Level.SEVERE, "saveLOBData", e);
- deflatedData = null;
- m_deflated = null;
- }
- super.setBinaryData(deflatedData);
- } // setBinaryData
-
/**
* Get Created By (User) Name
*
@@ -540,7 +235,7 @@ public class MArchive extends X_AD_Archive {
*
* @return String
*/
- private String getArchivePathSnippet() {
+ public String getArchivePathSnippet() {
StringBuilder path = new StringBuilder().append(this.getAD_Client_ID()).append(File.separator).append(this.getAD_Org_ID())
.append(File.separator);
if (this.getAD_Process_ID() > 0) {
@@ -556,6 +251,14 @@ public class MArchive extends X_AD_Archive {
return path.toString();
}
+ public byte[] getByteData(){
+ return super.getBinaryData();
+ }
+
+ public void setByteData(byte[] BinaryData){
+ super.setBinaryData(BinaryData);
+ }
+
/**
* Before Save
*
diff --git a/org.adempiere.base/src/org/compiere/model/MAttachment.java b/org.adempiere.base/src/org/compiere/model/MAttachment.java
index 58dc840b1b..a404cb4b24 100644
--- a/org.adempiere.base/src/org/compiere/model/MAttachment.java
+++ b/org.adempiere.base/src/org/compiere/model/MAttachment.java
@@ -47,7 +47,7 @@ public class MAttachment extends X_AD_Attachment
/**
*
*/
- private static final long serialVersionUID = -4443388991706555942L;
+ private static final long serialVersionUID = -8013716602070647299L;
/**
* Get Attachment (if there are more than one attachment it gets the first in no specific order)
@@ -68,7 +68,7 @@ public class MAttachment extends X_AD_Attachment
/** Static Logger */
private static CLogger s_log = CLogger.getCLogger (MAttachment.class);
- public MStorageProvider provider;
+ private MStorageProvider provider;
/**************************************************************************
@@ -124,9 +124,6 @@ public class MAttachment extends X_AD_Attachment
/** List of Entry Data */
public ArrayList m_items = null;
- /** attachment (root) path - if file system is used */
- public String m_attachmentPathRoot = "";
-
/** string replaces the attachment root in stored xml file
* to allow the changing of the attachment root. */
public final String ATTACHMENT_FOLDER_PLACEHOLDER = "%ATTACHMENT_FOLDER%";
@@ -138,33 +135,8 @@ public class MAttachment extends X_AD_Attachment
*/
private void initAttachmentStoreDetails(Properties ctx, String trxName)
{
-
MClientInfo clientInfo = MClientInfo.get(ctx);
-
provider=new MStorageProvider(ctx, clientInfo.getAD_StorageProvider_ID(), trxName);
-
- m_attachmentPathRoot=provider.getFolder();
-
- if(m_attachmentPathRoot == null){
- log.severe("no attachmentPath defined");
- }
-
- /* final MClient client = new MClient(ctx, this.getAD_Client_ID(), trxName);
- isStoreAttachmentsOnFileSystem = client.isStoreAttachmentsOnFileSystem();
- if(isStoreAttachmentsOnFileSystem){
- if(File.separatorChar == '\\'){
- m_attachmentPathRoot = client.getWindowsAttachmentPath();
- } else {
- m_attachmentPathRoot = client.getUnixAttachmentPath();
- }
- if("".equals(m_attachmentPathRoot)){
- log.severe("no attachmentPath defined");
- } else if (!m_attachmentPathRoot.endsWith(File.separator)){
- log.warning("attachment path doesn't end with " + File.separator);
- m_attachmentPathRoot = m_attachmentPathRoot + File.separator;
- log.fine(m_attachmentPathRoot);
- }
- }*/
}
/**
diff --git a/org.adempiere.base/src/org/compiere/model/MInvoiceLine.java b/org.adempiere.base/src/org/compiere/model/MInvoiceLine.java
index 726245d2bb..2200e75a67 100644
--- a/org.adempiere.base/src/org/compiere/model/MInvoiceLine.java
+++ b/org.adempiere.base/src/org/compiere/model/MInvoiceLine.java
@@ -494,9 +494,9 @@ public class MInvoiceLine extends X_C_InvoiceLine
+ taxThisAmt + " Standard Tax Amt: " + taxStdAmt + " Line Net Amt: " + bd);
}
}
-
- if (bd.scale() > getPrecision())
- bd = bd.setScale(getPrecision(), BigDecimal.ROUND_HALF_UP);
+ int precision = getPrecision();
+ if (bd.scale() > precision)
+ bd = bd.setScale(precision, BigDecimal.ROUND_HALF_UP);
super.setLineNetAmt (bd);
} // setLineNetAmt
/**
diff --git a/org.adempiere.base/src/org/compiere/model/MOrderLine.java b/org.adempiere.base/src/org/compiere/model/MOrderLine.java
index ed492b9eba..334ea9b35a 100644
--- a/org.adempiere.base/src/org/compiere/model/MOrderLine.java
+++ b/org.adempiere.base/src/org/compiere/model/MOrderLine.java
@@ -404,9 +404,9 @@ public class MOrderLine extends X_C_OrderLine
}
}
-
- if (bd.scale() > getPrecision())
- bd = bd.setScale(getPrecision(), BigDecimal.ROUND_HALF_UP);
+ int precision = getPrecision();
+ if (bd.scale() > precision)
+ bd = bd.setScale(precision, BigDecimal.ROUND_HALF_UP);
super.setLineNetAmt (bd);
} // setLineNetAmt
diff --git a/org.adempiere.base/src/org/compiere/model/MPInstance.java b/org.adempiere.base/src/org/compiere/model/MPInstance.java
index 6e71a0514e..12f1414cc4 100644
--- a/org.adempiere.base/src/org/compiere/model/MPInstance.java
+++ b/org.adempiere.base/src/org/compiere/model/MPInstance.java
@@ -304,9 +304,9 @@ public class MPInstance extends X_AD_PInstance
int seconds = (int)(ms / 1000);
if (seconds < 1)
seconds = 1;
- MProcess prc = MProcess.get(getCtx(), getAD_Process_ID());
- prc.addStatistics(seconds);
- if (prc.get_ID() != 0 && prc.save())
+ String updsql = "UPDATE AD_Process SET Statistic_Count=Statistic_Count+1, Statistic_Seconds=Statistic_Seconds+? WHERE AD_Process_ID=?";
+ int no = DB.executeUpdate(updsql, new Object[] {seconds, getAD_Process_ID()}, true, null); // out of trx
+ if (no == 1)
log.fine("afterSave - Process Statistics updated Sec=" + seconds);
else
log.warning("afterSave - Process Statistics not updated");
diff --git a/org.adempiere.base/src/org/compiere/model/MProcess.java b/org.adempiere.base/src/org/compiere/model/MProcess.java
index 047f624b99..9307f37fdd 100644
--- a/org.adempiere.base/src/org/compiere/model/MProcess.java
+++ b/org.adempiere.base/src/org/compiere/model/MProcess.java
@@ -341,6 +341,7 @@ public class MProcess extends X_AD_Process
/**
* Update Statistics
* @param seconds sec
+ * @deprecated - use UPDATE instead
*/
public void addStatistics (int seconds)
{
diff --git a/org.adempiere.base/src/org/compiere/model/MSchedule.java b/org.adempiere.base/src/org/compiere/model/MSchedule.java
index 55675f7cdb..c4b8ceab3a 100644
--- a/org.adempiere.base/src/org/compiere/model/MSchedule.java
+++ b/org.adempiere.base/src/org/compiere/model/MSchedule.java
@@ -21,7 +21,9 @@ import it.sauronsoftware.cron4j.Predictor;
import it.sauronsoftware.cron4j.SchedulingPattern;
import java.net.InetAddress;
+import java.net.NetworkInterface;
import java.sql.ResultSet;
+import java.util.Enumeration;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.logging.Level;
@@ -31,6 +33,7 @@ import java.util.regex.PatternSyntaxException;
import org.compiere.util.CCache;
+
public class MSchedule extends X_AD_Schedule
{
/**
@@ -107,36 +110,38 @@ public class MSchedule extends X_AD_Schedule
* @param ipOnly
* @return true if IP is correct
*/
- private boolean checkIP(String ipOnly)
- {
- try
- {
- InetAddress box = InetAddress.getLocalHost();
- String ip = box.getHostAddress();
- if (chekIPFormat(ipOnly)) {
- if (ipOnly.indexOf(ip) == -1) {
-
- log.fine("Not allowed here - IP=" + ip + " does not match "+ ipOnly);
- return false;
+ private boolean checkIP(String ipOnly) {
+ try {
+ for (Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();)
+ {
+ NetworkInterface intf = en.nextElement();
+ for (Enumeration enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();)
+ {
+ InetAddress inetAddress = enumIpAddr.nextElement();
+ if ( !inetAddress.isLoopbackAddress()
+ && !inetAddress.isLinkLocalAddress()
+ && inetAddress.isSiteLocalAddress())
+ {
+ String retVal = inetAddress.getHostAddress().toString();
+ if (chekIPFormat(ipOnly)) {
+ retVal = inetAddress.getHostAddress().toString();
+ } else {
+ retVal = inetAddress.getHostName();
+ }
+ if (ipOnly.equals(retVal)) {
+ log.info("Allowed here - IP=" + retVal+ " match");
+ return true;
+ } else {
+ log.info("Not Allowed here - IP=" + retVal+ " does not match " + ipOnly);
+ }
+ }
}
- log.fine("Allowed here - IP=" + ip + " matches " + ipOnly);
}
- else{
- String hostname=box.getHostName();
- if(! ipOnly.equals(hostname)){
- log.fine("Not Allowed here -hostname " + hostname + " does not match "+ipOnly);
- return false;
- }
- log.fine("Allowed here - hostname=" + hostname + " matches " + ipOnly);
- }
- }
- catch (Exception e)
- {
+ } catch (Exception e) {
log.log(Level.SEVERE, "", e);
- return false;
}
- return true;
- } // checkIP
+ return false;
+ } // checkIP
public static MSchedule get(Properties ctx, int AD_Schedule_ID)
{
diff --git a/org.adempiere.base/src/org/compiere/model/MSequence.java b/org.adempiere.base/src/org/compiere/model/MSequence.java
index df0ae453ee..96da845401 100644
--- a/org.adempiere.base/src/org/compiere/model/MSequence.java
+++ b/org.adempiere.base/src/org/compiere/model/MSequence.java
@@ -1310,46 +1310,48 @@ public class MSequence extends X_AD_Sequence
return retValue;
}
+ private static String [] dontUseCentralized = new String[] {
+ "AD_ACCESSLOG",
+ "AD_ALERTPROCESSORLOG",
+ "AD_CHANGELOG",
+ "AD_ISSUE",
+ "AD_LDAPPROCESSORLOG",
+ "AD_PACKAGE_IMP",
+ "AD_PACKAGE_IMP_BACKUP",
+ "AD_PACKAGE_IMP_DETAIL",
+ "AD_PACKAGE_IMP_INST",
+ "AD_PACKAGE_IMP_PROC",
+ "AD_PINSTANCE",
+ "AD_PINSTANCE_LOG",
+ "AD_PINSTANCE_PARA",
+ "AD_RECENTITEM",
+ "AD_REPLICATION_LOG",
+ "AD_SCHEDULERLOG",
+ "AD_SESSION",
+ "AD_WORKFLOWPROCESSORLOG",
+ "CM_WEBACCESSLOG",
+ "C_ACCTPROCESSORLOG",
+ "K_INDEXLOG",
+ "R_REQUESTPROCESSORLOG",
+ "T_AGING",
+ "T_ALTER_COLUMN",
+ "T_DISTRIBUTIONRUNDETAIL",
+ "T_INVENTORYVALUE",
+ "T_INVOICEGL",
+ "T_REPLENISH",
+ "T_REPORT",
+ "T_REPORTSTATEMENT",
+ "T_SELECTION",
+ "T_SELECTION2",
+ "T_SPOOL",
+ "T_TRANSACTION",
+ "T_TRIALBALANCE"
+ };
+
private static boolean isExceptionCentralized(String tableName) {
- String [] exceptionTables = new String[] {
- "AD_ACCESSLOG",
- "AD_ALERTPROCESSORLOG",
- "AD_CHANGELOG",
- "AD_ISSUE",
- "AD_LDAPPROCESSORLOG",
- "AD_PACKAGE_IMP",
- "AD_PACKAGE_IMP_BACKUP",
- "AD_PACKAGE_IMP_DETAIL",
- "AD_PACKAGE_IMP_INST",
- "AD_PACKAGE_IMP_PROC",
- "AD_PINSTANCE",
- "AD_PINSTANCE_LOG",
- "AD_PINSTANCE_PARA",
- "AD_RECENTITEM",
- "AD_REPLICATION_LOG",
- "AD_SCHEDULERLOG",
- "AD_SESSION",
- "AD_WORKFLOWPROCESSORLOG",
- "CM_WEBACCESSLOG",
- "C_ACCTPROCESSORLOG",
- "K_INDEXLOG",
- "R_REQUESTPROCESSORLOG",
- "T_AGING",
- "T_ALTER_COLUMN",
- "T_DISTRIBUTIONRUNDETAIL",
- "T_INVENTORYVALUE",
- "T_INVOICEGL",
- "T_REPLENISH",
- "T_REPORT",
- "T_REPORTSTATEMENT",
- "T_SELECTION",
- "T_SELECTION2",
- "T_SPOOL",
- "T_TRANSACTION",
- "T_TRIALBALANCE"
- };
- for (int i = 0; i < exceptionTables.length; i++) {
- if (tableName.equalsIgnoreCase(exceptionTables[i]))
+
+ for (String exceptionTable : dontUseCentralized) {
+ if (tableName.equalsIgnoreCase(exceptionTable))
return true;
}
diff --git a/org.adempiere.base/src/org/compiere/model/MStorageOnHand.java b/org.adempiere.base/src/org/compiere/model/MStorageOnHand.java
index 2fae555823..5e7eacf69a 100644
--- a/org.adempiere.base/src/org/compiere/model/MStorageOnHand.java
+++ b/org.adempiere.base/src/org/compiere/model/MStorageOnHand.java
@@ -576,7 +576,7 @@ public class MStorageOnHand extends X_M_StorageOnHand
* @return
*/
public static BigDecimal getQtyOnHand(int M_Product_ID, int M_Warehouse_ID, int M_AttributeSetInstance_ID, String trxName) {
- StringBuffer sql = new StringBuffer();
+ StringBuilder sql = new StringBuilder();
sql.append(" SELECT SUM(QtyOnHand) FROM M_StorageOnHand oh JOIN M_Locator loc ON (oh.M_Locator_ID=loc.M_Locator_ID)")
.append(" WHERE oh.M_Product_ID=?")
.append(" AND loc.M_Warehouse_ID=?");
diff --git a/org.adempiere.base/src/org/compiere/model/MStorageProvider.java b/org.adempiere.base/src/org/compiere/model/MStorageProvider.java
index aaccf8160f..506c84757a 100644
--- a/org.adempiere.base/src/org/compiere/model/MStorageProvider.java
+++ b/org.adempiere.base/src/org/compiere/model/MStorageProvider.java
@@ -17,7 +17,6 @@
package org.compiere.model;
import java.sql.ResultSet;
-import java.util.List;
import java.util.Properties;
import org.adempiere.base.Service;
@@ -27,16 +26,14 @@ public class MStorageProvider extends X_AD_StorageProvider {
/**
*
*/
- private static final long serialVersionUID = -1317908636350952835L;
+ private static final long serialVersionUID = -5889682671195395536L;
- public MStorageProvider(Properties ctx, int AD_StorageProvider_ID,
- String trxName) {
+ public MStorageProvider(Properties ctx, int AD_StorageProvider_ID, String trxName) {
super(ctx, AD_StorageProvider_ID, trxName);
}
public MStorageProvider(Properties ctx, ResultSet rs, String trxName) {
super(ctx, rs, trxName);
-
}
public IAttachmentStore getAttachmentStore() {
@@ -45,19 +42,24 @@ public class MStorageProvider extends X_AD_StorageProvider {
if (method == null)
method = "DB";
query.put("method", method);
- List storelist = Service.locator().list(IAttachmentStore.class, query).getServices();
-
- IAttachmentStore store = null;
- if (storelist == null) {
- log.saveError("Error", "No storage provider found");
- } else {
- store = storelist.get(0);
+ IAttachmentStore store = Service.locator().locate(IAttachmentStore.class, query).getService();
+ if (store == null){
+ log.saveError("Error", "No attachment storage provider found");
+ }
+ return store;
+ }
+
+ public IArchiveStore getArchiveStore() {
+ ServiceQuery query=new ServiceQuery();
+ String method = this.getMethod();
+ if (method == null)
+ method = "DB";
+ query.put("method", method);
+ IArchiveStore store = Service.locator().locate(IArchiveStore.class, query).getService();
+ if (store == null){
+ log.saveError("Error", "No archive storage provider found");
}
return store;
}
}
-
-
-
-
diff --git a/org.adempiere.base/src/org/compiere/model/MStorageReservation.java b/org.adempiere.base/src/org/compiere/model/MStorageReservation.java
index ad6178caa8..318800303f 100644
--- a/org.adempiere.base/src/org/compiere/model/MStorageReservation.java
+++ b/org.adempiere.base/src/org/compiere/model/MStorageReservation.java
@@ -167,7 +167,7 @@ public class MStorageReservation extends X_M_StorageReservation {
*/
private static BigDecimal getQty(int M_Product_ID, int M_Warehouse_ID, int M_AttributeSetInstance_ID, boolean isSOTrx, String trxName) {
ArrayList