You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@turbine.apache.org by he...@apache.org on 2003/04/08 13:19:51 UTC
cvs commit: jakarta-turbine-2/src/java/org/apache/turbine/util/security SecuritySet.java GroupSet.java PermissionSet.java RoleSet.java
henning 2003/04/08 04:19:51
Modified: src/java/org/apache/turbine/util/security GroupSet.java
PermissionSet.java RoleSet.java
Added: src/java/org/apache/turbine/util/security SecuritySet.java
Log:
- Factor out the common code of the various Sets.
- Turn the set itself into a map so lookup run much faster than they do now.
- Clean up the code.
- Prepare the slots for the id lookup methods.
Revision Changes Path
1.8 +54 -80 jakarta-turbine-2/src/java/org/apache/turbine/util/security/GroupSet.java
Index: GroupSet.java
===================================================================
RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/util/security/GroupSet.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- GroupSet.java 9 Mar 2003 02:54:13 -0000 1.7
+++ GroupSet.java 8 Apr 2003 11:19:51 -0000 1.8
@@ -54,49 +54,47 @@
* <http://www.apache.org/>.
*/
-import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
-import java.util.TreeSet;
+
+import org.apache.commons.lang.StringUtils;
import org.apache.turbine.om.security.Group;
/**
* This class represents a set of Groups. It's useful for building
- * administration UI. It wraps a TreeSet object to enforce that only
+ * administration UI. It enforces that only
* Group objects are allowed in the set and only relevant methods
- * are available. TreeSet's contain only unique Objects (no
- * duplicates).
+ * are available.
*
* @author <a href="mailto:john.mcnally@clearink.com">John D. McNally</a>
* @author <a href="mailto:bmclaugh@algx.net">Brett McLaughlin</a>
+ * @author <a href="mailto:marco@intermeta.de">Marco Knüttel</a>
* @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
* @version $Id$
*/
-public class GroupSet implements Serializable
+public class GroupSet
+ extends SecuritySet
{
- /** Set to hold the Group Set */
- private TreeSet set;
-
/**
* Constructs an empty GroupSet
*/
public GroupSet()
{
- set = new TreeSet();
+ super();
}
/**
* Constructs a new GroupSet with specified contents.
*
* If the given collection contains multiple objects that are
- * identical WRT equals() method, some objects will be overwriten.
+ * identical WRT equals() method, some objects will be overwritten.
*
* @param groups A collection of groups to be contained in the set.
*/
public GroupSet(Collection groups)
{
- this();
+ super();
add(groups);
}
@@ -109,7 +107,9 @@
*/
public boolean add(Group group)
{
- return set.add((Object) group);
+ boolean res = contains(group);
+ nameMap.put(group.getName(), group);
+ return res;
}
/**
@@ -122,7 +122,13 @@
*/
public boolean add(Collection groups)
{
- return set.addAll(groups);
+ boolean res = false;
+ for (Iterator it = groups.iterator(); it.hasNext();)
+ {
+ Group g = (Group) it.next();
+ res |= add(g);
+ }
+ return res;
}
/**
@@ -135,7 +141,13 @@
*/
public boolean add(GroupSet groupSet)
{
- return set.addAll(groupSet.set);
+ boolean res = false;
+ for( Iterator it = groupSet.iterator(); it.hasNext();)
+ {
+ Group g = (Group) it.next();
+ res |= add(g);
+ }
+ return res;
}
/**
@@ -147,15 +159,9 @@
*/
public boolean remove(Group group)
{
- return set.remove((Object) group);
- }
-
- /**
- * Removes all Groups from this GroupSet.
- */
- public void clear()
- {
- set.clear();
+ boolean res = contains(group);
+ nameMap.remove(group.getName());
+ return res;
}
/**
@@ -167,29 +173,7 @@
*/
public boolean contains(Group group)
{
- return set.contains((Object) group);
- }
-
- /**
- * Compares by name a Group with the Groups contained in
- * this GroupSet.
- *
- * @param groupName Name of Group.
- * @return True if argument matched a Group in this
- * GroupSet; false if no match.
- */
- public boolean contains(String groupName)
- {
- Iterator iter = set.iterator();
- while (iter.hasNext())
- {
- Group group = (Group) iter.next();
- if (groupName != null && groupName.equals(group.getName()))
- {
- return true;
- }
- }
- return false;
+ return nameMap.containsValue((Object) group);
}
/**
@@ -202,16 +186,8 @@
*/
public Group getGroup(String groupName)
{
- Iterator iter = set.iterator();
- while (iter.hasNext())
- {
- Group group = (Group) iter.next();
- if (groupName != null && groupName.equals(group.getName()))
- {
- return group;
- }
- }
- return null;
+ return (StringUtils.isNotEmpty(groupName))
+ ? (Group) nameMap.get(groupName) : null;
}
/**
@@ -221,34 +197,32 @@
*/
public Group[] getGroupsArray()
{
- return (Group[]) set.toArray(new Group[0]);
+ return (Group[]) getSet().toArray(new Group[0]);
}
/**
- * @deprecated Use iterator() instead.
- */
- public Iterator elements()
- {
- return set.iterator();
- }
-
- /**
- * Returns an Iterator for Groups in this GroupSet.
+ * Print out a GroupSet as a String
*
- * @return An Iterator for this GroupSet
- */
- public Iterator iterator()
- {
- return set.iterator();
- }
-
- /**
- * Returns size (cardinality) of this set.
+ * @returns The Group Set as String
*
- * @return The cardinality of this GroupSet.
*/
- public int size()
+ public String toString()
{
- return set.size();
+ StringBuffer sb = new StringBuffer();
+ sb.append("GroupSet: ");
+
+ for(Iterator it = iterator(); it.hasNext();)
+ {
+ Group g = (Group) it.next();
+ sb.append('[');
+ sb.append(g.getName());
+ sb.append(']');
+ if (it.hasNext())
+ {
+ sb.append(", ");
+ }
+ }
+
+ return sb.toString();
}
}
1.8 +56 -85 jakarta-turbine-2/src/java/org/apache/turbine/util/security/PermissionSet.java
Index: PermissionSet.java
===================================================================
RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/util/security/PermissionSet.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- PermissionSet.java 9 Mar 2003 02:54:13 -0000 1.7
+++ PermissionSet.java 8 Apr 2003 11:19:51 -0000 1.8
@@ -54,51 +54,48 @@
* <http://www.apache.org/>.
*/
-import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
-import java.util.TreeSet;
+
+import org.apache.commons.lang.StringUtils;
import org.apache.turbine.om.security.Permission;
-import org.apache.turbine.om.security.SecurityObject;
/**
* This class represents a set of Permissions. It makes it easy to
* build a UI that would allow someone to add a group of Permissions
- * to a Role. It wraps a TreeSet object to enforce that only
+ * to a Role. It enforces that only
* Permission objects are allowed in the set and only relevant methods
- * are available. TreeSet's contain only unique Objects (no
- * duplicates).
+ * are available.
*
* @author <a href="mailto:john.mcnally@clearink.com">John D. McNally</a>
* @author <a href="mailto:bmclaugh@algx.net">Brett McLaughlin</a>
+ * @author <a href="mailto:marco@intermeta.de">Marco Knüttel</a>
* @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
* @version $Id$
*/
-public class PermissionSet implements Serializable
+public class PermissionSet
+ extends SecuritySet
{
- /** Set to hold the Permission Set */
- private TreeSet set;
-
/**
* Constructs an empty PermissionSet
*/
public PermissionSet()
{
- set = new TreeSet();
+ super();
}
/**
- * Constructs a new PermissionSet with specifed contents.
+ * Constructs a new PermissionSet with specified contents.
*
* If the given collection contains multiple objects that are
- * identical WRT equals() method, some objects will be overwriten.
+ * identical WRT equals() method, some objects will be overwritten.
*
* @param permissions A collection of permissions to be contained in the set.
*/
public PermissionSet(Collection permissions)
{
- this();
+ super();
add(permissions);
}
@@ -111,20 +108,28 @@
*/
public boolean add(Permission permission)
{
- return set.add((Object) permission);
+ boolean res = contains(permission);
+ nameMap.put(permission.getName(), permission);
+ return res;
}
/**
* Adds the Permissions in a Collection to this PermissionSet.
*
- * @param permissions A Permission.
+ * @param permissions A Collection of Permissions.
* @return True if this PermissionSet changed as a result; false
* if no change to this PermissionSet occurred (this PermissionSet
* already contained all members of the added PermissionSet).
*/
public boolean add(Collection permissions)
{
- return set.addAll(permissions);
+ boolean res = false;
+ for (Iterator it = permissions.iterator(); it.hasNext();)
+ {
+ Permission p = (Permission) it.next();
+ res |= add(p);
+ }
+ return res;
}
/**
@@ -138,7 +143,13 @@
*/
public boolean add(PermissionSet permissionSet)
{
- return set.addAll(permissionSet.set);
+ boolean res = false;
+ for( Iterator it = permissionSet.iterator(); it.hasNext();)
+ {
+ Permission p = (Permission) it.next();
+ res |= add(p);
+ }
+ return res;
}
/**
@@ -150,15 +161,9 @@
*/
public boolean remove(Permission permission)
{
- return set.remove((Object) permission);
- }
-
- /**
- * Removes all Permissions from this PermissionSet.
- */
- public void clear()
- {
- set.clear();
+ boolean res = contains(permission);
+ nameMap.remove(permission.getName());
+ return res;
}
/**
@@ -170,30 +175,7 @@
*/
public boolean contains(Permission permission)
{
- return set.contains((Object) permission);
- }
-
- /**
- * Returns a Permission with the given name, if it is contained in
- * this PermissionSet.
- *
- * @param permissionName Name of Permission.
- * @return True if argument matched a Permission in this
- * PermissionSet; false if no match.
- */
- public boolean contains(String permissionName)
- {
- Iterator iter = set.iterator();
- while (iter.hasNext())
- {
- Permission permission = (Permission) iter.next();
- if (permissionName != null &&
- permissionName.equals(((SecurityObject) permission).getName()))
- {
- return true;
- }
- }
- return false;
+ return nameMap.containsValue((Object) permission);
}
/**
@@ -206,17 +188,8 @@
*/
public Permission getPermission(String permissionName)
{
- Iterator iter = set.iterator();
- while (iter.hasNext())
- {
- Permission permission = (Permission) iter.next();
- if (permissionName != null &&
- permissionName.equals(((SecurityObject) permission).getName()))
- {
- return permission;
- }
- }
- return null;
+ return (StringUtils.isNotEmpty(permissionName))
+ ? (Permission) nameMap.get(permissionName) : null;
}
/**
@@ -226,34 +199,32 @@
*/
public Permission[] getPermissionsArray()
{
- return (Permission[]) set.toArray(new Permission[0]);
- }
-
- /**
- * @deprecated Use iterator() instead.
- */
- public Iterator elements()
- {
- return set.iterator();
+ return (Permission[]) getSet().toArray(new Permission[0]);
}
/**
- * Returns an Iterator for Groups in this GroupSet.
+ * Print out a PermissionSet as a String
*
- * @return An Iterator for this GroupSet
- */
- public Iterator iterator()
- {
- return set.iterator();
- }
-
- /**
- * Returns size (cardinality) of this set.
+ * @returns The Permission Set as String
*
- * @return The cardinality of this PermissionSet.
*/
- public int size()
+ public String toString()
{
- return set.size();
+ StringBuffer sb = new StringBuffer();
+ sb.append("PermissionSet: ");
+
+ for(Iterator it = iterator(); it.hasNext();)
+ {
+ Permission p = (Permission) it.next();
+ sb.append('[');
+ sb.append(p.getName());
+ sb.append(']');
+ if (it.hasNext())
+ {
+ sb.append(", ");
+ }
+ }
+
+ return sb.toString();
}
}
1.7 +66 -94 jakarta-turbine-2/src/java/org/apache/turbine/util/security/RoleSet.java
Index: RoleSet.java
===================================================================
RCS file: /home/cvs/jakarta-turbine-2/src/java/org/apache/turbine/util/security/RoleSet.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- RoleSet.java 9 Mar 2003 02:54:13 -0000 1.6
+++ RoleSet.java 8 Apr 2003 11:19:51 -0000 1.7
@@ -54,51 +54,47 @@
* <http://www.apache.org/>.
*/
-import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
-import java.util.TreeSet;
+
+import org.apache.commons.lang.StringUtils;
import org.apache.turbine.om.security.Role;
/**
* This class represents a set of Roles. It makes it easy to build a
- * UI that would allow someone to add a group of Roles to a User. It
- * wraps a TreeSet object to enforce that only Role objects are
+ * UI that would allow someone to add a group of Roles to a User.
+ * It enforces that only Role objects are
* allowed in the set and only relevant methods are available.
- * TreeSet's contain only unique Objects (no duplicates).
*
* @author <a href="mailto:john.mcnally@clearink.com">John D. McNally</a>
* @author <a href="mailto:bmclaugh@algx.net">Brett McLaughlin</a>
+ * @author <a href="mailto:marco@intermeta.de">Marco Knüttel</a>
* @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
* @version $Id$
*/
-public class RoleSet implements Serializable
+public class RoleSet
+ extends SecuritySet
{
/**
- * Role storage.
- */
- private TreeSet set;
-
- /**
* Constructs an empty RoleSet
*/
public RoleSet()
{
- set = new TreeSet();
+ super();
}
/**
* Constructs a new RoleSet with specified contents.
*
* If the given collection contains multiple objects that are
- * identical WRT equals() method, some objects will be overwriten.
+ * identical WRT equals() method, some objects will be overwritten.
*
* @param roles A collection of roles to be contained in the set.
*/
public RoleSet(Collection roles)
{
- this();
+ super();
add(roles);
}
@@ -111,7 +107,9 @@
*/
public boolean add(Role role)
{
- return set.add((Object) role);
+ boolean res = contains(role);
+ nameMap.put(role.getName(), role);
+ return res;
}
/**
@@ -124,133 +122,107 @@
*/
public boolean add(Collection roles)
{
- return set.addAll(roles);
+ boolean res = false;
+ for (Iterator it = roles.iterator(); it.hasNext();)
+ {
+ Role r = (Role) it.next();
+ res |= add(r);
+ }
+ return res;
}
/**
* Adds the Roles in another RoleSet to this RoleSet.
*
* @param roleSet A RoleSet.
- * @return True if this RoleSet changed as a result; false if no
- * change to this RoleSet occurred (this RoleSet already contained
- * all members of the added RoleSet).
+ * @return True if this RoleSet changed as a result; false
+ * if no change to this RoleSet occurred (this RoleSet
+ * already contained all members of the added RoleSet).
*/
public boolean add(RoleSet roleSet)
{
- return set.addAll(roleSet.set);
+ boolean res = false;
+ for( Iterator it = roleSet.iterator(); it.hasNext();)
+ {
+ Role r = (Role) it.next();
+ res |= add(r);
+ }
+ return res;
}
/**
* Removes a Role from this RoleSet.
*
* @param role A Role.
- * @return True if this RoleSet contained the Role before it was
- * removed.
+ * @return True if this RoleSet contained the Role
+ * before it was removed.
*/
public boolean remove(Role role)
{
- return set.remove((Object) role);
- }
-
- /**
- * Removes all Roles from this RoleSet.
- */
- public void clear()
- {
- set.clear();
+ boolean res = contains(role);
+ nameMap.remove(role.getName());
+ return res;
}
/**
* Checks whether this RoleSet contains a Role.
*
* @param role A Role.
- * @return True if this RoleSet contains the Role, false
- * otherwise.
+ * @return True if this RoleSet contains the Role,
+ * false otherwise.
*/
public boolean contains(Role role)
{
- return set.contains((Object) role);
+ return nameMap.containsValue((Object) role);
}
/**
- * Compares by name a Role with the Roles contained in this
- * RoleSet.
+ * Returns a Role with the given name, if it is contained in
+ * this RoleSet.
*
* @param roleName Name of Role.
- * @return True if argument matched a Role in this RoleSet; false
- * if no match.
- */
- public boolean contains(String roleName)
- {
- Iterator iter = set.iterator();
- while (iter.hasNext())
- {
- Role role = (Role) iter.next();
- if (roleName != null && roleName.equals(role.getName()))
- {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns a Role with the given name, if it is contained in this
- * RoleSet.
- *
- * @param roleName Name of Role.
- * @return Role if argument matched a Role in this RoleSet; null
- * if no match.
+ * @return Role if argument matched a Role in this
+ * RoleSet; null if no match.
*/
public Role getRole(String roleName)
{
- Iterator iter = set.iterator();
- while (iter.hasNext())
- {
- Role role = (Role) iter.next();
- if (roleName != null && roleName.equals(role.getName()))
- {
- return role;
- }
- }
- return null;
+ return (StringUtils.isNotEmpty(roleName))
+ ? (Role) nameMap.get(roleName) : null;
}
/**
* Returns an Array of Roles in this RoleSet.
*
- * @return An Array of roles.
+ * @return An Array of Role objects.
*/
public Role[] getRolesArray()
{
- return (Role[]) set.toArray(new Role[0]);
- }
-
- /**
- * @deprecated Use iterator() instead.
- */
- public Iterator elements()
- {
- return set.iterator();
+ return (Role[]) getSet().toArray(new Role[0]);
}
/**
- * Returns an Iterator for Groups in this GroupSet.
+ * Print out a RoleSet as a String
*
- * @return An Iterator for this GroupSet
- */
- public Iterator iterator()
- {
- return set.iterator();
- }
-
- /**
- * Returns size (cardinality) of this set.
+ * @returns The Role Set as String
*
- * @return The cardinality of this RoleSet.
*/
- public int size()
+ public String toString()
{
- return set.size();
+ StringBuffer sb = new StringBuffer();
+ sb.append("RoleSet: ");
+
+ for(Iterator it = iterator(); it.hasNext();)
+ {
+ Role r = (Role) it.next();
+ sb.append('[');
+ sb.append(r.getName());
+ sb.append(']');
+ if (it.hasNext())
+ {
+ sb.append(", ");
+ }
+ }
+
+ return sb.toString();
}
}
1.1 jakarta-turbine-2/src/java/org/apache/turbine/util/security/SecuritySet.java
Index: SecuritySet.java
===================================================================
package org.apache.turbine.util.security;
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001-2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache Turbine" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache Turbine", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import org.apache.turbine.om.security.SecurityEntity;
/**
* This class represents a set of Security Entities.
* It makes it easy to build a UI.
* It wraps a TreeSet object to enforce that only relevant
* methods are available.
* TreeSet's contain only unique Objects (no duplicates).
*
* @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
* @author <a href="mailto:bmclaugh@algx.net">Brett McLaughlin</a>
* @author <a href="mailto:marco@intermeta.de">Marco Knüttel</a>
* @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
* @version $Id: SecuritySet.java,v 1.1 2003/04/08 11:19:51 henning Exp $
*/
public abstract class SecuritySet
implements Serializable
{
/** Map for "name" -> "security object" */
protected Map nameMap = null;
/**
* Constructs an empty Set
*/
public SecuritySet()
{
nameMap = new TreeMap();
}
/**
* Returns a set of security objects in this object.
*
* @return A Set Object
*
*/
public Set getSet()
{
return new HashSet(nameMap.values());
}
/**
* Returns a set of Names in this Object.
*
* @return The Set of Names in this Object,
* backed by the actual data.
*/
public Set getNames()
{
return nameMap.keySet();
}
/**
* Removes all Objects from this Set.
*/
public void clear()
{
nameMap.clear();
}
/**
* Searches if an Object with a given name is in the
* Set
*
* @param roleName Name of the Security Object.
* @return True if argument matched an Object in this Set; false
* if no match.
* @deprecated Use containsName(groupName) instead.
*/
public boolean contains(String groupName)
{
return containsName(groupName);
}
/**
* Searches if an Object with a given name is in the
* Set
*
* @param roleName Name of the Security Object.
* @return True if argument matched an Object in this Set; false
* if no match.
*/
public boolean containsName(String name)
{
if (name == null)
{
return false;
}
return nameMap.containsKey(name);
}
/**
* Returns an Iterator for Objects in this Set.
*
* @return An iterator for the Set
*/
public Iterator iterator()
{
return nameMap.values().iterator();
}
/**
* @deprecated Use iterator() instead.
*/
public Iterator elements()
{
return iterator();
}
/**
* Returns size (cardinality) of this set.
*
* @return The cardinality of this Set.
*/
public int size()
{
return nameMap.size();
}
/**
* list of role names in this set
*
* @return The string representation of this Set.
*/
public String toString()
{
StringBuffer sbuf = new StringBuffer(12 * size());
for(Iterator it = nameMap.keySet().iterator(); it.hasNext(); )
{
sbuf.append((String) it.next());
if(it.hasNext())
{
sbuf.append(", ");
}
}
return sbuf.toString();
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org