More flexible service locator interface.
https://sourceforge.net/tracker/?func=detail&aid=2700937&group_id=176962&atid=879334
This commit is contained in:
parent
e11cc21c52
commit
f73caa3e98
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.4"?>
|
||||
<plugin>
|
||||
<extension-point id="org.adempiere.base.ResourceFinder" name="org.adempiere.base.ResourceFinder" schema="schema/ResourceFinder.exsd"/>
|
||||
<extension-point id="org.adempiere.base.IResourceFinder" name="ResourceFinder" schema="schema/ResourceFinder.exsd"/>
|
||||
<extension-point id="org.adempiere.base.Callout" name="Callout" schema="schema/org.adempiere.base.Callout.exsd"/>
|
||||
|
||||
</plugin>
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Schema file written by PDE -->
|
||||
<schema targetNamespace="org.adempiere.base" xmlns="http://www.w3.org/2001/XMLSchema">
|
||||
<annotation>
|
||||
<appinfo>
|
||||
<meta.schema plugin="org.adempiere.base" id="org.adempiere.base.Callout" name="Callout"/>
|
||||
</appinfo>
|
||||
<documentation>
|
||||
This is the ADempiere Call extension point.
|
||||
|
||||
Callouts provided by plugins are not entered into the application dictionary.
|
||||
Instead, you specify Table and Column in the extension declaration.
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<element name="extension">
|
||||
<annotation>
|
||||
<appinfo>
|
||||
<meta.element />
|
||||
</appinfo>
|
||||
</annotation>
|
||||
<complexType>
|
||||
<choice>
|
||||
<element ref="client" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</choice>
|
||||
<attribute name="point" type="string" use="required">
|
||||
<annotation>
|
||||
<documentation>
|
||||
|
||||
</documentation>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="id" type="string">
|
||||
<annotation>
|
||||
<documentation>
|
||||
|
||||
</documentation>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="name" type="string">
|
||||
<annotation>
|
||||
<documentation>
|
||||
|
||||
</documentation>
|
||||
<appinfo>
|
||||
<meta.attribute translatable="true"/>
|
||||
</appinfo>
|
||||
</annotation>
|
||||
</attribute>
|
||||
</complexType>
|
||||
</element>
|
||||
|
||||
<element name="client">
|
||||
<complexType>
|
||||
<attribute name="class" type="string" use="required">
|
||||
<annotation>
|
||||
<documentation>
|
||||
|
||||
</documentation>
|
||||
<appinfo>
|
||||
<meta.attribute kind="java" basedOn=":org.compiere.model.Callout"/>
|
||||
</appinfo>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="tableName" type="string" use="required">
|
||||
<annotation>
|
||||
<documentation>
|
||||
|
||||
</documentation>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="columnName" type="string" use="required">
|
||||
<annotation>
|
||||
<documentation>
|
||||
|
||||
</documentation>
|
||||
</annotation>
|
||||
</attribute>
|
||||
</complexType>
|
||||
</element>
|
||||
|
||||
<annotation>
|
||||
<appinfo>
|
||||
<meta.section type="since"/>
|
||||
</appinfo>
|
||||
<documentation>
|
||||
[Enter the first release in which this extension point appears.]
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<annotation>
|
||||
<appinfo>
|
||||
<meta.section type="examples"/>
|
||||
</appinfo>
|
||||
<documentation>
|
||||
[Enter extension point usage example here.]
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<annotation>
|
||||
<appinfo>
|
||||
<meta.section type="apiinfo"/>
|
||||
</appinfo>
|
||||
<documentation>
|
||||
[Enter API information here.]
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
<annotation>
|
||||
<appinfo>
|
||||
<meta.section type="implementation"/>
|
||||
</appinfo>
|
||||
<documentation>
|
||||
[Enter information about supplied implementation of this extension point.]
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
|
||||
</schema>
|
|
@ -0,0 +1,41 @@
|
|||
package org.adempiere.base;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
import org.adempiere.base.equinox.ExtensionList;
|
||||
import org.compiere.model.Callout;
|
||||
|
||||
/**
|
||||
* This is a facade class for the Service Locator.
|
||||
* It provides simple access to all core services.
|
||||
*
|
||||
* @author viola
|
||||
*/
|
||||
public class Core {
|
||||
|
||||
public static IResourceFinder getResourceFinder() {
|
||||
return new IResourceFinder() {
|
||||
|
||||
public URL getResource(String name) {
|
||||
List<IResourceFinder> f = Service.list(IResourceFinder.class);
|
||||
for (IResourceFinder finder : f) {
|
||||
URL url = finder.getResource(name);
|
||||
if (url!=null)
|
||||
return url;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Callout getCallout(String tableName, String columnName) {
|
||||
ServiceQuery query = new ServiceQuery();
|
||||
query.put("tableName", tableName);
|
||||
query.put("columnName", columnName);
|
||||
|
||||
return Service.locate(Callout.class, query);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -18,7 +18,7 @@ package org.adempiere.base;
|
|||
|
||||
import java.net.URL;
|
||||
|
||||
public interface IResourceFinder {
|
||||
public interface IResourceFinder extends IService {
|
||||
|
||||
URL getResource(String name);
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package org.adempiere.base;
|
||||
|
||||
public interface IService {
|
||||
|
||||
}
|
|
@ -16,16 +16,24 @@
|
|||
*****************************************************************************/
|
||||
package org.adempiere.base;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.compiere.model.Callout;
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @author viola
|
||||
*
|
||||
*/
|
||||
public interface IServiceLocator {
|
||||
|
||||
IResourceFinder getResourceFinder();
|
||||
|
||||
<T extends IService> T locate(Class<T> type);
|
||||
<T extends IService> T locate(Class<T> type, ServiceQuery query);
|
||||
<T extends IService> List<T> list(Class<T> type);
|
||||
<T extends IService> List<T> list(Class<T> type, ServiceQuery query);
|
||||
}
|
||||
|
|
|
@ -16,10 +16,13 @@
|
|||
*****************************************************************************/
|
||||
package org.adempiere.base;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.adempiere.base.equinox.EquinoxServiceLocator;
|
||||
|
||||
/**
|
||||
* This is a very simple factory for service locators
|
||||
*
|
||||
* @author viola
|
||||
*
|
||||
*/
|
||||
|
@ -28,14 +31,31 @@ public class Service {
|
|||
private static IServiceLocator theLocator;
|
||||
|
||||
public static IServiceLocator locator() {
|
||||
if (theLocator==null) {
|
||||
if (theLocator == null) {
|
||||
synchronized (Service.class) {
|
||||
if (theLocator==null) {
|
||||
if (theLocator == null) {
|
||||
theLocator = new EquinoxServiceLocator();
|
||||
System.out
|
||||
.println("Started service locator: " + theLocator);
|
||||
}
|
||||
}
|
||||
}
|
||||
return theLocator;
|
||||
}
|
||||
|
||||
public static <T extends IService> T locate(Class<T> type) {
|
||||
return locator().locate(type);
|
||||
}
|
||||
|
||||
public static <T extends IService> T locate(Class<T> type, ServiceQuery query) {
|
||||
return locator().locate(type, query);
|
||||
}
|
||||
|
||||
public static <T extends IService> List<T> list(Class<T> type) {
|
||||
return locator().list(type);
|
||||
}
|
||||
|
||||
public static <T extends IService> List<T> list(Class<T> type, ServiceQuery query) {
|
||||
return locator().list(type, query);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package org.adempiere.base;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class ServiceQuery extends HashMap<String, String> {
|
||||
|
||||
private static final long serialVersionUID = -3624488575106821781L;
|
||||
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/******************************************************************************
|
||||
* Product: Adempiere ERP & CRM Smart Business Solution *
|
||||
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
|
||||
* 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. *
|
||||
* For the text or an alternative of this public license, you may reach us *
|
||||
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
|
||||
* or via info@compiere.org or http://www.compiere.org/license.html *
|
||||
*****************************************************************************/
|
||||
package org.adempiere.base.equinox;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import org.adempiere.base.IResourceFinder;
|
||||
|
||||
public class EquinoxResourceFinder implements IResourceFinder {
|
||||
|
||||
public URL getResource(String name) {
|
||||
ExtensionList<IResourceFinder> list = new ExtensionList<IResourceFinder>(IResourceFinder.class, "org.adempiere.base.ResourceFinder");
|
||||
for (IResourceFinder rf : list) {
|
||||
URL url = rf.getResource(name);
|
||||
if (url!=null)
|
||||
return url;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -16,14 +16,41 @@
|
|||
*****************************************************************************/
|
||||
package org.adempiere.base.equinox;
|
||||
|
||||
import org.adempiere.base.IResourceFinder;
|
||||
import java.util.List;
|
||||
|
||||
import org.adempiere.base.IService;
|
||||
import org.adempiere.base.IServiceLocator;
|
||||
import org.adempiere.base.ServiceQuery;
|
||||
|
||||
|
||||
/**
|
||||
* This is the Equinox implementation of the ADempiere Service Locator.
|
||||
* It delegates work to the ExtensionList that lookups up services as extensions.
|
||||
* The ids of extension points have to correspond to the interface names of the services.
|
||||
*
|
||||
* @author viola
|
||||
*
|
||||
*/
|
||||
public class EquinoxServiceLocator implements IServiceLocator {
|
||||
|
||||
public IResourceFinder getResourceFinder() {
|
||||
return new EquinoxResourceFinder();
|
||||
public <T extends IService> List<T> list(Class<T> type) {
|
||||
ExtensionList<T> list = new ExtensionList<T>(type, type.getName());
|
||||
return list.asList();
|
||||
}
|
||||
|
||||
public <T extends IService> List<T> list(Class<T> type, ServiceQuery query) {
|
||||
ExtensionList<T> list = new ExtensionList<T>(type, type.getName(), query);
|
||||
return list.asList();
|
||||
}
|
||||
|
||||
public <T extends IService> T locate(Class<T> type) {
|
||||
ExtensionList<T> list = new ExtensionList<T>(type, type.getName());
|
||||
return list.first();
|
||||
}
|
||||
|
||||
public <T extends IService> T locate(Class<T> type, ServiceQuery query) {
|
||||
ExtensionList<T> list = new ExtensionList<T>(type, type.getName(), query);
|
||||
return list.first();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,12 +16,28 @@
|
|||
*****************************************************************************/
|
||||
package org.adempiere.base.equinox;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.adempiere.base.ServiceQuery;
|
||||
import org.compiere.model.Callout;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IConfigurationElement;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
|
||||
/**
|
||||
* This List looks up services as extensions in equinox.
|
||||
* The extension point must be the class name of the service interface.
|
||||
* The query attributes are checked against the attributes
|
||||
* of the extension configuration element.
|
||||
*
|
||||
* In order to minimize equinox lookups, a filtering iterator is used.
|
||||
* @author viola
|
||||
*
|
||||
* @param <T> The service this list holds implementations of.
|
||||
*/
|
||||
public class ExtensionList<T> implements Iterable<T>{
|
||||
|
||||
public class ExtensionIterator<T> implements Iterator<T> {
|
||||
|
@ -29,11 +45,31 @@ public class ExtensionList<T> implements Iterable<T>{
|
|||
private int index = 0;
|
||||
|
||||
public boolean hasNext() {
|
||||
iterateUntilAccepted();
|
||||
return index<elements.length;
|
||||
}
|
||||
|
||||
private void iterateUntilAccepted() {
|
||||
while (index<elements.length) {
|
||||
if (accept(elements[index]))
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean accept(IConfigurationElement element) {
|
||||
for (String name : filters.keySet()) {
|
||||
String expected = filters.get(name);
|
||||
String actual = element.getAttribute(name);
|
||||
if (!expected.equals(actual))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T next() {
|
||||
iterateUntilAccepted();
|
||||
IConfigurationElement e = elements[index++];
|
||||
try {
|
||||
return (T) e.createExecutableExtension("class");
|
||||
|
@ -49,6 +85,7 @@ public class ExtensionList<T> implements Iterable<T>{
|
|||
}
|
||||
|
||||
private IConfigurationElement[] elements;
|
||||
private HashMap<String, String> filters = new HashMap<String, String>();
|
||||
|
||||
public ExtensionList(Class<T> clazz, String id) {
|
||||
try {
|
||||
|
@ -58,8 +95,34 @@ public class ExtensionList<T> implements Iterable<T>{
|
|||
}
|
||||
}
|
||||
|
||||
public ExtensionList(Class<T> type, String name, ServiceQuery query) {
|
||||
this(type, name);
|
||||
for (String key : query.keySet()) {
|
||||
addFilter(key, query.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<T> iterator() {
|
||||
return new ExtensionIterator<T>();
|
||||
}
|
||||
|
||||
public void addFilter(String name, String value) {
|
||||
filters.put(name, value);
|
||||
}
|
||||
|
||||
public T first() {
|
||||
Iterator<T> i = iterator();
|
||||
if (!i.hasNext())
|
||||
return null;
|
||||
return i.next();
|
||||
}
|
||||
|
||||
public List<T> asList() {
|
||||
List<T> result = new ArrayList<T>();
|
||||
for (T t : this) {
|
||||
result.add(t);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
@ -30,6 +31,8 @@ import javax.jnlp.ServiceManager;
|
|||
import javax.jnlp.UnavailableServiceException;
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
import org.adempiere.base.Core;
|
||||
import org.adempiere.base.IResourceFinder;
|
||||
import org.adempiere.base.Service;
|
||||
import org.compiere.db.CConnection;
|
||||
import org.compiere.model.MClient;
|
||||
|
@ -337,7 +340,7 @@ public final class Adempiere
|
|||
if (s_imageLogo == null)
|
||||
{
|
||||
Toolkit tk = Toolkit.getDefaultToolkit();
|
||||
URL url = Service.locator().getResourceFinder().getResource(s_file100x30);
|
||||
URL url = Core.getResourceFinder().getResource(s_file100x30);
|
||||
// URL url = org.compiere.Adempiere.class.getResource(s_file100x30);
|
||||
// System.out.println(url);
|
||||
if (url == null)
|
||||
|
@ -583,7 +586,7 @@ public final class Adempiere
|
|||
} // startupEnvironment
|
||||
|
||||
public static URL getResource(String name) {
|
||||
return Service.locator().getResourceFinder().getResource(name);
|
||||
return Core.getResourceFinder().getResource(name);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ package org.compiere.model;
|
|||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.adempiere.base.IService;
|
||||
|
||||
/**
|
||||
* Callout Interface for Callout.
|
||||
* Used in MTab and ImpFormatRow
|
||||
|
@ -25,7 +27,7 @@ import java.util.Properties;
|
|||
* @author Jorg Janke
|
||||
* @version $Id: Callout.java,v 1.2 2006/07/30 00:51:05 jjanke Exp $
|
||||
*/
|
||||
public interface Callout
|
||||
public interface Callout extends IService
|
||||
{
|
||||
/**
|
||||
* Start Callout.
|
||||
|
|
|
@ -37,6 +37,8 @@ import java.util.logging.Level;
|
|||
import javax.script.ScriptEngine;
|
||||
import javax.swing.event.EventListenerList;
|
||||
|
||||
import org.adempiere.base.Core;
|
||||
import org.adempiere.base.Service;
|
||||
import org.compiere.util.CLogMgt;
|
||||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.DB;
|
||||
|
@ -2682,6 +2684,13 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
|
|||
*/
|
||||
public String processCallout (GridField field)
|
||||
{
|
||||
Object value = field.getValue();
|
||||
Object oldValue = field.getOldValue();
|
||||
Callout co = Core.getCallout(getTableName(), field.getColumnName());
|
||||
if (co!=null) {
|
||||
return co.start(m_vo.ctx, "", m_vo.WindowNo, this, field, value, oldValue);
|
||||
}
|
||||
|
||||
String callout = field.getCallout();
|
||||
if (callout.length() == 0)
|
||||
return "";
|
||||
|
@ -2689,8 +2698,6 @@ public class GridTab implements DataStatusListener, Evaluatee, Serializable
|
|||
if (isProcessed() && !field.isAlwaysUpdateable()) // only active records
|
||||
return ""; // "DocProcessed";
|
||||
|
||||
Object value = field.getValue();
|
||||
Object oldValue = field.getOldValue();
|
||||
log.fine(field.getColumnName() + "=" + value
|
||||
+ " (" + callout + ") - old=" + oldValue);
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ import javax.swing.JFrame;
|
|||
import javax.swing.RepaintManager;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import org.adempiere.base.Core;
|
||||
import org.adempiere.base.IResourceFinder;
|
||||
import org.adempiere.base.Service;
|
||||
import org.compiere.Adempiere;
|
||||
|
@ -1485,7 +1486,7 @@ public final class Env
|
|||
*/
|
||||
public static Image getImage (String fileNameInImageDir)
|
||||
{
|
||||
IResourceFinder rf = Service.locator().getResourceFinder();
|
||||
IResourceFinder rf = Core.getResourceFinder();
|
||||
URL url = rf.getResource("images/" + fileNameInImageDir);
|
||||
|
||||
// URL url = Adempiere.class.getResource("images/" + fileNameInImageDir);
|
||||
|
@ -1506,7 +1507,7 @@ public final class Env
|
|||
*/
|
||||
public static ImageIcon getImageIcon (String fileNameInImageDir)
|
||||
{
|
||||
IResourceFinder rf = Service.locator().getResourceFinder();
|
||||
IResourceFinder rf = Core.getResourceFinder();
|
||||
URL url = rf.getResource("images/" + fileNameInImageDir);
|
||||
// URL url = Adempiere.class.getResource("images/" + fileNameInImageDir);
|
||||
if (url == null)
|
||||
|
@ -1528,7 +1529,7 @@ public final class Env
|
|||
*/
|
||||
public static ImageIcon getImageIcon2 (String fileName)
|
||||
{
|
||||
IResourceFinder rf = Service.locator().getResourceFinder();
|
||||
IResourceFinder rf = Core.getResourceFinder();
|
||||
URL url = rf.getResource("images/" + fileName+".gif");
|
||||
// URL url = Adempiere.class.getResource("images/" + fileName+".gif");
|
||||
if (url == null)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<extension
|
||||
id="RF"
|
||||
name="RF"
|
||||
point="org.adempiere.base.ResourceFinder">
|
||||
point="org.adempiere.base.IResourceFinder">
|
||||
<client
|
||||
class="org.compiere.util.ResourceFinder">
|
||||
</client>
|
||||
|
|
Loading…
Reference in New Issue