From: <mol...@us...> - 2008-02-01 10:59:44
|
Revision: 592 http://openutils.svn.sourceforge.net/openutils/?rev=592&view=rev Author: molaschi Date: 2008-02-01 02:59:48 -0800 (Fri, 01 Feb 2008) Log Message: ----------- [maven-release-plugin] copy for tag openutils-bshd5-2.0.1 Added Paths: ----------- tags/openutils-bshd5-2.0.1/ tags/openutils-bshd5-2.0.1/pom.xml tags/openutils-bshd5-2.0.1/src/main/java/it/openutils/hibernate/example/EnhancedExample.java Removed Paths: ------------- tags/openutils-bshd5-2.0.1/pom.xml tags/openutils-bshd5-2.0.1/src/main/java/it/openutils/hibernate/example/EnhancedExample.java Copied: tags/openutils-bshd5-2.0.1 (from rev 589, trunk/openutils-bshd5) Deleted: tags/openutils-bshd5-2.0.1/pom.xml =================================================================== --- trunk/openutils-bshd5/pom.xml 2008-01-31 22:35:00 UTC (rev 589) +++ tags/openutils-bshd5-2.0.1/pom.xml 2008-02-01 10:59:48 UTC (rev 592) @@ -1,108 +0,0 @@ -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>net.sourceforge.openutils</groupId> - <artifactId>openutils</artifactId> - <version>7</version> - <relativePath>..</relativePath> - </parent> - <artifactId>openutils-bshd5</artifactId> - <name>openutils base Spring-Hibernate DAO for java 5.0</name> - <version>2.0.1-SNAPSHOT</version> - <description>openutils base Spring-Hibernate DAO for java 5.0</description> - <dependencies> - <dependency> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-log4j12</artifactId> - <version>1.4.3</version> - </dependency> - <dependency> - <groupId>org.slf4j</groupId> - <artifactId>jcl104-over-slf4j</artifactId> - <version>1.4.3</version> - </dependency> - <dependency> - <groupId>org.springframework</groupId> - <artifactId>spring-jdbc</artifactId> - <version>${spring.version}</version> - <exclusions> - <exclusion> - <groupId>commons-logging</groupId> - <artifactId>commons-logging</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>org.springframework</groupId> - <artifactId>spring-beans</artifactId> - <version>${spring.version}</version> - <exclusions> - <exclusion> - <groupId>commons-logging</groupId> - <artifactId>commons-logging</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>org.springframework</groupId> - <artifactId>spring-orm</artifactId> - <version>${spring.version}</version> - <exclusions> - <exclusion> - <groupId>commons-logging</groupId> - <artifactId>commons-logging</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>org.springframework</groupId> - <artifactId>spring-aop</artifactId> - <version>${spring.version}</version> - <exclusions> - <exclusion> - <groupId>commons-logging</groupId> - <artifactId>commons-logging</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>org.hibernate</groupId> - <artifactId>hibernate</artifactId> - <version>3.2.1.ga</version> - <exclusions> - <exclusion> - <groupId>commons-logging</groupId> - <artifactId>commons-logging</artifactId> - </exclusion> - <exclusion> - <groupId>cglib</groupId> - <artifactId>cglib</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>cglib</groupId> - <artifactId>cglib-nodep</artifactId> - <version>2.1_3</version> - </dependency> - <dependency> - <groupId>commons-beanutils</groupId> - <artifactId>commons-beanutils</artifactId> - <version>1.7.0</version> - <exclusions> - <exclusion> - <groupId>commons-logging</groupId> - <artifactId>commons-logging</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>commons-lang</groupId> - <artifactId>commons-lang</artifactId> - <version>2.3</version> - </dependency> - </dependencies> - <properties> - <spring.version>2.5.1</spring.version> - </properties> -</project> \ No newline at end of file Copied: tags/openutils-bshd5-2.0.1/pom.xml (from rev 591, trunk/openutils-bshd5/pom.xml) =================================================================== --- tags/openutils-bshd5-2.0.1/pom.xml (rev 0) +++ tags/openutils-bshd5-2.0.1/pom.xml 2008-02-01 10:59:48 UTC (rev 592) @@ -0,0 +1,114 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>net.sourceforge.openutils</groupId> + <artifactId>openutils</artifactId> + <version>7</version> + <relativePath>..</relativePath> + </parent> + <artifactId>openutils-bshd5</artifactId> + <name>openutils base Spring-Hibernate DAO for java 5.0</name> + <version>2.0.1</version> + <description>openutils base Spring-Hibernate DAO for java 5.0</description> + <dependencies> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <version>1.4.3</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jcl104-over-slf4j</artifactId> + <version>1.4.3</version> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-jdbc</artifactId> + <version>${spring.version}</version> + <exclusions> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-beans</artifactId> + <version>${spring.version}</version> + <exclusions> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-orm</artifactId> + <version>${spring.version}</version> + <exclusions> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-aop</artifactId> + <version>${spring.version}</version> + <exclusions> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.hibernate</groupId> + <artifactId>hibernate</artifactId> + <version>3.2.1.ga</version> + <exclusions> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + <exclusion> + <groupId>cglib</groupId> + <artifactId>cglib</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>cglib</groupId> + <artifactId>cglib-nodep</artifactId> + <version>2.1_3</version> + </dependency> + <dependency> + <groupId>commons-beanutils</groupId> + <artifactId>commons-beanutils</artifactId> + <version>1.7.0</version> + <exclusions> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>2.3</version> + </dependency> + </dependencies> + <properties> + <spring.version>2.5.1</spring.version> + </properties> + + <scm> + <connection>scm:svn:https://openutils.svn.sourceforge.net/svnroot/openutils/tags/openutils-bshd5-2.0.1</connection> + <developerConnection>scm:svn:https://openutils.svn.sourceforge.net/svnroot/openutils/tags/openutils-bshd5-2.0.1</developerConnection> + <url>http://openutils.svn.sourceforge.net/viewcvs.cgi/openutils/tags/openutils-bshd5-2.0.1</url> + </scm> +</project> \ No newline at end of file Deleted: tags/openutils-bshd5-2.0.1/src/main/java/it/openutils/hibernate/example/EnhancedExample.java =================================================================== --- trunk/openutils-bshd5/src/main/java/it/openutils/hibernate/example/EnhancedExample.java 2008-01-31 22:35:00 UTC (rev 589) +++ tags/openutils-bshd5-2.0.1/src/main/java/it/openutils/hibernate/example/EnhancedExample.java 2008-02-01 10:59:48 UTC (rev 592) @@ -1,305 +0,0 @@ -package it.openutils.hibernate.example; - -import java.lang.reflect.InvocationTargetException; -import java.math.BigDecimal; -import java.sql.Timestamp; -import java.util.Calendar; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.beanutils.PropertyUtils; -import org.apache.commons.lang.ClassUtils; -import org.apache.commons.lang.StringUtils; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.dao.DataRetrievalFailureException; - - -/** - * @author Fabrizio Giustina - * @version $Id: $ - */ -public final class EnhancedExample -{ - - /** - * Logger. - */ - private static Logger log = LoggerFactory.getLogger(EnhancedExample.class); - - private Map<String, FilterMetadata> metadata; - - private EnhancedExample(Criteria crit, Object filter, Map<String, FilterMetadata> metadata) - { - this.metadata = metadata == null ? new HashMap<String, FilterMetadata>(0) : metadata; - fillCriteria(null, crit, filter); - } - - /** - * Fills a criteria object calling addCondition() for any non-null property or for any component in collections. - * @param crit Criteria - * @param filter javabean which will be analyzed for non-null properties - * @param metadata Map of property names - filter metadata - * @throws HibernateException exception while building the criteria - */ - public static void create(Criteria crit, Object filter, Map<String, FilterMetadata> metadata) - throws HibernateException - { - new EnhancedExample(crit, filter, metadata); - } - - /** - * Adds contitions to an existing criteria or create sub-criteria for associations. - * @param crit Criteria - * @param propertyName property name in parent bean - * @param value property value - * @throws HibernateException exception while building the criteria - */ - private void addCondition(Criteria crit, String propertyName, Object value, Object parentObject) - throws HibernateException - { - - String simplePropertyName = StringUtils.contains(propertyName, ".") ? StringUtils.substringAfterLast( - propertyName, - ".") : propertyName; - - if (isSimpleType(value) || value.getClass().isEnum()) - { - - // don't filter on empty strings! - if (value instanceof String && StringUtils.isBlank((String) value)) - { - return; - } - - FilterMetadata fmd = metadata.get(propertyName); - - if (fmd == null) - { - fmd = FilterMetadata.EQUAL; - } - - fmd.createFilter(crit, simplePropertyName, value); - - } - else - { - if (containsSomething(value)) - { - // @todo handle multiple associations in lists? - // see http://opensource2.atlassian.com/projects/hibernate/browse/HHH-879 - if ((value instanceof Set || value instanceof List) && !((Collection< ? >) value).isEmpty()) - { - // collection: the new criteria has already been created, now we only nee to analize content - - for (Object element : ((Collection< ? >) value)) - { - - log.debug("crit.createCriteria({})", simplePropertyName); - Criteria childrenCriteria = crit.createCriteria(simplePropertyName); - fillCriteria(propertyName, childrenCriteria, element); - } - } - else if ((value instanceof Map) && !((Map< ? , ? >) value).isEmpty()) - { - FilterMetadata fmd = metadata.get(propertyName); - - if (fmd != null) - { - fmd.createFilter(crit, simplePropertyName, value); - } - else - { - log.warn( - "Maps are not handled without a FilterMetadata. Property is {} and value is {}.", - propertyName, - value); - } - } - else - { - log.debug("crit.createCriteria({})", simplePropertyName); - Criteria childrenCriteria = crit.createCriteria(simplePropertyName); - fillCriteria(propertyName, childrenCriteria, value); - } - } - } - } - - /** - * Check if the bean contains at least a valid property. - * @param bean javabean - * @return <code>true</code> if the bean contains at least a valid property - */ - @SuppressWarnings("unchecked") - private boolean containsSomething(Object bean) - { - - if (bean == null) - { - return false; - } - if (isSimpleType(bean)) - { - return true; - } - - if (bean instanceof Collection) - { - - Collection< ? > coll = ((Collection< ? >) bean); - if (coll.isEmpty()) - { - return false; - } - - if (containsSomething(coll.iterator().next())) - { - return true; - } - } - else if (bean instanceof Map) - { - Map< ? , ? > coll = ((Map< ? , ? >) bean); - if (coll.isEmpty()) - { - return false; - } - - if (containsSomething(coll.values().iterator().next())) - { - return true; - } - } - - Map<String, Object> properties; - try - { - properties = PropertyUtils.describe(bean); - } - catch (Throwable e) - { - if (e instanceof InvocationTargetException) - { - e = ((InvocationTargetException) e).getTargetException(); - } - - log.error("Unable to build filter, PropertyUtils.describe throws an exception while analizing class " - + ClassUtils.getShortClassName(bean, "NULL"), e); - return false; - } - - for (Map.Entry<String, Object> property : properties.entrySet()) - { - - if (!PropertyUtils.isWriteable(bean, property.getKey())) - { - // skip readonly properties - continue; - } - - Object propertyValue = property.getValue(); - if (propertyValue == null) - { - continue; - } - - if (isSimpleType(propertyValue) || containsSomething(propertyValue)) - { - return true; - } - } - - return false; - } - - /** - * Fills a criteria object calling addCondition() for any non-null property or for any component in collections. - * @param crit Criteria - * @param filter javabean which will be analyzed for non-null properties - * @throws HibernateException exception while building the criteria - */ - @SuppressWarnings("unchecked") - private void fillCriteria(String parentPropertyName, Criteria crit, Object filter) throws HibernateException - { - if ((filter instanceof Set || filter instanceof List) && !((Collection< ? >) filter).isEmpty()) - { - // collection: the new criteria has already been created, now we only need to analize content - for (Object element : ((Collection< ? >) filter)) - { - fillCriteria(parentPropertyName, crit, element); - } - } - - Map<String, Object> properties; - try - { - properties = PropertyUtils.describe(filter); - } - catch (Throwable e) - { - if (e instanceof InvocationTargetException) - { - e = ((InvocationTargetException) e).getTargetException(); - } - - throw new DataRetrievalFailureException( - "Unable to build filter, PropertyUtils.describe throws an exception while analizing class " - + ClassUtils.getShortClassName(filter, "NULL") - + ":" - + e.getClass(), - e); - } - - Iterator<String> iterator = properties.keySet().iterator(); - while (iterator.hasNext()) - { - String propertyName = iterator.next(); - - Object value = properties.get(propertyName); - - // add only non-null values, ignore read-only properties - if (value != null && PropertyUtils.isWriteable(filter, propertyName)) - { - String composedPropertyName = (parentPropertyName == null) ? propertyName : parentPropertyName - + "." - + propertyName; - addCondition(crit, composedPropertyName, value, filter); - } - } - } - - /** - * Check if the given object is a simple java type - * @param object object to check - * @return <code>true</code>if the given object is a simple type - */ - private boolean isSimpleType(Object object) - { - - Class< ? extends Object> objClass = object.getClass(); - - return objClass.isPrimitive() - || objClass.equals(Integer.class) - || objClass.equals(Long.class) - || objClass.equals(Short.class) - || objClass.equals(Boolean.class) - || objClass.equals(String.class) - || objClass.equals(Double.class) - || objClass.equals(Float.class) - || objClass.equals(Date.class) - || objClass.equals(Byte.class) - || objClass.equals(BigDecimal.class) - || objClass.equals(Timestamp.class) - || objClass.equals(Character.class) - || Calendar.class.isAssignableFrom(objClass); - } - -} Copied: tags/openutils-bshd5-2.0.1/src/main/java/it/openutils/hibernate/example/EnhancedExample.java (from rev 590, trunk/openutils-bshd5/src/main/java/it/openutils/hibernate/example/EnhancedExample.java) =================================================================== --- tags/openutils-bshd5-2.0.1/src/main/java/it/openutils/hibernate/example/EnhancedExample.java (rev 0) +++ tags/openutils-bshd5-2.0.1/src/main/java/it/openutils/hibernate/example/EnhancedExample.java 2008-02-01 10:59:48 UTC (rev 592) @@ -0,0 +1,306 @@ +package it.openutils.hibernate.example; + +import java.lang.reflect.InvocationTargetException; +import java.math.BigDecimal; +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.lang.ClassUtils; +import org.apache.commons.lang.StringUtils; +import org.hibernate.Criteria; +import org.hibernate.HibernateException; +import org.hibernate.mapping.Value; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.DataRetrievalFailureException; + + +/** + * @author Fabrizio Giustina + * @version $Id: $ + */ +public final class EnhancedExample +{ + + /** + * Logger. + */ + private static Logger log = LoggerFactory.getLogger(EnhancedExample.class); + + private Map<String, FilterMetadata> metadata; + + private EnhancedExample(Criteria crit, Object filter, Map<String, FilterMetadata> metadata) + { + this.metadata = metadata == null ? new HashMap<String, FilterMetadata>(0) : metadata; + fillCriteria(null, crit, filter); + } + + /** + * Fills a criteria object calling addCondition() for any non-null property or for any component in collections. + * @param crit Criteria + * @param filter javabean which will be analyzed for non-null properties + * @param metadata Map of property names - filter metadata + * @throws HibernateException exception while building the criteria + */ + public static void create(Criteria crit, Object filter, Map<String, FilterMetadata> metadata) + throws HibernateException + { + new EnhancedExample(crit, filter, metadata); + } + + /** + * Adds contitions to an existing criteria or create sub-criteria for associations. + * @param crit Criteria + * @param propertyName property name in parent bean + * @param value property value + * @throws HibernateException exception while building the criteria + */ + private void addCondition(Criteria crit, String propertyName, Object value, Object parentObject) + throws HibernateException + { + + String simplePropertyName = StringUtils.contains(propertyName, ".") ? StringUtils.substringAfterLast( + propertyName, + ".") : propertyName; + + if (isSimpleType(value) || value.getClass().isEnum()) + { + + // don't filter on empty strings! + if (value instanceof String && StringUtils.isBlank((String) value)) + { + return; + } + + FilterMetadata fmd = metadata.get(propertyName); + + if (fmd == null) + { + fmd = FilterMetadata.EQUAL; + } + + fmd.createFilter(crit, simplePropertyName, value); + + } + else + { + if (containsSomething(value)) + { + // @todo handle multiple associations in lists? + // see http://opensource2.atlassian.com/projects/hibernate/browse/HHH-879 + if ((value instanceof Set || value instanceof List) && !((Collection< ? >) value).isEmpty()) + { + // collection: the new criteria has already been created, now we only nee to analize content + + for (Object element : ((Collection< ? >) value)) + { + + log.debug("crit.createCriteria({})", simplePropertyName); + Criteria childrenCriteria = crit.createCriteria(simplePropertyName); + fillCriteria(propertyName, childrenCriteria, element); + } + } + else if ((value instanceof Map) && !((Map< ? , ? >) value).isEmpty()) + { + FilterMetadata fmd = metadata.get(propertyName); + + if (fmd != null) + { + fmd.createFilter(crit, simplePropertyName, value); + } + else + { + log.warn( + "Maps are not handled without a FilterMetadata. Property is {} and value is {}.", + propertyName, + value); + } + } + else + { + log.debug("crit.createCriteria({})", simplePropertyName); + Criteria childrenCriteria = crit.createCriteria(simplePropertyName); + fillCriteria(propertyName, childrenCriteria, value); + } + } + } + } + + /** + * Check if the bean contains at least a valid property. + * @param bean javabean + * @return <code>true</code> if the bean contains at least a valid property + */ + @SuppressWarnings("unchecked") + private boolean containsSomething(Object bean) + { + + if (bean == null) + { + return false; + } + if (isSimpleType(bean) || bean.getClass().isEnum()) + { + return true; + } + + if (bean instanceof Collection) + { + + Collection< ? > coll = ((Collection< ? >) bean); + if (coll.isEmpty()) + { + return false; + } + + if (containsSomething(coll.iterator().next())) + { + return true; + } + } + else if (bean instanceof Map) + { + Map< ? , ? > coll = ((Map< ? , ? >) bean); + if (coll.isEmpty()) + { + return false; + } + + if (containsSomething(coll.values().iterator().next())) + { + return true; + } + } + + Map<String, Object> properties; + try + { + properties = PropertyUtils.describe(bean); + } + catch (Throwable e) + { + if (e instanceof InvocationTargetException) + { + e = ((InvocationTargetException) e).getTargetException(); + } + + log.error("Unable to build filter, PropertyUtils.describe throws an exception while analizing class " + + ClassUtils.getShortClassName(bean, "NULL"), e); + return false; + } + + for (Map.Entry<String, Object> property : properties.entrySet()) + { + + if (!PropertyUtils.isWriteable(bean, property.getKey())) + { + // skip readonly properties + continue; + } + + Object propertyValue = property.getValue(); + if (propertyValue == null) + { + continue; + } + + if (isSimpleType(propertyValue) || containsSomething(propertyValue)) + { + return true; + } + } + + return false; + } + + /** + * Fills a criteria object calling addCondition() for any non-null property or for any component in collections. + * @param crit Criteria + * @param filter javabean which will be analyzed for non-null properties + * @throws HibernateException exception while building the criteria + */ + @SuppressWarnings("unchecked") + private void fillCriteria(String parentPropertyName, Criteria crit, Object filter) throws HibernateException + { + if ((filter instanceof Set || filter instanceof List) && !((Collection< ? >) filter).isEmpty()) + { + // collection: the new criteria has already been created, now we only need to analize content + for (Object element : ((Collection< ? >) filter)) + { + fillCriteria(parentPropertyName, crit, element); + } + } + + Map<String, Object> properties; + try + { + properties = PropertyUtils.describe(filter); + } + catch (Throwable e) + { + if (e instanceof InvocationTargetException) + { + e = ((InvocationTargetException) e).getTargetException(); + } + + throw new DataRetrievalFailureException( + "Unable to build filter, PropertyUtils.describe throws an exception while analizing class " + + ClassUtils.getShortClassName(filter, "NULL") + + ":" + + e.getClass(), + e); + } + + Iterator<String> iterator = properties.keySet().iterator(); + while (iterator.hasNext()) + { + String propertyName = iterator.next(); + + Object value = properties.get(propertyName); + + // add only non-null values, ignore read-only properties + if (value != null && PropertyUtils.isWriteable(filter, propertyName)) + { + String composedPropertyName = (parentPropertyName == null) ? propertyName : parentPropertyName + + "." + + propertyName; + addCondition(crit, composedPropertyName, value, filter); + } + } + } + + /** + * Check if the given object is a simple java type + * @param object object to check + * @return <code>true</code>if the given object is a simple type + */ + private boolean isSimpleType(Object object) + { + + Class< ? extends Object> objClass = object.getClass(); + + return objClass.isPrimitive() + || objClass.equals(Integer.class) + || objClass.equals(Long.class) + || objClass.equals(Short.class) + || objClass.equals(Boolean.class) + || objClass.equals(String.class) + || objClass.equals(Double.class) + || objClass.equals(Float.class) + || objClass.equals(Date.class) + || objClass.equals(Byte.class) + || objClass.equals(BigDecimal.class) + || objClass.equals(Timestamp.class) + || objClass.equals(Character.class) + || Calendar.class.isAssignableFrom(objClass); + } + +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |