diff --git a/org.adempiere.base/META-INF/MANIFEST.MF b/org.adempiere.base/META-INF/MANIFEST.MF
index 63c5db283d..04737eb512 100644
--- a/org.adempiere.base/META-INF/MANIFEST.MF
+++ b/org.adempiere.base/META-INF/MANIFEST.MF
@@ -279,7 +279,9 @@ Import-Package: com.sun.mail.auth;version="1.4.5",
org.eclipse.osgi.framework.console;version="1.1.0",
org.eclipse.osgi.service.datalocation,
org.osgi.framework,
+ org.osgi.service.component;version="1.1.0",
org.osgi.service.event;version="1.2.0",
+ org.osgi.util.tracker;version="1.5.0",
org.restlet,
org.restlet.data,
org.restlet.representation,
@@ -287,6 +289,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
+Service-Component: OSGI-INF/eventmanager.xml, OSGI-INF/dslocator.xml, OSGI-INF/extensionlocator.xml, OSGI-INF/serverbean.xml, OSGI-INF/statusbean.xml
Bundle-ActivationPolicy: lazy
Require-Bundle: org.eclipse.equinox.app;bundle-version="1.3.1"
diff --git a/org.adempiere.base/OSGI-INF/dslocator.xml b/org.adempiere.base/OSGI-INF/dslocator.xml
new file mode 100644
index 0000000000..c318b703fb
--- /dev/null
+++ b/org.adempiere.base/OSGI-INF/dslocator.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/org.adempiere.base/OSGI-INF/extensionlocator.xml b/org.adempiere.base/OSGI-INF/extensionlocator.xml
new file mode 100644
index 0000000000..4134d186fd
--- /dev/null
+++ b/org.adempiere.base/OSGI-INF/extensionlocator.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/org.adempiere.base/OSGI-INF/serverbean.xml b/org.adempiere.base/OSGI-INF/serverbean.xml
new file mode 100644
index 0000000000..201af98d9b
--- /dev/null
+++ b/org.adempiere.base/OSGI-INF/serverbean.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/org.adempiere.base/OSGI-INF/statusbean.xml b/org.adempiere.base/OSGI-INF/statusbean.xml
new file mode 100644
index 0000000000..5528079e58
--- /dev/null
+++ b/org.adempiere.base/OSGI-INF/statusbean.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/org.adempiere.base/build.properties b/org.adempiere.base/build.properties
index b6a4bb78c8..35345f99c3 100644
--- a/org.adempiere.base/build.properties
+++ b/org.adempiere.base/build.properties
@@ -16,7 +16,11 @@ bin.includes = META-INF/,\
groovy-all-1.7.5.jar,\
vt-dictionary-3.0.jar,\
vt-password-3.1.1.jar,\
- super-csv-2.0.0-beta-1.jar
+ super-csv-2.0.0-beta-1.jar,\
+ OSGI-INF/dslocator.xml,\
+ OSGI-INF/extensionlocator.xml,\
+ OSGI-INF/serverbean.xml,\
+ OSGI-INF/statusbean.xml
output.base.jar = build/
-source.base.jar = src/
src.includes = schema/
+source.base.jar = src/
diff --git a/org.adempiere.base/src/org/adempiere/base/BaseActivator.java b/org.adempiere.base/src/org/adempiere/base/BaseActivator.java
index 12f9897050..0096e386f9 100644
--- a/org.adempiere.base/src/org/adempiere/base/BaseActivator.java
+++ b/org.adempiere.base/src/org/adempiere/base/BaseActivator.java
@@ -23,6 +23,8 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Properties;
import org.adempiere.base.equinox.StackTraceCommand;
@@ -30,6 +32,8 @@ import org.compiere.Adempiere;
import org.eclipse.osgi.framework.console.CommandProvider;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.util.tracker.ServiceTracker;
/**
* @author hengsin
@@ -102,10 +106,55 @@ public class BaseActivator implements BundleActivator {
@Override
public void stop(BundleContext context) throws Exception {
bundleContext = null;
+ for(Map> cacheMap : trackerCache.values()) {
+ for(ServiceTracker,?> cacheTracker : cacheMap.values()) {
+ if (cacheTracker.getTrackingCount() != -1) {
+ cacheTracker.close();
+ }
+ }
+ }
+ trackerCache.clear();
Adempiere.stop();
}
+ /**
+ * @return bundle context
+ */
public static BundleContext getBundleContext() {
return bundleContext;
}
+
+ private static Map>> trackerCache = new HashMap>>();
+
+ @SuppressWarnings("unchecked")
+ /**
+ * @param type
+ * @param filter
+ * @return service tracker
+ */
+ public static ServiceTracker getServiceTracker(Class type, Filter filter) {
+ ServiceTracker tracker = null;
+ String className = type.getName();
+ Map> cacheMap = null;
+ synchronized (trackerCache) {
+ cacheMap = trackerCache.get(className);
+ if (cacheMap == null) {
+ cacheMap = new HashMap>();
+ trackerCache.put(className, cacheMap);
+ }
+ }
+
+ String filterKey = filter.toString();
+ synchronized (cacheMap) {
+ ServiceTracker, ?> cacheTracker = cacheMap.get(filterKey);
+ if (cacheTracker == null) {
+ tracker = new ServiceTracker(bundleContext, filter, null);
+ cacheMap.put(filterKey, tracker);
+ } else {
+ tracker = (ServiceTracker) cacheTracker;
+ }
+ }
+
+ return tracker;
+ }
}
diff --git a/org.adempiere.base/src/org/adempiere/base/Core.java b/org.adempiere.base/src/org/adempiere/base/Core.java
index cba5b182c9..b40e2c3a3f 100644
--- a/org.adempiere.base/src/org/adempiere/base/Core.java
+++ b/org.adempiere.base/src/org/adempiere/base/Core.java
@@ -49,7 +49,7 @@ public class Core {
return new IResourceFinder() {
public URL getResource(String name) {
- List f = Service.list(IResourceFinder.class);
+ List f = Service.locator().list(IResourceFinder.class).getServices();
for (IResourceFinder finder : f) {
URL url = finder.getResource(name);
if (url!=null)
@@ -71,39 +71,37 @@ public class Core {
query.put("tableName", tableName);
query.put("columnName", columnName);
- return Service.list(IColumnCallout.class, query);
+ return Service.locator().list(IColumnCallout.class, query).getServices();
}
/**
*
- * @param extensionId
- * @return ProcessCall instance or null if extensionId not found
+ * @param serviceId
+ * @return ProcessCall instance or null if serviceId not found
*/
- public static ProcessCall getProcess(String extensionId) {
- ServiceQuery query = new ServiceQuery();
- query.put(ServiceQuery.EXTENSION_ID, extensionId);
- return Service.locate(ProcessCall.class, "org.adempiere.base.Process", query);
+ public static ProcessCall getProcess(String serviceId) {
+ return Service.locator().locate(ProcessCall.class, "org.adempiere.base.Process", serviceId, null).getService();
}
/**
*
- * @param extensionId
- * @return ModelValidator instance of null if extensionId not found
+ * @param serviceId
+ * @return ModelValidator instance of null if serviceId not found
*/
- public static ModelValidator getModelValidator(String extensionId) {
- ServiceQuery query = new ServiceQuery();
- query.put(ServiceQuery.EXTENSION_ID, extensionId);
- return Service.locate(ModelValidator.class, "org.adempiere.base.ModelValidator", query);
+ public static ModelValidator getModelValidator(String serviceId) {
+ return Service.locator().locate(ModelValidator.class, "org.adempiere.base.ModelValidator", serviceId, null).getService();
}
/**
- * Factory
+ * Get payment processor instance
* @param mpp payment processor model
* @param mp payment model
* @return initialized PaymentProcessor or null
*/
public static PaymentProcessor getPaymentProcessor(MPaymentProcessor mpp, PaymentInterface mp) {
- s_log.info("create for " + mpp);
+ if (s_log.isLoggable(Level.FINE))
+ s_log.fine("create for " + mpp);
+
String className = mpp.getPayProcessorClass();
if (className == null || className.length() == 0) {
s_log.log(Level.SEVERE, "No PaymentProcessor class name in " + mpp);
@@ -111,10 +109,9 @@ public class Core {
}
//
PaymentProcessor myProcessor = null;
- ServiceQuery query = new ServiceQuery();
- query.put(ServiceQuery.EXTENSION_ID, className);
- myProcessor = Service.locate(PaymentProcessor.class, query);
+ myProcessor = Service.locator().locate(PaymentProcessor.class, className, null).getService();
if (myProcessor == null) {
+ //fall back to dynamic java class loadup
try {
Class> ppClass = Class.forName(className);
if (ppClass != null)
@@ -128,7 +125,7 @@ public class Core {
}
}
if (myProcessor == null) {
- s_log.log(Level.SEVERE, "Not found in extension registry and classpath");
+ s_log.log(Level.SEVERE, "Not found in service/extension registry and classpath");
return null;
}
diff --git a/org.adempiere.base/src/org/adempiere/base/DelegatingServiceHolder.java b/org.adempiere.base/src/org/adempiere/base/DelegatingServiceHolder.java
new file mode 100644
index 0000000000..7f085ea393
--- /dev/null
+++ b/org.adempiere.base/src/org/adempiere/base/DelegatingServiceHolder.java
@@ -0,0 +1,64 @@
+/******************************************************************************
+ * Copyright (C) 2012 Heng Sin Low *
+ * 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.adempiere.base;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author hengsin
+ *
+ */
+public class DelegatingServiceHolder implements IServiceHolder,
+ IServicesHolder {
+
+ private List> serviceHolder = new ArrayList>();
+ private List> servicesHolder = new ArrayList>();
+
+ /**
+ *
+ */
+ public DelegatingServiceHolder() {
+ }
+
+ public void addServiceHolder(IServiceHolder holder) {
+ serviceHolder.add(holder);
+ }
+
+ public void addServicesHolder(IServicesHolder holder) {
+ servicesHolder.add(holder);
+ }
+
+ @Override
+ public List getServices() {
+ List list = new ArrayList();
+ for(IServicesHolder holder : servicesHolder) {
+ List t = holder.getServices();
+ if (t != null && !t.isEmpty())
+ list.addAll(t);
+ }
+ return list;
+ }
+
+ @Override
+ public T getService() {
+ T t = null;
+ for(IServiceHolder holder : serviceHolder) {
+ t = holder.getService();
+ if (t != null) break;
+ }
+ return t;
+ }
+
+}
diff --git a/org.adempiere.base/src/org/adempiere/base/DelegatingServiceLocator.java b/org.adempiere.base/src/org/adempiere/base/DelegatingServiceLocator.java
new file mode 100644
index 0000000000..8375376036
--- /dev/null
+++ b/org.adempiere.base/src/org/adempiere/base/DelegatingServiceLocator.java
@@ -0,0 +1,181 @@
+/******************************************************************************
+ * Copyright (C) 2012 Heng Sin Low *
+ * 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.adempiere.base;
+
+import java.util.List;
+
+import org.adempiere.base.ds.DynamicServiceLocator;
+
+/**
+ * Delegate to available service locator
+ * @author hengsin
+ *
+ */
+public class DelegatingServiceLocator implements IServiceLocator {
+
+ private IServicesHolder locatorsHolder;
+
+ public DelegatingServiceLocator() {
+ DynamicServiceLocator serviceLocator = new DynamicServiceLocator();
+ locatorsHolder = serviceLocator.list(IServiceLocator.class);
+ }
+
+ private IServiceLocator[] getLocators() {
+ List locators = locatorsHolder.getServices();
+ return locators.toArray(new IServiceLocator[0]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.adempiere.base.IServiceLocator#locate(java.lang.Class)
+ */
+ @Override
+ public IServiceHolder locate(Class type) {
+ DelegatingServiceHolder holder = new DelegatingServiceHolder();
+ for(IServiceLocator locator : getLocators()) {
+ IServiceHolder t = locator.locate(type);
+ if (t != null)
+ holder.addServiceHolder(t);
+ }
+ return holder;
+ }
+
+ /* (non-Javadoc)
+ * @see org.adempiere.base.IServiceLocator#locate(java.lang.Class, java.lang.String)
+ */
+ @Override
+ public IServiceHolder locate(Class type, String serviceType) {
+ DelegatingServiceHolder holder = new DelegatingServiceHolder();
+ for(IServiceLocator locator : getLocators()) {
+ IServiceHolder t = locator.locate(type, serviceType);
+ if (t != null)
+ holder.addServiceHolder(t);
+ }
+ return holder;
+ }
+
+ /* (non-Javadoc)
+ * @see org.adempiere.base.IServiceLocator#locate(java.lang.Class, org.adempiere.base.ServiceQuery)
+ */
+ @Override
+ public IServiceHolder locate(Class type, ServiceQuery query) {
+ DelegatingServiceHolder holder = new DelegatingServiceHolder();
+ for(IServiceLocator locator : getLocators()) {
+ IServiceHolder t = locator.locate(type, query);
+ if (t != null)
+ holder.addServiceHolder(t);
+ }
+ return holder;
+ }
+
+ /* (non-Javadoc)
+ * @see org.adempiere.base.IServiceLocator#locate(java.lang.Class, java.lang.String, org.adempiere.base.ServiceQuery)
+ */
+ @Override
+ public IServiceHolder locate(Class type, String serviceId, ServiceQuery query) {
+ DelegatingServiceHolder holder = new DelegatingServiceHolder();
+ for(IServiceLocator locator : getLocators()) {
+ IServiceHolder t = locator.locate(type, serviceId, query);
+ if (t != null)
+ holder.addServiceHolder(t);
+ }
+ return holder;
+ }
+
+ /* (non-Javadoc)
+ * @see org.adempiere.base.IServiceLocator#locate(java.lang.Class, java.lang.String, java.lang.String, org.adempiere.base.ServiceQuery)
+ */
+ @Override
+ public IServiceHolder locate(Class type, String serviceType,
+ String serviceId, ServiceQuery query) {
+ DelegatingServiceHolder holder = new DelegatingServiceHolder();
+ for(IServiceLocator locator : getLocators()) {
+ IServiceHolder t = locator.locate(type, serviceType, serviceId, query);
+ if (t != null)
+ holder.addServiceHolder(t);
+ }
+ return holder;
+ }
+
+ /* (non-Javadoc)
+ * @see org.adempiere.base.IServiceLocator#list(java.lang.Class)
+ */
+ @Override
+ public IServicesHolder list(Class type) {
+ DelegatingServiceHolder holder = new DelegatingServiceHolder();
+ for(IServiceLocator locator : getLocators()) {
+ IServicesHolder t = locator.list(type);
+ if (t != null)
+ holder.addServicesHolder(t);
+ }
+ return holder;
+ }
+
+ /* (non-Javadoc)
+ * @see org.adempiere.base.IServiceLocator#list(java.lang.Class, java.lang.String)
+ */
+ @Override
+ public IServicesHolder list(Class type, String serviceType) {
+ DelegatingServiceHolder holder = new DelegatingServiceHolder();
+ for(IServiceLocator locator : getLocators()) {
+ IServicesHolder t = locator.list(type, serviceType);
+ if (t != null)
+ holder.addServicesHolder(t);
+ }
+ return holder;
+ }
+
+ /* (non-Javadoc)
+ * @see org.adempiere.base.IServiceLocator#list(java.lang.Class, org.adempiere.base.ServiceQuery)
+ */
+ @Override
+ public IServicesHolder list(Class type, ServiceQuery query) {
+ DelegatingServiceHolder holder = new DelegatingServiceHolder();
+ for(IServiceLocator locator : getLocators()) {
+ IServicesHolder t = locator.list(type, query);
+ if (t != null)
+ holder.addServicesHolder(t);
+ }
+ return holder;
+ }
+
+ /* (non-Javadoc)
+ * @see org.adempiere.base.IServiceLocator#list(java.lang.Class, java.lang.String, org.adempiere.base.ServiceQuery)
+ */
+ @Override
+ public IServicesHolder list(Class type, String serviceId, ServiceQuery query) {
+ DelegatingServiceHolder holder = new DelegatingServiceHolder();
+ for(IServiceLocator locator : getLocators()) {
+ IServicesHolder t = locator.list(type, serviceId, query);
+ if (t != null)
+ holder.addServicesHolder(t);
+ }
+ return holder;
+ }
+
+ /* (non-Javadoc)
+ * @see org.adempiere.base.IServiceLocator#list(java.lang.Class, java.lang.String, java.lang.String, org.adempiere.base.ServiceQuery)
+ */
+ @Override
+ public IServicesHolder list(Class type, String serviceType,
+ String serviceId, ServiceQuery query) {
+ DelegatingServiceHolder holder = new DelegatingServiceHolder();
+ for(IServiceLocator locator : getLocators()) {
+ IServicesHolder t = locator.list(type, serviceType, serviceId, query);
+ if (t != null)
+ holder.addServicesHolder(t);
+ }
+ return holder;
+ }
+
+}
diff --git a/org.adempiere.base/src/org/adempiere/base/IServiceHolder.java b/org.adempiere.base/src/org/adempiere/base/IServiceHolder.java
new file mode 100644
index 0000000000..a8e07dc8fa
--- /dev/null
+++ b/org.adempiere.base/src/org/adempiere/base/IServiceHolder.java
@@ -0,0 +1,30 @@
+/******************************************************************************
+ * Copyright (C) 2012 Heng Sin Low *
+ * 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.adempiere.base;
+
+/**
+ *
+ * @author hengsin
+ *
+ * @param
+ */
+public interface IServiceHolder {
+
+ /**
+ *
+ * @return service instance. null if not available or no matching service found
+ */
+ public T getService();
+
+}
diff --git a/org.adempiere.base/src/org/adempiere/base/IServiceLocator.java b/org.adempiere.base/src/org/adempiere/base/IServiceLocator.java
index 45f8ecc984..7941a4bca1 100644
--- a/org.adempiere.base/src/org/adempiere/base/IServiceLocator.java
+++ b/org.adempiere.base/src/org/adempiere/base/IServiceLocator.java
@@ -16,25 +16,99 @@
*****************************************************************************/
package org.adempiere.base;
-import java.util.List;
-
/**
* A service locator looks up services.
* This is the central authority for adempiere service definition,
* because each service defined has to be looked up via this interface.
*
- * A service in adempiere is an interface extended from the tagging interface IService.
+ * A service in adempiere is an implementation for the registered interface, expose through osgi service registry or equinox extension registry
*
* @author viola
*
*/
public interface IServiceLocator {
- T locate(Class type);
- T locate(Class type, String extensionPointId);
- T locate(Class type, ServiceQuery query);
- T locate(Class type, String extensionPointId, ServiceQuery query);
- List list(Class type);
- List list(Class type, String extensionPointId);
- List list(Class type, ServiceQuery query);
- List list(Class type, String extensionPointId, ServiceQuery query);
+ /**
+ *
+ * @param type service interface
+ * @return holder for dynamic service
+ */
+ IServiceHolder locate(Class type);
+
+ /**
+ *
+ * @param type
+ * @param serviceType equinox extension point id, ignore by osgi service locator
+ * type.getName
+ * @return holder for dynamic service
+ */
+ IServiceHolder locate(Class type, String serviceType);
+
+ /**
+ *
+ * @param type
+ * @param query
+ * @return
+ */
+ IServiceHolder locate(Class type, ServiceQuery query);
+
+ /**
+ *
+ * @param type
+ * @param serviceId component name or extension id
+ * @param query
+ * @return holder for dynamic service
+ */
+ IServiceHolder locate(Class type, String serviceId, ServiceQuery query);
+
+ /**
+ *
+ * @param type
+ * @param serviceType equinox extension point id, ignore by osgi service locator
+ * @param serviceId component name or extension id
+ * @param query
+ * @return holder for dynamic service
+ */
+ IServiceHolder locate(Class type, String serviceType, String serviceId, ServiceQuery query);
+
+ /**
+ *
+ * @param type
+ * @return holder for list of dynamic service
+ */
+ IServicesHolder list(Class type);
+
+ /**
+ *
+ * @param type
+ * @param serviceType equinox extension point id, ignore by osgi service locator
+ * @return holder for list of dynamic service
+ */
+ IServicesHolder list(Class type, String serviceType);
+
+ /**
+ *
+ * @param type
+ * @param query
+ * @return holder for list of dynamic service
+ */
+ IServicesHolder list(Class type, ServiceQuery query);
+
+ /**
+ *
+ * @param type
+ * @param serviceId component name or extension id
+ * @param query
+ * @return holder for list of dynamic service
+ */
+ IServicesHolder list(Class type, String serviceId, ServiceQuery query);
+
+ /**
+ *
+ * @param type
+ * @param serviceType equinox extension point id, ignore by osgi service locator
+ * @param serviceId component name or extension id
+ * @param query
+ * @return holder for list of dynamic service
+ */
+ IServicesHolder list(Class type, String serviceType, String serviceId, ServiceQuery query);
}
diff --git a/org.adempiere.base/src/org/adempiere/base/IServicesHolder.java b/org.adempiere.base/src/org/adempiere/base/IServicesHolder.java
new file mode 100644
index 0000000000..e16b9ed23d
--- /dev/null
+++ b/org.adempiere.base/src/org/adempiere/base/IServicesHolder.java
@@ -0,0 +1,32 @@
+/******************************************************************************
+ * Copyright (C) 2012 Heng Sin Low *
+ * 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.adempiere.base;
+
+import java.util.List;
+
+/**
+ *
+ * @author hengsin
+ *
+ * @param
+ */
+public interface IServicesHolder {
+
+ /**
+ *
+ * @return list of service instance. null if not available or no matching service found
+ */
+ public List getServices();
+
+}
diff --git a/org.adempiere.base/src/org/adempiere/base/Service.java b/org.adempiere.base/src/org/adempiere/base/Service.java
index dcdbdecbe3..65a65c0b64 100644
--- a/org.adempiere.base/src/org/adempiere/base/Service.java
+++ b/org.adempiere.base/src/org/adempiere/base/Service.java
@@ -16,8 +16,6 @@
*****************************************************************************/
package org.adempiere.base;
-import java.util.List;
-
/**
* This is a very simple factory for service locators
*
@@ -26,66 +24,13 @@ import java.util.List;
*/
public class Service {
- private static final String LOCATOR_CLASS = "ServiceLocator";
- private static final String DEFAULT_LOCATOR_CLASS = "org.adempiere.base.equinox.EquinoxServiceLocator";
-
- private static IServiceLocator theLocator;
+ private static IServiceLocator theLocator = new DelegatingServiceLocator();
+ /**
+ *
+ * @return service locator instance
+ */
public static IServiceLocator locator() {
- if (theLocator == null) {
- synchronized (Service.class) {
- if (theLocator == null) {
- theLocator = createServiceLocator();
- }
- }
- }
return theLocator;
}
-
- private static IServiceLocator createServiceLocator() {
- String className = System.getProperty(LOCATOR_CLASS);
- if (className==null)
- className = DEFAULT_LOCATOR_CLASS;
- try {
- Class> clazz = Class.forName(className);
- IServiceLocator locator = (IServiceLocator) clazz.newInstance();
- System.out.println("Started service locator: " + locator);
- return locator;
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- }
-
- public static T locate(Class type) {
- return locate(type, type.getName());
- }
-
- public static T locate(Class type, String id) {
- return locator().locate(type, id);
- }
-
- public static T locate(Class type, ServiceQuery query) {
- return locate(type, type.getName(), query);
- }
-
- public static T locate(Class type, String id, ServiceQuery query) {
- return locator().locate(type, id, query);
- }
-
- public static List list(Class type) {
- return list(type, type.getName());
- }
-
- public static List list(Class type, String id) {
- return locator().list(type, id);
- }
-
- public static List list(Class type, ServiceQuery query) {
- return locator().list(type, type.getName(), query);
- }
-
- public static List list(Class type, String id, ServiceQuery query) {
- return locator().list(type, id, query);
- }
}
diff --git a/org.adempiere.base/src/org/adempiere/base/ServiceQuery.java b/org.adempiere.base/src/org/adempiere/base/ServiceQuery.java
index 74bd10a424..1358bae09c 100644
--- a/org.adempiere.base/src/org/adempiere/base/ServiceQuery.java
+++ b/org.adempiere.base/src/org/adempiere/base/ServiceQuery.java
@@ -1,10 +1,13 @@
package org.adempiere.base;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
-public class ServiceQuery extends HashMap {
+/**
+ * A sequence of name value pair filter
+ * @author hengsin
+ *
+ */
+public class ServiceQuery extends LinkedHashMap {
private static final long serialVersionUID = -3624488575106821781L;
-
- public static final String EXTENSION_ID = "Extension.ID";
}
diff --git a/org.adempiere.base/src/org/adempiere/base/ds/DynamicServiceHolder.java b/org.adempiere.base/src/org/adempiere/base/ds/DynamicServiceHolder.java
new file mode 100644
index 0000000000..96a29dd57b
--- /dev/null
+++ b/org.adempiere.base/src/org/adempiere/base/ds/DynamicServiceHolder.java
@@ -0,0 +1,63 @@
+/******************************************************************************
+ * Copyright (C) 2012 Heng Sin Low *
+ * 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.adempiere.base.ds;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.adempiere.base.IServiceHolder;
+import org.adempiere.base.IServicesHolder;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * @author hengsin
+ *
+ */
+public class DynamicServiceHolder implements IServiceHolder, IServicesHolder {
+
+ private ServiceTracker serviceTracker;
+
+ /**
+ * @param tracker
+ */
+ public DynamicServiceHolder(ServiceTracker tracker) {
+ serviceTracker = tracker;
+ if (serviceTracker.getTrackingCount() == -1)
+ serviceTracker.open();
+ }
+
+ @Override
+ public T getService() {
+ T service = serviceTracker.getService();
+ return service;
+ }
+
+ @Override
+ public List getServices() {
+ List services = new ArrayList();
+ ServiceReference[] objects = serviceTracker.getServiceReferences();
+ List> references = new ArrayList>();
+ if (objects != null && objects.length > 0) {
+ references = Arrays.asList(objects);
+ }
+ Collections.sort(references, Collections.reverseOrder());
+ for(ServiceReference reference : references) {
+ services.add(serviceTracker.getService(reference));
+ }
+ return services;
+ }
+}
diff --git a/org.adempiere.base/src/org/adempiere/base/ds/DynamicServiceLocator.java b/org.adempiere.base/src/org/adempiere/base/ds/DynamicServiceLocator.java
new file mode 100644
index 0000000000..7f2dfae0af
--- /dev/null
+++ b/org.adempiere.base/src/org/adempiere/base/ds/DynamicServiceLocator.java
@@ -0,0 +1,166 @@
+/******************************************************************************
+ * Copyright (C) 2012 Heng Sin Low *
+ * 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.adempiere.base.ds;
+
+import org.adempiere.base.BaseActivator;
+import org.adempiere.base.IServiceHolder;
+import org.adempiere.base.IServiceLocator;
+import org.adempiere.base.IServicesHolder;
+import org.adempiere.base.ServiceQuery;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.component.ComponentConstants;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * @author hengsin
+ *
+ */
+public class DynamicServiceLocator implements IServiceLocator {
+
+ /**
+ *
+ */
+ public DynamicServiceLocator() {
+ }
+
+ /**
+ * @see org.adempiere.base.IServiceLocator#locate(java.lang.Class)
+ */
+ @Override
+ public IServiceHolder locate(Class type) {
+ Filter filter = filter(type, null, null);
+ ServiceTracker tracker = BaseActivator.getServiceTracker(type, filter);
+ return new DynamicServiceHolder(tracker);
+ }
+
+ /**
+ * @see org.adempiere.base.IServiceLocator#locate(java.lang.Class, java.lang.String)
+ */
+ @Override
+ public IServiceHolder locate(Class type, String serviceType) {
+ return locate(type);
+ }
+
+ /**
+ * @see org.adempiere.base.IServiceLocator#locate(java.lang.Class, org.adempiere.base.ServiceQuery)
+ */
+ @Override
+ public IServiceHolder locate(Class type, ServiceQuery query) {
+ if (query == null || query.isEmpty())
+ return locate(type);
+
+ Filter filter = filter(type, null, query);
+ ServiceTracker tracker = BaseActivator.getServiceTracker(type, filter);
+ return new DynamicServiceHolder(tracker);
+ }
+
+ /**
+ * @see org.adempiere.base.IServiceLocator#locate(java.lang.Class, java.lang.String, org.adempiere.base.ServiceQuery)
+ */
+ @Override
+ public IServiceHolder locate(Class type, String serviceId, ServiceQuery query) {
+ if ((query == null || query.isEmpty()) && (serviceId == null || serviceId.trim().length() == 0))
+ return locate(type);
+
+ Filter filter = filter(type, serviceId, query);
+ ServiceTracker tracker = BaseActivator.getServiceTracker(type, filter);
+
+ return new DynamicServiceHolder(tracker);
+ }
+
+ /**
+ * @see org.adempiere.base.IServiceLocator#locate(java.lang.Class, java.lang.String, java.lang.String, org.adempiere.base.ServiceQuery)
+ */
+ @Override
+ public IServiceHolder locate(Class type, String serviceType, String serviceId,
+ ServiceQuery query) {
+ return locate(type, serviceId, query);
+ }
+
+ /**
+ * @see org.adempiere.base.IServiceLocator#list(java.lang.Class)
+ */
+ @Override
+ public IServicesHolder list(Class type) {
+ Filter filter = filter(type, null, null);
+ ServiceTracker tracker = BaseActivator.getServiceTracker(type, filter);
+
+ return new DynamicServiceHolder(tracker);
+ }
+
+ /**
+ * @see org.adempiere.base.IServiceLocator#list(java.lang.Class, java.lang.String)
+ */
+ @Override
+ public IServicesHolder list(Class type, String serviceType) {
+ return list(type);
+ }
+
+ /**
+ * @see org.adempiere.base.IServiceLocator#list(java.lang.Class, org.adempiere.base.ServiceQuery)
+ */
+ @Override
+ public IServicesHolder list(Class type, ServiceQuery query) {
+ if (query == null || query.isEmpty())
+ return list(type);
+
+ Filter filter = filter(type, null, query);
+ ServiceTracker tracker = BaseActivator.getServiceTracker(type, filter);
+ return new DynamicServiceHolder(tracker);
+ }
+
+ /**
+ * @see org.adempiere.base.IServiceLocator#list(java.lang.Class, java.lang.String, org.adempiere.base.ServiceQuery)
+ */
+ @Override
+ public IServicesHolder list(Class type, String serviceId, ServiceQuery query) {
+ if ((query == null || query.isEmpty()) && (serviceId == null || serviceId.trim().length() == 0))
+ return list(type);
+
+ Filter filter = filter(type, serviceId, query);
+ ServiceTracker tracker = BaseActivator.getServiceTracker(type, filter);
+ return new DynamicServiceHolder(tracker);
+ }
+
+ /**
+ * @see org.adempiere.base.IServiceLocator#list(java.lang.Class, java.lang.String, java.lang.String, org.adempiere.base.ServiceQuery)
+ */
+ @Override
+ public IServicesHolder list(Class type, String serviceType,
+ String serviceId, ServiceQuery query) {
+ return list(type, serviceId, query);
+ }
+
+ private Filter filter(Class> type, String serviceId, ServiceQuery query) {
+ StringBuilder builder = new StringBuilder("(&(objectclass=");
+ builder.append(type.getName()).append(")");
+ if (query != null) {
+ for(String key : query.keySet()) {
+ String value = query.get(key);
+ builder.append("(").append(key).append("=").append(value).append(")");
+ }
+ }
+ if (serviceId != null && serviceId.trim().length() > 0) {
+ builder.append("(").append(ComponentConstants.COMPONENT_NAME).append("=").append(serviceId.trim()).append(")");
+ }
+ builder.append(")");
+ try {
+ return BaseActivator.getBundleContext().createFilter(builder.toString());
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+}
diff --git a/org.adempiere.base/src/org/adempiere/base/equinox/EquinoxServiceHolder.java b/org.adempiere.base/src/org/adempiere/base/equinox/EquinoxServiceHolder.java
new file mode 100644
index 0000000000..d7e501e00f
--- /dev/null
+++ b/org.adempiere.base/src/org/adempiere/base/equinox/EquinoxServiceHolder.java
@@ -0,0 +1,46 @@
+/******************************************************************************
+ * Copyright (C) 2012 Heng Sin Low *
+ * 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.adempiere.base.equinox;
+
+import java.util.List;
+
+import org.adempiere.base.IServiceHolder;
+import org.adempiere.base.IServicesHolder;
+
+/**
+ * @author hengsin
+ *
+ */
+public class EquinoxServiceHolder implements IServiceHolder, IServicesHolder {
+
+ private ExtensionList extensionList;
+
+ /**
+ * @param list
+ */
+ public EquinoxServiceHolder(ExtensionList list) {
+ extensionList = list;
+ }
+
+ @Override
+ public T getService() {
+ return extensionList.first();
+ }
+
+ @Override
+ public List getServices() {
+ return extensionList.asList();
+ }
+
+}
diff --git a/org.adempiere.base/src/org/adempiere/base/equinox/EquinoxServiceLocator.java b/org.adempiere.base/src/org/adempiere/base/equinox/EquinoxServiceLocator.java
index 1a730d3669..c706c8387c 100644
--- a/org.adempiere.base/src/org/adempiere/base/equinox/EquinoxServiceLocator.java
+++ b/org.adempiere.base/src/org/adempiere/base/equinox/EquinoxServiceLocator.java
@@ -16,9 +16,9 @@
*****************************************************************************/
package org.adempiere.base.equinox;
-import java.util.List;
-
+import org.adempiere.base.IServiceHolder;
import org.adempiere.base.IServiceLocator;
+import org.adempiere.base.IServicesHolder;
import org.adempiere.base.ServiceQuery;
@@ -32,44 +32,60 @@ import org.adempiere.base.ServiceQuery;
*/
public class EquinoxServiceLocator implements IServiceLocator {
- public List list(Class type) {
+ @Override
+ public IServicesHolder list(Class type) {
return list(type, type.getName());
}
@Override
- public List list(Class type, String extensionPointId) {
- ExtensionList list = new ExtensionList(type, extensionPointId);
- return list.asList();
+ public IServicesHolder list(Class type, String serviceType) {
+ ExtensionList list = new ExtensionList(type, serviceType);
+ return new EquinoxServiceHolder(list);
}
- public List list(Class type, ServiceQuery query) {
- return list(type, type.getName(), query);
+ @Override
+ public IServicesHolder list(Class type, ServiceQuery query) {
+ return list(type, type.getName(), null, query);
}
@Override
- public List list(Class type, String extensionPointId,
+ public IServicesHolder