[Ipojo-toolbox-commits] SF.net SVN: ipojo-toolbox:[66] trunk/utils/ipojo-metatype-bridge
Brought to you by:
bourretp
|
From: <bou...@us...> - 2009-04-20 15:23:58
|
Revision: 66
http://ipojo-toolbox.svn.sourceforge.net/ipojo-toolbox/?rev=66&view=rev
Author: bourretp
Date: 2009-04-20 15:23:43 +0000 (Mon, 20 Apr 2009)
Log Message:
-----------
iPOJO Metatype bridge :
- Removed org.apache.felix.ipojo ghost package
* Renamed component types, implementation classes and instance names.
Modified Paths:
--------------
trunk/utils/ipojo-metatype-bridge/metadata.xml
Added Paths:
-----------
trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/Factory2MetatypeBridge.java
trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/MetatypeBridgeManager.java
Removed Paths:
-------------
trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/MetatypeBridge.java
trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/MetatypeFactoryWrapper.java
trunk/utils/ipojo-metatype-bridge/src/main/java/org/
Modified: trunk/utils/ipojo-metatype-bridge/metadata.xml
===================================================================
--- trunk/utils/ipojo-metatype-bridge/metadata.xml 2009-04-20 09:15:10 UTC (rev 65)
+++ trunk/utils/ipojo-metatype-bridge/metadata.xml 2009-04-20 15:23:43 UTC (rev 66)
@@ -19,17 +19,17 @@
-->
<!-- TODO !!! : Rename components type, instances and properties -->
<iPOJO>
- <component className="net.sourceforge.ipojo_toolbox.utils.metatype_bridge.MetatypeBridge" architecture="true" public="false">
+ <component name="net.sourceforge.ipojo_toolbox.MetatypeBridgeManager" className="net.sourceforge.ipojo_toolbox.utils.metatype_bridge.MetatypeBridgeManager" architecture="true" public="false">
<requires filter="(factory.state=1)" optional="true" aggregate="true">
<callback type="bind" method="bindFactory"/>
<callback type="unbind" method="unbindFactory"/>
</requires>
- <requires field="m_wrapperFactory" filter="(factory.name=MetatypeBundleBridge)"/>
+ <requires field="m_wrapperFactory" filter="(factory.name=net.sourceforge.ipojo_toolbox.Factory2MetatypeBridge)"/>
<callback transition="invalidate" method="stop"/>
</component>
- <instance component="net.sourceforge.ipojo_toolbox.utils.metatype_bridge.MetatypeBridge"/>
+ <instance component="net.sourceforge.ipojo_toolbox.MetatypeBridgeManager" name="net.sourceforge.ipojo_toolbox.MetatypeBridgeManager"/>
- <component className="net.sourceforge.ipojo_toolbox.utils.metatype_bridge.MetatypeFactoryWrapper" architecture="false" name="MetatypeBundleBridge">
+ <component name="net.sourceforge.ipojo_toolbox.Factory2MetatypeBridge" className="net.sourceforge.ipojo_toolbox.utils.metatype_bridge.Factory2MetatypeBridge">
<provides>
<property name="bundle.id" type="long"/>
<property name="service.pid" type="java.lang.String"/>
Copied: trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/Factory2MetatypeBridge.java (from rev 65, trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/MetatypeFactoryWrapper.java)
===================================================================
--- trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/Factory2MetatypeBridge.java (rev 0)
+++ trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/Factory2MetatypeBridge.java 2009-04-20 15:23:43 UTC (rev 66)
@@ -0,0 +1,229 @@
+package net.sourceforge.ipojo_toolbox.utils.metatype_bridge;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.List;
+
+import org.apache.felix.ipojo.IPojoFactory;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
+import org.apache.felix.ipojo.architecture.PropertyDescription;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedServiceFactory;
+import org.osgi.service.metatype.AttributeDefinition;
+import org.osgi.service.metatype.MetaTypeProvider;
+import org.osgi.service.metatype.ObjectClassDefinition;
+
+/**
+ * ManagedServiceFactory wrapper.
+ * This class delegates call to the wrapped managed service factory.
+ * However, it provides a Metatype description for the factory configurations.
+ */
+public class Factory2MetatypeBridge implements MetaTypeProvider, ManagedServiceFactory {
+
+ /**
+ * Wrapped Factory.
+ */
+ private IPojoFactory m_factory; //Injected
+
+ private class ObjectClassDefinitionImpl implements ObjectClassDefinition {
+
+ private ComponentTypeDescription m_description;
+
+ List m_attributes = new ArrayList();
+
+ public ObjectClassDefinitionImpl(ComponentTypeDescription desc) {
+ m_description = desc;
+ PropertyDescription[] props = desc.getProperties();
+ for (int i = 0; i < props.length; i++) {
+ m_attributes.add(new AttributeDefinitionImpl(props[i], m_description.getName()));
+ }
+ }
+
+ public AttributeDefinition[] getAttributeDefinitions(int filter) {
+ List list = new ArrayList();
+ switch(filter) {
+ case ObjectClassDefinition.OPTIONAL :
+ for (int i = 0; i < m_attributes.size(); i++) {
+ AttributeDefinitionImpl att = (AttributeDefinitionImpl) m_attributes.get(i);
+ if (! att.m_isImmutable && ! att.m_isMandatory) {
+ list.add(att);
+ }
+ }
+ break;
+ case ObjectClassDefinition.REQUIRED:
+ for (int i = 0; i < m_attributes.size(); i++) {
+ AttributeDefinitionImpl att = (AttributeDefinitionImpl) m_attributes.get(i);
+ if (! att.m_isImmutable && att.m_isMandatory) {
+ list.add(att);
+ }
+ }
+ break;
+ default :
+ for (int i = 0; i < m_attributes.size(); i++) {
+ AttributeDefinitionImpl att = (AttributeDefinitionImpl) m_attributes.get(i);
+ if (! att.m_isImmutable) {
+ list.add(att);
+ }
+ }
+ }
+ return (AttributeDefinition[]) list.toArray(new AttributeDefinition[list.size()]);
+ }
+
+ public String getDescription() {
+ return m_description.getName();
+ }
+
+ public String getID() {
+ return m_description.getName();
+ }
+
+ public InputStream getIcon(int arg0) throws IOException {
+ return null;
+ }
+
+ public String getName() {
+ return m_description.getName();
+ }
+
+ }
+
+ private class AttributeDefinitionImpl implements AttributeDefinition {
+
+ private PropertyDescription m_desc;
+ private String m_typeName;
+
+ private int m_type;
+ private int m_cardinality;
+ private boolean m_isMandatory;
+ private boolean m_isImmutable;
+
+ public AttributeDefinitionImpl(PropertyDescription desc, String typeName) {
+ m_desc = desc;
+ m_typeName = typeName;
+ m_isMandatory = desc.isMandatory();
+ m_isImmutable = desc.isImmutable();
+ String type = m_desc.getType();
+ String internType = null;
+ if (type.endsWith("[]")) {
+ // Array
+ m_cardinality = Integer.MAX_VALUE;
+ int index = type.indexOf('[');
+ internType = type.substring(0, index);
+ } else if (type.equals(java.util.Vector.class.getName())) {
+ m_cardinality = Integer.MIN_VALUE;
+ internType = String.class.getName();
+ } else {
+ m_cardinality = 0;
+ internType = type;
+ }
+ m_type = getTypeByInternType(internType);
+ }
+
+ private int getTypeByInternType(String internType) {
+ //STRING,LONG,INTEGER, CHAR,BYTE,DOUBLE,FLOAT, BOOLEAN
+
+ if (internType.equalsIgnoreCase("string") || internType.equals(String.class.getName())) {
+ return AttributeDefinition.STRING;
+ }
+ if (internType.equals("boolean")) {
+ return AttributeDefinition.BOOLEAN;
+ }
+ if (internType.equals("float")) {
+ return AttributeDefinition.FLOAT;
+ }
+ if (internType.equals("double")) {
+ return AttributeDefinition.DOUBLE;
+ }
+ if (internType.equals("byte")) {
+ return AttributeDefinition.BYTE;
+ }
+ if (internType.equals("char")) {
+ return AttributeDefinition.CHARACTER;
+ }
+ if (internType.equals("int")) {
+ return AttributeDefinition.INTEGER;
+ }
+ if (internType.equals("long")) {
+ return AttributeDefinition.LONG;
+ }
+ System.out.println("WARNING : Cannot determine the type of " + internType);
+ return -1;
+ }
+
+ public int getCardinality() {
+ return m_cardinality;
+ }
+
+ public String[] getDefaultValue() {
+ if (m_desc.getValue() != null) {
+ if (getCardinality() == 0) {
+ return new String[] { m_desc.getValue() };
+ } else if (m_cardinality > 0) {
+ return org.apache.felix.ipojo.parser.ParseUtils.parseArrays(m_desc.getValue());
+ } else if (m_cardinality < 0) {
+ //TODO handle vector case
+ return new String[] { m_desc.getValue() };
+ }
+ }
+ return null;
+ }
+
+ public String getDescription() {
+ return m_desc.getName();
+ }
+
+ public String getID() {
+ return m_typeName + "-" + m_desc.getName();
+
+ }
+
+ public String getName() {
+ return m_desc.getName();
+ }
+
+ public String[] getOptionLabels() {
+ return null;
+ }
+
+ public String[] getOptionValues() {
+ return null;
+ }
+
+ public int getType() {
+ return m_type;
+ }
+
+ public String validate(String arg0) {
+ return null; // No validation
+ }
+
+
+
+ }
+
+ public void deleted(String arg0) {
+ m_factory.deleted(arg0);
+ }
+
+ public String getName() {
+ return m_factory.getName();
+ }
+
+ public void updated(String arg0, Dictionary arg1)
+ throws ConfigurationException {
+ m_factory.updated(arg0, arg1);
+
+ }
+
+ public String[] getLocales() {
+ return null;
+ }
+
+ public ObjectClassDefinition getObjectClassDefinition(String id,
+ String loc) {
+ return new ObjectClassDefinitionImpl(m_factory.getComponentDescription());
+ }
+
+}
Property changes on: trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/Factory2MetatypeBridge.java
___________________________________________________________________
Added: svn:mergeinfo
+
Deleted: trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/MetatypeBridge.java
===================================================================
--- trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/MetatypeBridge.java 2009-04-20 09:15:10 UTC (rev 65)
+++ trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/MetatypeBridge.java 2009-04-20 15:23:43 UTC (rev 66)
@@ -1,74 +0,0 @@
-package net.sourceforge.ipojo_toolbox.utils.metatype_bridge;
-
-import java.util.Collection;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Properties;
-
-import org.apache.felix.ipojo.Factory;
-import org.apache.felix.ipojo.InstanceManager;
-import org.osgi.framework.Bundle;
-
-/**
- * Creates on the fly ManagedServiceFactory implementing MetatypeProvider.
- * The created MSF just delegates calls on the wrapped one.
- */
-public class MetatypeBridge {
-
- /**
- * Store created wrapper per iPOJO Factories.
- */
- private Map/*Factory, ComponentInstance<MetatypeBundleBridge>*/ m_bridges = new HashMap();
-
- /**
- * Wrapper Factory
- */
- private Factory m_wrapperFactory; // injected (only valid factories)
-
- public synchronized void bindFactory(Factory factory) {
- Bundle bundle = factory.getComponentDescription().getBundleContext().getBundle();
- InstanceManager instance = (InstanceManager) m_bridges.get(factory);
- if (instance == null) {
- // Create a new instance for this factory
- Dictionary prop = new Properties();
- prop.put("bundle.id", new Long(bundle.getBundleId()));
- prop.put("factory", factory);
- prop.put("factory.name", factory.getName());
- prop.put("service.pid", factory.getName()+ "-WRAPPER");
-
- try {
- instance = (InstanceManager) m_wrapperFactory.createComponentInstance(prop);
- m_bridges.put(factory, instance);
- } catch (Exception e) {
- System.out.println("ERROR : Cannot create a bridge instance : "
- + e.getMessage());
- e.printStackTrace();
- return;
- }
- }
- }
-
- public synchronized void unbindFactory(Factory factory) {
- InstanceManager instance = (InstanceManager) m_bridges.remove(factory);
- if (instance == null) {
- // Ignore ...
- return;
- } else {
- instance.dispose();
- }
-
- }
-
- public void stop() {
- // Cleanup
- Collection instances = m_bridges.values();
- Iterator it = instances.iterator();
- while (it.hasNext()) {
- ((InstanceManager) it.next()).dispose();
- }
- m_bridges.clear();
- }
-
-}
Copied: trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/MetatypeBridgeManager.java (from rev 65, trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/MetatypeBridge.java)
===================================================================
--- trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/MetatypeBridgeManager.java (rev 0)
+++ trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/MetatypeBridgeManager.java 2009-04-20 15:23:43 UTC (rev 66)
@@ -0,0 +1,74 @@
+package net.sourceforge.ipojo_toolbox.utils.metatype_bridge;
+
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.felix.ipojo.Factory;
+import org.apache.felix.ipojo.InstanceManager;
+import org.osgi.framework.Bundle;
+
+/**
+ * Creates on the fly ManagedServiceFactory implementing MetatypeProvider.
+ * The created MSF just delegates calls on the wrapped one.
+ */
+public class MetatypeBridgeManager {
+
+ /**
+ * Store created wrapper per iPOJO Factories.
+ */
+ private Map/*Factory, ComponentInstance<MetatypeBundleBridge>*/ m_bridges = new HashMap();
+
+ /**
+ * Wrapper Factory
+ */
+ private Factory m_wrapperFactory; // injected (only valid factories)
+
+ public synchronized void bindFactory(Factory factory) {
+ Bundle bundle = factory.getComponentDescription().getBundleContext().getBundle();
+ InstanceManager instance = (InstanceManager) m_bridges.get(factory);
+ if (instance == null) {
+ // Create a new instance for this factory
+ Dictionary prop = new Properties();
+ prop.put("bundle.id", new Long(bundle.getBundleId()));
+ prop.put("factory", factory);
+ prop.put("factory.name", factory.getName());
+ prop.put("service.pid", factory.getName()+ "-WRAPPER");
+
+ try {
+ instance = (InstanceManager) m_wrapperFactory.createComponentInstance(prop);
+ m_bridges.put(factory, instance);
+ } catch (Exception e) {
+ System.out.println("ERROR : Cannot create a bridge instance : "
+ + e.getMessage());
+ e.printStackTrace();
+ return;
+ }
+ }
+ }
+
+ public synchronized void unbindFactory(Factory factory) {
+ InstanceManager instance = (InstanceManager) m_bridges.remove(factory);
+ if (instance == null) {
+ // Ignore ...
+ return;
+ } else {
+ instance.dispose();
+ }
+
+ }
+
+ public void stop() {
+ // Cleanup
+ Collection instances = m_bridges.values();
+ Iterator it = instances.iterator();
+ while (it.hasNext()) {
+ ((InstanceManager) it.next()).dispose();
+ }
+ m_bridges.clear();
+ }
+
+}
Property changes on: trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/MetatypeBridgeManager.java
___________________________________________________________________
Added: svn:mergeinfo
+
Deleted: trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/MetatypeFactoryWrapper.java
===================================================================
--- trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/MetatypeFactoryWrapper.java 2009-04-20 09:15:10 UTC (rev 65)
+++ trunk/utils/ipojo-metatype-bridge/src/main/java/net/sourceforge/ipojo_toolbox/utils/metatype_bridge/MetatypeFactoryWrapper.java 2009-04-20 15:23:43 UTC (rev 66)
@@ -1,229 +0,0 @@
-package net.sourceforge.ipojo_toolbox.utils.metatype_bridge;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.List;
-
-import org.apache.felix.ipojo.IPojoFactory;
-import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
-import org.apache.felix.ipojo.architecture.PropertyDescription;
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedServiceFactory;
-import org.osgi.service.metatype.AttributeDefinition;
-import org.osgi.service.metatype.MetaTypeProvider;
-import org.osgi.service.metatype.ObjectClassDefinition;
-
-/**
- * ManagedServiceFactory wrapper.
- * This class delegates call to the wrapped managed service factory.
- * However, it provides a Metatype description for the factory configurations.
- */
-public class MetatypeFactoryWrapper implements MetaTypeProvider, ManagedServiceFactory {
-
- /**
- * Wrapped Factory.
- */
- private IPojoFactory m_factory; //Injected
-
- private class ObjectClassDefinitionImpl implements ObjectClassDefinition {
-
- private ComponentTypeDescription m_description;
-
- List m_attributes = new ArrayList();
-
- public ObjectClassDefinitionImpl(ComponentTypeDescription desc) {
- m_description = desc;
- PropertyDescription[] props = desc.getProperties();
- for (int i = 0; i < props.length; i++) {
- m_attributes.add(new AttributeDefinitionImpl(props[i], m_description.getName()));
- }
- }
-
- public AttributeDefinition[] getAttributeDefinitions(int filter) {
- List list = new ArrayList();
- switch(filter) {
- case ObjectClassDefinition.OPTIONAL :
- for (int i = 0; i < m_attributes.size(); i++) {
- AttributeDefinitionImpl att = (AttributeDefinitionImpl) m_attributes.get(i);
- if (! att.m_isImmutable && ! att.m_isMandatory) {
- list.add(att);
- }
- }
- break;
- case ObjectClassDefinition.REQUIRED:
- for (int i = 0; i < m_attributes.size(); i++) {
- AttributeDefinitionImpl att = (AttributeDefinitionImpl) m_attributes.get(i);
- if (! att.m_isImmutable && att.m_isMandatory) {
- list.add(att);
- }
- }
- break;
- default :
- for (int i = 0; i < m_attributes.size(); i++) {
- AttributeDefinitionImpl att = (AttributeDefinitionImpl) m_attributes.get(i);
- if (! att.m_isImmutable) {
- list.add(att);
- }
- }
- }
- return (AttributeDefinition[]) list.toArray(new AttributeDefinition[list.size()]);
- }
-
- public String getDescription() {
- return m_description.getName();
- }
-
- public String getID() {
- return m_description.getName();
- }
-
- public InputStream getIcon(int arg0) throws IOException {
- return null;
- }
-
- public String getName() {
- return m_description.getName();
- }
-
- }
-
- private class AttributeDefinitionImpl implements AttributeDefinition {
-
- private PropertyDescription m_desc;
- private String m_typeName;
-
- private int m_type;
- private int m_cardinality;
- private boolean m_isMandatory;
- private boolean m_isImmutable;
-
- public AttributeDefinitionImpl(PropertyDescription desc, String typeName) {
- m_desc = desc;
- m_typeName = typeName;
- m_isMandatory = desc.isMandatory();
- m_isImmutable = desc.isImmutable();
- String type = m_desc.getType();
- String internType = null;
- if (type.endsWith("[]")) {
- // Array
- m_cardinality = Integer.MAX_VALUE;
- int index = type.indexOf('[');
- internType = type.substring(0, index);
- } else if (type.equals(java.util.Vector.class.getName())) {
- m_cardinality = Integer.MIN_VALUE;
- internType = String.class.getName();
- } else {
- m_cardinality = 0;
- internType = type;
- }
- m_type = getTypeByInternType(internType);
- }
-
- private int getTypeByInternType(String internType) {
- //STRING,LONG,INTEGER, CHAR,BYTE,DOUBLE,FLOAT, BOOLEAN
-
- if (internType.equalsIgnoreCase("string") || internType.equals(String.class.getName())) {
- return AttributeDefinition.STRING;
- }
- if (internType.equals("boolean")) {
- return AttributeDefinition.BOOLEAN;
- }
- if (internType.equals("float")) {
- return AttributeDefinition.FLOAT;
- }
- if (internType.equals("double")) {
- return AttributeDefinition.DOUBLE;
- }
- if (internType.equals("byte")) {
- return AttributeDefinition.BYTE;
- }
- if (internType.equals("char")) {
- return AttributeDefinition.CHARACTER;
- }
- if (internType.equals("int")) {
- return AttributeDefinition.INTEGER;
- }
- if (internType.equals("long")) {
- return AttributeDefinition.LONG;
- }
- System.out.println("WARNING : Cannot determine the type of " + internType);
- return -1;
- }
-
- public int getCardinality() {
- return m_cardinality;
- }
-
- public String[] getDefaultValue() {
- if (m_desc.getValue() != null) {
- if (getCardinality() == 0) {
- return new String[] { m_desc.getValue() };
- } else if (m_cardinality > 0) {
- return org.apache.felix.ipojo.parser.ParseUtils.parseArrays(m_desc.getValue());
- } else if (m_cardinality < 0) {
- //TODO handle vector case
- return new String[] { m_desc.getValue() };
- }
- }
- return null;
- }
-
- public String getDescription() {
- return m_desc.getName();
- }
-
- public String getID() {
- return m_typeName + "-" + m_desc.getName();
-
- }
-
- public String getName() {
- return m_desc.getName();
- }
-
- public String[] getOptionLabels() {
- return null;
- }
-
- public String[] getOptionValues() {
- return null;
- }
-
- public int getType() {
- return m_type;
- }
-
- public String validate(String arg0) {
- return null; // No validation
- }
-
-
-
- }
-
- public void deleted(String arg0) {
- m_factory.deleted(arg0);
- }
-
- public String getName() {
- return m_factory.getName();
- }
-
- public void updated(String arg0, Dictionary arg1)
- throws ConfigurationException {
- m_factory.updated(arg0, arg1);
-
- }
-
- public String[] getLocales() {
- return null;
- }
-
- public ObjectClassDefinition getObjectClassDefinition(String id,
- String loc) {
- return new ObjectClassDefinitionImpl(m_factory.getComponentDescription());
- }
-
-}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|