From c582c21810f2bf158c86abbb812c7a8994b74fd2 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Wed, 8 Nov 2017 18:29:30 +0100 Subject: [PATCH] IDEMPIERE-3551 1008086 - External (non-plugin) 2Pack automation --- .../201706221744_AutomaticExternalPackin.sql | 15 + .../201706221744_AutomaticExternalPackin.sql | 12 + .../src/org/compiere/model/MSysConfig.java | 40 +-- org.adempiere.pipo/META-INF/MANIFEST.MF | 5 +- .../pipo/srv/PipoDictionaryService.java | 6 +- .../plugin/utils/AbstractActivator.java | 2 +- .../plugin/utils/AdempiereActivator.java | 4 + .../utils/Incremental2PackActivator.java | 4 + .../utils/PackInApplicationActivator.java | 317 ++++++++++++++++++ .../plugin/utils/Version2PackActivator.java | 4 + 10 files changed, 386 insertions(+), 23 deletions(-) create mode 100644 migration/i5.1/oracle/201706221744_AutomaticExternalPackin.sql create mode 100644 migration/i5.1/postgresql/201706221744_AutomaticExternalPackin.sql create mode 100644 org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/PackInApplicationActivator.java diff --git a/migration/i5.1/oracle/201706221744_AutomaticExternalPackin.sql b/migration/i5.1/oracle/201706221744_AutomaticExternalPackin.sql new file mode 100644 index 0000000000..cee0cd7d07 --- /dev/null +++ b/migration/i5.1/oracle/201706221744_AutomaticExternalPackin.sql @@ -0,0 +1,15 @@ +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Jun 22, 2017 5:41:04 PM CEST +-- Automatic Packin +INSERT INTO AD_SysConfig (AD_SysConfig_ID,ConfigurationLevel,Updated,Value,Description,AD_SysConfig_UU,IsActive,Name,Created,AD_Org_ID,CreatedBy,UpdatedBy,AD_Client_ID,EntityType) VALUES (200101,'S',TO_DATE('2017-06-22 17:41:03','YYYY-MM-DD HH24:MI:SS'),'120','Delay in seconds to start applying the external automatic packin - see AUTOMATIC_PACKIN_FOLDERS','7db52ef2-ce9e-4989-b583-b64429fca5c8','Y','AUTOMATIC_PACKIN_INITIAL_DELAY',TO_DATE('2017-06-22 17:41:03','YYYY-MM-DD HH24:MI:SS'),0,100,100,0,'D') +; + +-- Jun 22, 2017 5:44:09 PM CEST +INSERT INTO AD_SysConfig (AD_SysConfig_ID,ConfigurationLevel,Updated,Value,Description,AD_SysConfig_UU,IsActive,Name,Created,AD_Org_ID,CreatedBy,UpdatedBy,AD_Client_ID,EntityType) VALUES (200102,'S',TO_DATE('2017-06-22 17:44:09','YYYY-MM-DD HH24:MI:SS'),' ','List of folders separated by semicolon (;) - allowed is .zip file or folder containing .zip files (recursive) - filename notation yyyymmddHHMM_ClientValue_InformationalDescription.zip','5468245a-0bb1-4357-b293-2ffb81c7cf2d','Y','AUTOMATIC_PACKIN_FOLDERS',TO_DATE('2017-06-22 17:44:09','YYYY-MM-DD HH24:MI:SS'),0,100,100,0,'D') +; + +SELECT register_migration_script('201706221744_AutomaticExternalPackin.sql') FROM dual +; + diff --git a/migration/i5.1/postgresql/201706221744_AutomaticExternalPackin.sql b/migration/i5.1/postgresql/201706221744_AutomaticExternalPackin.sql new file mode 100644 index 0000000000..783e5a8bbe --- /dev/null +++ b/migration/i5.1/postgresql/201706221744_AutomaticExternalPackin.sql @@ -0,0 +1,12 @@ +-- Jun 22, 2017 5:41:04 PM CEST +-- Automatic Packin +INSERT INTO AD_SysConfig (AD_SysConfig_ID,ConfigurationLevel,Updated,Value,Description,AD_SysConfig_UU,IsActive,Name,Created,AD_Org_ID,CreatedBy,UpdatedBy,AD_Client_ID,EntityType) VALUES (200101,'S',TO_TIMESTAMP('2017-06-22 17:41:03','YYYY-MM-DD HH24:MI:SS'),'120','Delay in seconds to start applying the external automatic packin - see AUTOMATIC_PACKIN_FOLDERS','7db52ef2-ce9e-4989-b583-b64429fca5c8','Y','AUTOMATIC_PACKIN_INITIAL_DELAY',TO_TIMESTAMP('2017-06-22 17:41:03','YYYY-MM-DD HH24:MI:SS'),0,100,100,0,'D') +; + +-- Jun 22, 2017 5:44:09 PM CEST +INSERT INTO AD_SysConfig (AD_SysConfig_ID,ConfigurationLevel,Updated,Value,Description,AD_SysConfig_UU,IsActive,Name,Created,AD_Org_ID,CreatedBy,UpdatedBy,AD_Client_ID,EntityType) VALUES (200102,'S',TO_TIMESTAMP('2017-06-22 17:44:09','YYYY-MM-DD HH24:MI:SS'),' ','List of folders separated by semicolon (;) - allowed is .zip file or folder containing .zip files (recursive) - filename notation yyyymmddHHMM_ClientValue_InformationalDescription.zip','5468245a-0bb1-4357-b293-2ffb81c7cf2d','Y','AUTOMATIC_PACKIN_FOLDERS',TO_TIMESTAMP('2017-06-22 17:44:09','YYYY-MM-DD HH24:MI:SS'),0,100,100,0,'D') +; + +SELECT register_migration_script('201706221744_AutomaticExternalPackin.sql') FROM dual +; + diff --git a/org.adempiere.base/src/org/compiere/model/MSysConfig.java b/org.adempiere.base/src/org/compiere/model/MSysConfig.java index bb5164bd9a..2d422365d7 100644 --- a/org.adempiere.base/src/org/compiere/model/MSysConfig.java +++ b/org.adempiere.base/src/org/compiere/model/MSysConfig.java @@ -39,10 +39,10 @@ import org.compiere.util.DisplayType; */ public class MSysConfig extends X_AD_SysConfig { - /** + /** * */ - private static final long serialVersionUID = -7805174199114873428L; + private static final long serialVersionUID = -4917976995339273240L; public static final String ADDRESS_VALIDATION = "ADDRESS_VALIDATION"; public static final String ALERT_SEND_ATTACHMENT_AS_XLS = "ALERT_SEND_ATTACHMENT_AS_XLS"; @@ -59,10 +59,12 @@ public class MSysConfig extends X_AD_SysConfig public static final String APPLICATION_MAIN_VERSION = "APPLICATION_MAIN_VERSION"; public static final String APPLICATION_MAIN_VERSION_SHOWN = "APPLICATION_MAIN_VERSION_SHOWN"; public static final String APPLICATION_OS_INFO_SHOWN = "APPLICATION_OS_INFO_SHOWN"; - public static final String AUTOMATIC_PACKIN_PROCESSING = "AUTOMATIC_PACKIN_PROCESSING"; - public static final String AUTOMATIC_PACKIN_TIMEOUT = "AUTOMATIC_PACKIN_TIMEOUT"; - public static final String AUTOMATIC_PACKIN_RETRIES = "AUTOMATIC_PACKIN_RETRIES"; - public static final String ATTACH_EMBEDDED_2PACK = "ATTACH_EMBEDDED_2PACK"; + public static final String ATTACH_EMBEDDED_2PACK = "ATTACH_EMBEDDED_2PACK"; + public static final String AUTOMATIC_PACKIN_FOLDERS = null; + public static final String AUTOMATIC_PACKIN_INITIAL_DELAY = null; + public static final String AUTOMATIC_PACKIN_PROCESSING = "AUTOMATIC_PACKIN_PROCESSING"; + public static final String AUTOMATIC_PACKIN_RETRIES = "AUTOMATIC_PACKIN_RETRIES"; + public static final String AUTOMATIC_PACKIN_TIMEOUT = "AUTOMATIC_PACKIN_TIMEOUT"; public static final String BACKGROUND_JOB_ALLOWED = "BACKGROUND_JOB_ALLOWED"; public static final String BACKGROUND_JOB_BY_DEFAULT = "BACKGROUND_JOB_BY_DEFAULT"; public static final String BACKGROUND_JOB_MAX_IN_SYSTEM = "BACKGROUND_JOB_MAX_IN_SYSTEM"; @@ -83,10 +85,10 @@ public class MSysConfig extends X_AD_SysConfig public static final String DOCACTIONBUTTON_SHOWACTIONNAME = "DOCACTIONBUTTON_SHOWACTIONNAME"; public static final String DPVIEWS_SHOWINFOACCOUNT = "DPViews_ShowInfoAccount"; public static final String DPVIEWS_SHOWINFOSCHEDULE = "DPViews_ShowInfoSchedule"; - public static final String EMAIL_NOTIFY_2PACK = "EMAIL_NOTIFY_2PACK"; - public static final String ENABLE_PAYMENTBOX_BUTTON = "ENABLE_PAYMENTBOX_BUTTON"; - public static final String GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS = "GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS"; - public static final String HTML_REPORT_THEME = "HTML_REPORT_THEME"; + public static final String EMAIL_NOTIFY_2PACK = "EMAIL_NOTIFY_2PACK"; + public static final String ENABLE_PAYMENTBOX_BUTTON = "ENABLE_PAYMENTBOX_BUTTON"; + public static final String GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS = "GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS"; + public static final String HTML_REPORT_THEME = "HTML_REPORT_THEME"; public static final String IBAN_VALIDATION = "IBAN_VALIDATION" ; public static final String IDENTIFIER_SEPARATOR = "IDENTIFIER_SEPARATOR" ; public static final String Invoice_ReverseUseNewNumber = "Invoice_ReverseUseNewNumber"; @@ -99,12 +101,12 @@ public class MSysConfig extends X_AD_SysConfig public static final String LOCATION_MAX_CITY_ROWS = "LOCATION_MAX_CITY_ROWS"; public static final String LOGIN_HELP_URL = "LOGIN_HELP_URL"; public static final String LOGIN_SHOW_RESETPASSWORD = "LOGIN_SHOW_RESETPASSWORD"; - public static final String MAIL_DONT_SEND_TO_ADDRESS = "MAIL_DONT_SEND_TO_ADDRESS"; + public static final String MAIL_DONT_SEND_TO_ADDRESS = "MAIL_DONT_SEND_TO_ADDRESS"; public static final String MAIL_SEND_BCC_TO_ADDRESS = "MAIL_SEND_BCC_TO_ADDRESS"; public static final String MAIL_SEND_BCC_TO_FROM = "MAIL_SEND_BCC_TO_FROM"; public static final String MAIL_SEND_CREDENTIALS = "MAIL_SEND_CREDENTIALS"; public static final String MAX_ACTIVITIES_IN_LIST = "MAX_ACTIVITIES_IN_LIST"; - public static final String MAX_RESULTS_PER_SEARCH_IN_DOCUMENT_CONTROLLER = "MAX_RESULTS_PER_SEARCH_IN_DOCUMENT_CONTROLLER"; + public static final String MAX_RESULTS_PER_SEARCH_IN_DOCUMENT_CONTROLLER = "MAX_RESULTS_PER_SEARCH_IN_DOCUMENT_CONTROLLER"; public static final String MAX_TEXT_LENGTH_ON_GRID_VIEW = "MAX_TEXT_LENGTH_ON_GRID_VIEW"; public static final String MENU_INFOUPDATER_SLEEP_MS = "MENU_INFOUPDATER_SLEEP_MS"; public static final String MFG_ValidateCostsDifferenceOnCreate = "MFG_ValidateCostsDifferenceOnCreate"; @@ -112,7 +114,7 @@ public class MSysConfig extends X_AD_SysConfig public static final String PAYMENT_OVERWRITE_DOCUMENTNO_WITH_CHECK_ON_PAYMENT = "PAYMENT_OVERWRITE_DOCUMENTNO_WITH_CHECK_ON_PAYMENT"; public static final String PAYMENT_OVERWRITE_DOCUMENTNO_WITH_CHECK_ON_RECEIPT = "PAYMENT_OVERWRITE_DOCUMENTNO_WITH_CHECK_ON_RECEIPT"; public static final String PAYMENT_OVERWRITE_DOCUMENTNO_WITH_CREDIT_CARD = "PAYMENT_OVERWRITE_DOCUMENTNO_WITH_CREDIT_CARD"; - public static final String PAYMENT_SELECTION_MANUAL_ASK_INVOKE_GENERATE = "PAYMENT_SELECTION_MANUAL_ASK_INVOKE_GENERATE"; + public static final String PAYMENT_SELECTION_MANUAL_ASK_INVOKE_GENERATE = "PAYMENT_SELECTION_MANUAL_ASK_INVOKE_GENERATE"; public static final String PDF_FONT_DIR = "PDF_FONT_DIR"; public static final String ProductUOMConversionRateValidate = "ProductUOMConversionRateValidate"; public static final String ProductUOMConversionUOMValidate = "ProductUOMConversionUOMValidate"; @@ -127,7 +129,7 @@ public class MSysConfig extends X_AD_SysConfig public static final String RecentItems_MaxShown = "RecentItems_MaxShown"; public static final String REPORT_SWAP_MAX_ROWS = "REPORT_SWAP_MAX_ROWS"; public static final String SHIPPING_DEFAULT_WEIGHT_PER_PACKAGE = "SHIPPING_DEFAULT_WEIGHT_PER_PACKAGE"; - public static final String STANDARD_REPORT_FOOTER_TRADEMARK_TEXT = "STANDARD_REPORT_FOOTER_TRADEMARK_TEXT"; + public static final String STANDARD_REPORT_FOOTER_TRADEMARK_TEXT = "STANDARD_REPORT_FOOTER_TRADEMARK_TEXT"; public static final String START_VALUE_BPLOCATION_NAME = "START_VALUE_BPLOCATION_NAME"; public static final String SWING_LOGIN_ALLOW_REMEMBER_ME = "SWING_LOGIN_ALLOW_REMEMBER_ME"; public static final String SWING_OVERRIDE_TEXT_AREA_BEHAVIOUR = "SWING_OVERRIDE_TEXT_AREA_BEHAVIOUR"; @@ -136,7 +138,7 @@ public class MSysConfig extends X_AD_SysConfig public static final String SYSTEM_IN_MAINTENANCE_MODE = "SYSTEM_IN_MAINTENANCE_MODE"; public static final String SYSTEM_INSERT_CHANGELOG = "SYSTEM_INSERT_CHANGELOG"; public static final String SYSTEM_NATIVE_SEQUENCE = "SYSTEM_NATIVE_SEQUENCE"; - public static final String TRACE_ALL_TRX_CONNECTION_GET = "TRACE_ALL_TRX_CONNECTION_GET"; + public static final String TRACE_ALL_TRX_CONNECTION_GET = "TRACE_ALL_TRX_CONNECTION_GET"; public static final String TWOPACK_COMMIT_DDL = "2PACK_COMMIT_DDL"; public static final String TWOPACK_HANDLE_TRANSLATIONS = "2PACK_HANDLE_TRANSLATIONS"; public static final String USE_EMAIL_FOR_LOGIN = "USE_EMAIL_FOR_LOGIN"; @@ -151,10 +153,10 @@ public class MSysConfig extends X_AD_SysConfig public static final String ZK_BROWSER_TITLE = "ZK_BROWSER_TITLE"; public static final String ZK_BUTTON_STYLE = "ZK_BUTTON_STYLE"; public static final String ZK_DASHBOARD_CALENDAR_REQUEST_DISPLAY_MODE = "ZK_DASHBOARD_CALENDAR_REQUEST_DISPLAY_MODE"; - public static final String ZK_DASHBOARD_PERFORMANCE_TIMEOUT = "ZK_DASHBOARD_PERFORMANCE_TIMEOUT"; - public static final String ZK_DASHBOARD_PERFORMANCE_REFRESH_INTERVAL = "ZK_DASHBOARD_PERFORMANCE_REFRESH_INTERVAL"; + public static final String ZK_DASHBOARD_PERFORMANCE_REFRESH_INTERVAL = "ZK_DASHBOARD_PERFORMANCE_REFRESH_INTERVAL"; + public static final String ZK_DASHBOARD_PERFORMANCE_TIMEOUT = "ZK_DASHBOARD_PERFORMANCE_TIMEOUT"; public static final String ZK_DASHBOARD_REFRESH_INTERVAL = "ZK_DASHBOARD_REFRESH_INTERVAL"; - public static final String ZK_DECIMALBOX_PROCESS_DOTKEYPAD = "ZK_DECIMALBOX_PROCESS_DOTKEYPAD"; + public static final String ZK_DECIMALBOX_PROCESS_DOTKEYPAD = "ZK_DECIMALBOX_PROCESS_DOTKEYPAD"; public static final String ZK_DESKTOP_CLASS = "ZK_DESKTOP_CLASS"; public static final String ZK_FOOTER_SERVER_DATETIME_FORMAT = "ZK_FOOTER_SERVER_DATETIME_FORMAT"; public static final String ZK_FOOTER_SERVER_MSG = "ZK_FOOTER_SERVER_MSG"; @@ -175,7 +177,7 @@ public class MSysConfig extends X_AD_SysConfig public static final String ZK_REPORT_TABLE_OUTPUT_TYPE = "ZK_REPORT_TABLE_OUTPUT_TYPE"; public static final String ZK_ROOT_FOLDER_BROWSER = "ZK_ROOT_FOLDER_BROWSER"; public static final String ZK_SEQ_DEFAULT_VALUE_PANEL = "ZK_SEQ_DEFAULT_VALUE_PANEL"; - public static final String ZK_SESSION_TIMEOUT_IN_SECONDS = "ZK_SESSION_TIMEOUT_IN_SECONDS"; + public static final String ZK_SESSION_TIMEOUT_IN_SECONDS = "ZK_SESSION_TIMEOUT_IN_SECONDS"; public static final String ZK_THEME = "ZK_THEME"; /** diff --git a/org.adempiere.pipo/META-INF/MANIFEST.MF b/org.adempiere.pipo/META-INF/MANIFEST.MF index 197a5442f2..028a8a29c9 100644 --- a/org.adempiere.pipo/META-INF/MANIFEST.MF +++ b/org.adempiere.pipo/META-INF/MANIFEST.MF @@ -13,6 +13,7 @@ Import-Package: org.apache.commons.codec, Export-Package: org.adempiere.pipo.srv, org.adempiere.pipo2, org.adempiere.pipo2.exception -Require-Bundle: org.adempiere.base;bundle-version="0.0.0" +Require-Bundle: org.adempiere.base;bundle-version="0.0.0", + org.adempiere.plugin.utils;bundle-version="0.0.0" Service-Component: OSGI-INF/dictionaryservice.xml -Bundle-ActivationPolicy: lazy +Bundle-Activator: org.adempiere.plugin.utils.PackInApplicationActivator diff --git a/org.adempiere.pipo/src/org/adempiere/pipo/srv/PipoDictionaryService.java b/org.adempiere.pipo/src/org/adempiere/pipo/srv/PipoDictionaryService.java index 6d443c0fd8..0b6c727b1d 100644 --- a/org.adempiere.pipo/src/org/adempiere/pipo/srv/PipoDictionaryService.java +++ b/org.adempiere.pipo/src/org/adempiere/pipo/srv/PipoDictionaryService.java @@ -47,7 +47,11 @@ public class PipoDictionaryService implements IDictionaryService { trxName = Trx.createTrxName("PipoDS"); Trx.get(trxName, true).setDisplayName(getClass().getName()+"_merge"); packIn = new PackIn(); - packIn.setPackageName(context.getBundle().getSymbolicName()); + //external files must not start with "2Pack" prefix in order to work correctly + if ("org.adempiere.pipo".equals(context.getBundle().getSymbolicName()) && !packageFile.getName().startsWith("2Pack")) + packIn.setPackageName(packageFile.getName()); + else + packIn.setPackageName(context.getBundle().getSymbolicName()); if (Env.getCtx().getProperty("#AD_Client_ID") == null) { Env.getCtx().put("#AD_Client_ID", 0); diff --git a/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/AbstractActivator.java b/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/AbstractActivator.java index 354e3b9db2..f119aecaa7 100644 --- a/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/AbstractActivator.java +++ b/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/AbstractActivator.java @@ -64,7 +64,7 @@ public abstract class AbstractActivator implements BundleActivator, ServiceTrack Query q = new Query(Env.getCtx(), X_AD_Package_Imp.Table_Name, where.toString(), null); q.setParameters(params); - return q.first() != null; + return q.match(); } public abstract String getName(); diff --git a/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/AdempiereActivator.java b/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/AdempiereActivator.java index ec5e72da24..0c366700ed 100644 --- a/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/AdempiereActivator.java +++ b/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/AdempiereActivator.java @@ -10,6 +10,7 @@ import java.util.logging.Level; import org.adempiere.base.IDictionaryService; import org.adempiere.util.ServerContext; import org.compiere.Adempiere; +import org.compiere.model.MSession; import org.compiere.model.Query; import org.compiere.model.ServerStateChangeEvent; import org.compiere.model.ServerStateChangeListener; @@ -104,6 +105,8 @@ public class AdempiereActivator extends AbstractActivator { protected void packIn() { URL packout = context.getBundle().getEntry("/META-INF/2Pack.zip"); if (packout != null && service != null) { + //Create Session to be able to create records in AD_ChangeLog + MSession.get(Env.getCtx(), true); FileOutputStream zipstream = null; try { // copy the resource to a temporary file to process it with 2pack @@ -211,6 +214,7 @@ public class AdempiereActivator extends AbstractActivator { protected void setupPackInContext() { Properties serverContext = new Properties(); + serverContext.setProperty("#AD_Client_ID", "0"); ServerContext.setCurrentInstance(serverContext); }; } diff --git a/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/Incremental2PackActivator.java b/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/Incremental2PackActivator.java index fabb12367c..ea6197482f 100644 --- a/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/Incremental2PackActivator.java +++ b/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/Incremental2PackActivator.java @@ -28,6 +28,7 @@ import java.util.logging.Level; import org.adempiere.base.IDictionaryService; import org.adempiere.util.ServerContext; import org.compiere.Adempiere; +import org.compiere.model.MSession; import org.compiere.model.Query; import org.compiere.model.ServerStateChangeEvent; import org.compiere.model.ServerStateChangeListener; @@ -215,6 +216,8 @@ public class Incremental2PackActivator extends AbstractActivator { protected boolean packIn(URL packout) { if (packout != null && service != null) { + //Create Session to be able to create records in AD_ChangeLog + MSession.get(Env.getCtx(), true); String path = packout.getPath(); String suffix = "_"+path.substring(path.lastIndexOf("2Pack_")); System.out.println("Installing " + getName() + " " + path + " ..."); @@ -334,6 +337,7 @@ public class Incremental2PackActivator extends AbstractActivator { protected void setupPackInContext() { Properties serverContext = new Properties(); + serverContext.setProperty("#AD_Client_ID", "0"); ServerContext.setCurrentInstance(serverContext); }; } diff --git a/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/PackInApplicationActivator.java b/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/PackInApplicationActivator.java new file mode 100644 index 0000000000..5a3020485d --- /dev/null +++ b/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/PackInApplicationActivator.java @@ -0,0 +1,317 @@ +/****************************************************************************** + * Copyright (C) 2017 Diego Ruiz * + * Copyright (C) 2017 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.adempiere.plugin.utils; + +import java.io.File; +import java.io.FileFilter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import java.util.Timer; +import java.util.TimerTask; +import java.util.logging.Level; + +import org.adempiere.base.IDictionaryService; +import org.adempiere.util.ServerContext; +import org.compiere.Adempiere; +import org.compiere.model.MClient; +import org.compiere.model.MSession; +import org.compiere.model.MSysConfig; +import org.compiere.model.Query; +import org.compiere.model.ServerStateChangeEvent; +import org.compiere.model.ServerStateChangeListener; +import org.compiere.util.AdempiereSystemError; +import org.compiere.util.CLogger; +import org.compiere.util.Env; +import org.compiere.util.Util; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.util.tracker.ServiceTracker; + +public class PackInApplicationActivator extends AbstractActivator { + + protected final static CLogger logger = CLogger.getCLogger(PackInApplicationActivator.class.getName()); + private List filesToProcess = new ArrayList<>(); + private File currentFile; + + @Override + public void start(BundleContext context) throws Exception { + this.context = context; + if (logger.isLoggable(Level.INFO)) logger.info(getName() + " starting..."); + serviceTracker = new ServiceTracker(context, IDictionaryService.class.getName(), this); + serviceTracker.open(); + start(); + if (logger.isLoggable(Level.INFO)) + logger.info(getName() + " ready."); + } + + /** + * call when bundle have been started ( after this.context have been set ) + */ + protected void start() { + }; + + /** + * call when bundle is stop ( before this.context is set to null ) + */ + protected void stop() { + } + + @Override + public void stop(BundleContext context) throws Exception { + stop(); + serviceTracker.close(); + this.context = null; + if (logger.isLoggable(Level.INFO)) logger.info(context.getBundle().getSymbolicName() + " " + + context.getBundle().getHeaders().get("Bundle-Version") + + " stopped."); + } + + @Override + public IDictionaryService addingService(ServiceReference reference) { + service = context.getService(reference); + if (Adempiere.getThreadPoolExecutor() != null) { + Adempiere.getThreadPoolExecutor().execute(new Runnable() { + @Override + public void run() { + automaticPackin(); + } + }); + } else { + Adempiere.addServerStateChangeListener(new ServerStateChangeListener() { + @Override + public void stateChange(ServerStateChangeEvent event) { + if (event.getEventType() == ServerStateChangeEvent.SERVER_START && service != null) { + automaticPackin(); + } + } + }); + } + return null; + } + + private void automaticPackin() { + //Initial delay + Timer t = new Timer(); + t.schedule(new TimerTask() { + @Override + public void run() { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(PackInApplicationActivator.class.getClassLoader()); + setupPackInContext(); + installPackages(); + } finally { + ServerContext.dispose(); + service = null; + Thread.currentThread().setContextClassLoader(cl); + } + t.cancel(); + } + }, MSysConfig.getIntValue(MSysConfig.AUTOMATIC_PACKIN_INITIAL_DELAY, 120) * 1000); + } + + private void installPackages() { + + String folders = MSysConfig.getValue(MSysConfig.AUTOMATIC_PACKIN_FOLDERS); + + if (Util.isEmpty(folders, true)) { + logger.log(Level.INFO, "Not specified folders for automatic packin"); + return; + } + + File[] fileArray = getFilesToProcess(folders); + + if (fileArray.length <= 0) { + System.out.println("No zip files to process"); + return; + } + + try { + if (getDBLock()) { + //Create Session to be able to create records in AD_ChangeLog + MSession.get(Env.getCtx(), true); + for(File zipFile : fileArray) { + currentFile = zipFile; + if (!packIn(zipFile)) { + // stop processing further packages if one fail + break; + } + filesToProcess.remove(zipFile); + } + releaseLock(); + } else { + logger.log(Level.SEVERE, "Could not acquire the DB lock to automatically install the packins"); + } + } catch (AdempiereSystemError e) { + e.printStackTrace(); + } + + if (filesToProcess.size() > 0) { + System.out.println("The following packages were not applied: "); + for (File file : filesToProcess) { + System.out.println(file.getName()); + } + } + } + + private boolean packIn(File packinFile) { + if (packinFile != null && service != null) { + String fileName = packinFile.getName(); + System.out.println("Installing " + fileName + " ..."); + + // The convention for package names is: yyyymmddHHMM_ClientValue_InformationalDescription.zip + String [] parts = fileName.split("_"); + String clientValue = parts[1]; + + MClient client = getClient(clientValue); + if (client == null) { + logger.log(Level.SEVERE, "Client does not exist: " + clientValue); + return false; + } + + Env.setContext(Env.getCtx(), "#AD_Client_ID", client.getAD_Client_ID()); + + try { + // call 2pack + if (!merge(packinFile, null)) + return false; + } catch (Throwable e) { + logger.log(Level.SEVERE, "Pack in failed.", e); + return false; + } + System.out.println(packinFile.getPath() + " installed"); + } + + return true; + } + + private File[] getFilesToProcess(String folders) { + String filePaths[] = null; + if (folders.indexOf(";") > 0) { + filePaths = folders.split("[;]"); + } else { + filePaths = new String[]{folders}; + } + + //Add files to the array + for (String filePath : filePaths) { + File toProcess = new File(filePath.trim()); + if (!toProcess.exists()) { + logger.log(Level.SEVERE, filePath + " does not exist"); + continue; + } + + processFilePath(toProcess); + } + + //Verify installed packages and remove those that were installed previously + verifyInstalledPackages(); + + File[] fileArray = filesToProcess.toArray(new File[filesToProcess.size()]); + // Sort files by name + Arrays.sort(fileArray, new Comparator() { + @Override + public int compare(File f1, File f2) { + return f1.getName().compareTo(f2.getName()); + } + }); + + return fileArray; + } + + private void processFilePath(File toProcess) { + if (toProcess.isFile()) { + if (toProcess.getName().toLowerCase().endsWith(".zip")) + filesToProcess.add(toProcess); + else { + logger.log(Level.SEVERE, toProcess.getName() + " is not a valid .zip file"); + return; + } + } else if (toProcess.isDirectory()) { + FileFilter filter = new FileFilter() { + public boolean accept(File file) { + if (file.getName().toUpperCase().endsWith(".ZIP") || file.isDirectory()) + return true; + else + return false; + } + }; + boolean found = false; + for (File fileToProcess : toProcess.listFiles(filter)) { + if (!found) { + System.out.println("*** Creating list from folder " + toProcess.toString()); + found = true; + } + if (fileToProcess.isDirectory()) + processFilePath(fileToProcess); + else + filesToProcess.add(fileToProcess); + } + if (!found) { + logger.log(Level.SEVERE, toProcess.getName() + " does not have .zip files or subfolders"); + return; + } + } else { + logger.log(Level.SEVERE, toProcess.getName() + " not a file or folder"); + } + } + + private void verifyInstalledPackages() { + Iterator iterator = filesToProcess.iterator(); + while(iterator.hasNext()){ + currentFile = iterator.next(); + if (installedPackage(null)) { + logger.log(Level.INFO, currentFile.getName() + " already installed. Removing it from the list..."); + iterator.remove(); + } + } + } + + private MClient getClient(String clientValue) { + String where = "upper(Value) = upper(?)"; + Query q = new Query(Env.getCtx(), MClient.Table_Name, + where, null) + .setParameters(new Object[] {clientValue}) + .setOnlyActiveRecords(true); + + return q.first(); + } + + @Override + public void modifiedService(ServiceReference reference, IDictionaryService service) { + } + + @Override + public void removedService(ServiceReference reference, IDictionaryService service) { + } + + @Override + public String getName() { + if (currentFile != null) + return currentFile.getName(); + else + return ""; + } + + protected void setupPackInContext() { + Properties serverContext = new Properties(); + serverContext.setProperty("#AD_Client_ID", "0"); + ServerContext.setCurrentInstance(serverContext); + }; + +} diff --git a/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/Version2PackActivator.java b/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/Version2PackActivator.java index ac6dba55b8..b4d0162d64 100644 --- a/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/Version2PackActivator.java +++ b/org.adempiere.plugin.utils/src/org/adempiere/plugin/utils/Version2PackActivator.java @@ -28,6 +28,7 @@ import java.util.logging.Level; import org.adempiere.base.IDictionaryService; import org.adempiere.util.ServerContext; import org.compiere.Adempiere; +import org.compiere.model.MSession; import org.compiere.model.Query; import org.compiere.model.ServerStateChangeEvent; import org.compiere.model.ServerStateChangeListener; @@ -160,6 +161,8 @@ public class Version2PackActivator extends AbstractActivator { try { if (getDBLock()) { + //Create Session to be able to create records in AD_ChangeLog + MSession.get(Env.getCtx(), true); for(TwoPackEntry entry : list) { if (!packIn(entry.url)) { // stop processing further packages if one fail @@ -304,6 +307,7 @@ public class Version2PackActivator extends AbstractActivator { protected void setupPackInContext() { Properties serverContext = new Properties(); + serverContext.setProperty("#AD_Client_ID", "0"); ServerContext.setCurrentInstance(serverContext); }; }