You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2008/05/24 22:06:54 UTC

svn commit: r659865 - in /directory: apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/jndi/ apacheds/branches/bigbang/core/src...

Author: elecharny
Date: Sat May 24 13:06:53 2008
New Revision: 659865

URL: http://svn.apache.org/viewvc?rev=659865&view=rev
Log:
o Fixed the failing Search test for attributes with options.
o Moved some utility methods from ServerUtils to SchemaUtils in shared ldap
o Added some parameters in the search test to check if a bad parameter is ignored
o Added a checkAttributes into the schemaInterceptor to remove attributes with options
o Added a AttributeTypeOptions class to store oiptions within attributeType in the returningAttributes set

Added:
    directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AttributeTypeOptions.java
Modified:
    directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntryUtils.java
    directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/jndi/SearchIT.java
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/filtering/EntryFilteringCursor.java
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/interceptor/context/SearchingOperationContext.java
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/schema/SchemaInterceptor.java
    directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/schema/SchemaUtils.java

Modified: directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntryUtils.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntryUtils.java?rev=659865&r1=659864&r2=659865&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntryUtils.java (original)
+++ directory/apacheds/branches/bigbang/core-entry/src/main/java/org/apache/directory/server/core/entry/ServerEntryUtils.java Sat May 24 13:06:53 2008
@@ -19,7 +19,6 @@
 package org.apache.directory.server.core.entry;
 
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.NoSuchElementException;
@@ -48,6 +47,7 @@
 import org.apache.directory.shared.ldap.message.ModificationItemImpl;
 import org.apache.directory.shared.ldap.name.LdapDN;
 import org.apache.directory.shared.ldap.schema.AttributeType;
+import org.apache.directory.shared.ldap.schema.SchemaUtils;
 import org.apache.directory.shared.ldap.util.EmptyEnumeration;
 import org.apache.directory.shared.ldap.util.StringTools;
 
@@ -194,8 +194,8 @@
                     Attribute attr = attrs.nextElement();
 
                     String attributeId = attr.getID();
-                    String id = stripOptions( attributeId );
-                    Set<String> options = getOptions( attributeId );
+                    String id = SchemaUtils.stripOptions( attributeId );
+                    Set<String> options = SchemaUtils.getOptions( attributeId );
                     // TODO : handle options.
                     AttributeType attributeType = registries.getAttributeTypeRegistry().lookup( id );
                     ServerAttribute serverAttribute = ServerEntryUtils.toServerAttribute( attr, attributeType );
@@ -477,8 +477,8 @@
 	        for ( ModificationItem modification: modifications )
 	        {
 	            String attributeId = modification.getAttribute().getID();
-                String id = stripOptions( attributeId );
-	            Set<String> options = getOptions( attributeId );
+                String id = SchemaUtils.stripOptions( attributeId );
+	            Set<String> options = SchemaUtils.getOptions( attributeId );
 
 	            // -------------------------------------------------------------------
 	            // DIRSERVER-646 Fix: Replacing an unknown attribute with no values 
@@ -639,62 +639,4 @@
     	    }
     	};
     }
-    
-    
-    /**
-     * Remove the options from the attributeType, and returns the ID.
-     * 
-     * RFC 4512 :
-     * attributedescription = attributetype options
-     * attributetype = oid
-     * options = *( SEMI option )
-     * option = 1*keychar
-     */
-    private static String stripOptions( String attributeId )
-    {
-        int optionsPos = attributeId.indexOf( ";" ); 
-        
-        if ( optionsPos != -1 )
-        {
-            return attributeId.substring( 0, optionsPos );
-        }
-        else
-        {
-            return attributeId;
-        }
-    }
-    
-    /**
-     * Get the options from the attributeType.
-     * 
-     * For instance, given :
-     * jpegphoto;binary;lang=jp
-     * 
-     * your get back a set containing { "binary", "lang=jp" }
-     */
-    private static Set<String> getOptions( String attributeId )
-    {
-        int optionsPos = attributeId.indexOf( ";" ); 
-
-        if ( optionsPos != -1 )
-        {
-            Set<String> options = new HashSet<String>();
-            
-            String[] res = attributeId.substring( optionsPos + 1 ).split( ";" );
-            
-            for ( String option:res )
-            {
-                if ( !StringTools.isEmpty( option ) )
-                {
-                    options.add( option );
-                }
-            }
-            
-            return options;
-        }
-        else
-        {
-            return null;
-        }
-    }
 }

Modified: directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/jndi/SearchIT.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/jndi/SearchIT.java?rev=659865&r1=659864&r2=659865&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/jndi/SearchIT.java (original)
+++ directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/jndi/SearchIT.java Sat May 24 13:06:53 2008
@@ -939,7 +939,7 @@
         SearchControls ctls = new SearchControls();
         ctls.setSearchScope( SearchControls.OBJECT_SCOPE );
         ctls.setReturningAttributes( new String[]
-            { "cn", "sn;unknownOption" } );
+            { "cn", "sn;unknownOption", "badAttr" } );
 
         NamingEnumeration<SearchResult> result = sysRoot.search( RDN, FILTER, ctls );
 

Modified: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/filtering/EntryFilteringCursor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/filtering/EntryFilteringCursor.java?rev=659865&r1=659864&r2=659865&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/filtering/EntryFilteringCursor.java (original)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/filtering/EntryFilteringCursor.java Sat May 24 13:06:53 2008
@@ -33,6 +33,7 @@
 import org.apache.directory.server.core.interceptor.context.SearchingOperationContext;
 import org.apache.directory.shared.ldap.exception.OperationAbandonedException;
 import org.apache.directory.shared.ldap.schema.AttributeType;
+import org.apache.directory.shared.ldap.schema.AttributeTypeOptions;
 import org.apache.directory.shared.ldap.schema.UsageEnum;
 
 import org.slf4j.Logger;
@@ -343,7 +344,17 @@
         {
             for ( AttributeType at : entry.getOriginalEntry().getAttributeTypes() )
             {
-                boolean isNotRequested = ! getOperationContext().getReturningAttributes().contains( at );
+                boolean isNotRequested = true;
+                
+                for ( AttributeTypeOptions attrOptions:getOperationContext().getReturningAttributes() )
+                {
+                    if ( attrOptions.getAttributeType().equals( at ) )
+                    {
+                        isNotRequested = false;
+                        break;
+                    }
+                }
+                
                 boolean isNotUserAttribute = at.getUsage() != UsageEnum.USER_APPLICATIONS;
                 
                 if (  isNotRequested && isNotUserAttribute )
@@ -359,7 +370,17 @@
         {
             for ( AttributeType at : entry.getOriginalEntry().getAttributeTypes() )
             {
-                boolean isNotRequested = ! getOperationContext().getReturningAttributes().contains( at );
+                boolean isNotRequested = true;
+                
+                for ( AttributeTypeOptions attrOptions:getOperationContext().getReturningAttributes() )
+                {
+                    if ( attrOptions.getAttributeType().equals( at ) )
+                    {
+                        isNotRequested = false;
+                        break;
+                    }
+                }
+
                 boolean isUserAttribute = at.getUsage() == UsageEnum.USER_APPLICATIONS;
                 
                 if ( isNotRequested && isUserAttribute )
@@ -375,7 +396,16 @@
         {
             for ( AttributeType at : entry.getOriginalEntry().getAttributeTypes() )
             {
-                boolean isNotRequested = ! getOperationContext().getReturningAttributes().contains( at );
+                boolean isNotRequested = true;
+                
+                for ( AttributeTypeOptions attrOptions:getOperationContext().getReturningAttributes() )
+                {
+                    if ( attrOptions.getAttributeType().equals( at ) )
+                    {
+                        isNotRequested = false;
+                        break;
+                    }
+                }
 
                 if ( isNotRequested )
                 {

Modified: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/interceptor/context/SearchingOperationContext.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/interceptor/context/SearchingOperationContext.java?rev=659865&r1=659864&r2=659865&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/interceptor/context/SearchingOperationContext.java (original)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/interceptor/context/SearchingOperationContext.java Sat May 24 13:06:53 2008
@@ -24,6 +24,7 @@
 import java.util.Set;
 
 import javax.naming.NamingException;
+import javax.naming.directory.NoSuchAttributeException;
 import javax.naming.directory.SearchControls;
 
 import org.apache.directory.server.schema.registries.Registries;
@@ -32,7 +33,11 @@
 import org.apache.directory.shared.ldap.message.AliasDerefMode;
 import org.apache.directory.shared.ldap.name.LdapDN;
 import org.apache.directory.shared.ldap.schema.AttributeType;
+import org.apache.directory.shared.ldap.schema.AttributeTypeOptions;
+import org.apache.directory.shared.ldap.schema.SchemaUtils;
 import org.apache.directory.shared.ldap.util.ArrayUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import static org.apache.directory.shared.ldap.filter.SearchScope.ONELEVEL;
 
@@ -46,22 +51,34 @@
  */
 public abstract class SearchingOperationContext extends AbstractOperationContext
 {
+    /** The LoggerFactory used by this Interceptor */
+    private static Logger LOG = LoggerFactory.getLogger( SearchingOperationContext.class );
+
+    /** A flag describing the way alias should be handled */
     private AliasDerefMode aliasDerefMode = AliasDerefMode.DEREF_ALWAYS;
 
+    /** The sizeLimit for this search operation */
     private long sizeLimit = 0;
     
+    /** The timeLimit for this search operation */
     private int timeLimit = 0;
     
+    /** The scope for this search : default to One Level */
     private SearchScope scope = ONELEVEL;
 
+    /** A flag set if the returned attributes set contains '+' */
     private boolean allOperationalAttributes = false;
     
+    /** A flag set if the returned attributes set contains '*' */
     private boolean allUserAttributes = false;
     
+    /** A flag set if the returned attributes set contains '1.1' */
     private boolean noAttributes = false;
     
-    private Set<AttributeType> returningAttributes; 
+    /** A set containing the returning attributeTypesOptions */
+    private Set<AttributeTypeOptions> returningAttributes; 
     
+    /** A flag if the search operation is abandoned */
     private boolean abandoned = false;
     
     
@@ -116,7 +133,8 @@
         
         if ( searchControls.getReturningAttributes() != null )
         {
-            returningAttributes = new HashSet<AttributeType>();
+            returningAttributes = new HashSet<AttributeTypeOptions>();
+            
             for ( String returnAttribute : searchControls.getReturningAttributes() )
             {
                 if ( returnAttribute.equals( SchemaConstants.NO_ATTRIBUTE ) )
@@ -137,7 +155,20 @@
                     continue;
                 }
                 
-                returningAttributes.add( registries.getAttributeTypeRegistry().lookup( returnAttribute ) );
+                try
+                {
+                    String id = SchemaUtils.stripOptions( returnAttribute );
+                    Set<String> options = SchemaUtils.getOptions( returnAttribute );
+                    AttributeType attributeType = registries.getAttributeTypeRegistry().lookup( id );
+                    AttributeTypeOptions attrOptions = new AttributeTypeOptions( attributeType, options );
+                    
+                    returningAttributes.add( attrOptions );
+                }
+                catch ( NoSuchAttributeException nsae )
+                {
+                    LOG.warn( "Requested attribute {} does not exist in the schema, it will be ignored", returnAttribute );
+                    // Unknown attributes should be silently ignored, as RFC 2251 states
+                }
             }
         }
     }
@@ -271,7 +302,7 @@
     /**
      * @param returningAttributes the returningAttributes to set
      */
-    public void setReturningAttributes( Set<AttributeType> returningAttributes )
+    public void setReturningAttributes( Set<AttributeTypeOptions> returningAttributes )
     {
         this.returningAttributes = returningAttributes;
     }
@@ -280,7 +311,7 @@
     /**
      * @return the returningAttributes
      */
-    public Set<AttributeType> getReturningAttributes()
+    public Set<AttributeTypeOptions> getReturningAttributes()
     {
         return returningAttributes;
     }
@@ -331,15 +362,15 @@
         
         if ( returningAttributes != null )
         {
-            for ( AttributeType at : returningAttributes )
+            for ( AttributeTypeOptions at : returningAttributes )
             {
                 if ( denormalized )
                 {
-                    allReturningAttributes.add( at.getName() );
+                    allReturningAttributes.add( at.getAttributeType().getName() );
                 }
                 else
                 {
-                    allReturningAttributes.add( at.getOid() );
+                    allReturningAttributes.add( at.getAttributeType().getOid() );
                 }
             }
         }

Modified: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/schema/SchemaInterceptor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/schema/SchemaInterceptor.java?rev=659865&r1=659864&r2=659865&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/schema/SchemaInterceptor.java (original)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/schema/SchemaInterceptor.java Sat May 24 13:06:53 2008
@@ -81,6 +81,7 @@
 import org.apache.directory.shared.ldap.name.LdapDN;
 import org.apache.directory.shared.ldap.name.Rdn;
 import org.apache.directory.shared.ldap.schema.AttributeType;
+import org.apache.directory.shared.ldap.schema.AttributeTypeOptions;
 import org.apache.directory.shared.ldap.schema.ObjectClass;
 import org.apache.directory.shared.ldap.schema.SchemaUtils;
 import org.apache.directory.shared.ldap.schema.UsageEnum;
@@ -1441,6 +1442,50 @@
         next.modify( opContext );
     }
 
+    
+    /**
+     * Filter the attributes by removing the ones which are not allowed
+     */
+    private void filterAttributeTypes( SearchingOperationContext operation, ClonedServerEntry result )
+    {
+        if ( operation.getReturningAttributes() == null )
+        {
+            return;
+        }
+        
+        for ( AttributeTypeOptions attrOptions:operation.getReturningAttributes() )
+        {
+            EntryAttribute attribute = result.get( attrOptions.getAttributeType() );
+            
+            if ( attrOptions.hasOption() )
+            {
+                for ( String option:attrOptions.getOptions() )
+                {
+                    if ( "binary".equalsIgnoreCase( option ) )
+                    {
+                        continue;
+                    }
+                    else
+                    {
+                        try
+                        {
+                            if ( result.contains( attribute ) )
+                            {
+                                result.remove( attribute );
+                            }
+                        }
+                        catch ( NamingException ne )
+                        {
+                            // Do nothings
+                        }
+                        break;
+                    }
+                }
+                
+                
+            }
+        }
+    }
 
     private void filterObjectClass( ServerEntry entry ) throws Exception
     {
@@ -1527,6 +1572,7 @@
             throws Exception
         {
             filterObjectClass( result );
+            filterAttributeTypes( operation, result );
             return true;
         }
     }

Added: directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AttributeTypeOptions.java
URL: http://svn.apache.org/viewvc/directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AttributeTypeOptions.java?rev=659865&view=auto
==============================================================================
--- directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AttributeTypeOptions.java (added)
+++ directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/schema/AttributeTypeOptions.java Sat May 24 13:06:53 2008
@@ -0,0 +1,168 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.shared.ldap.schema;
+
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.directory.shared.ldap.util.StringTools;
+
+
+/**
+ * An structure containing a couple of attributeType and options. A search request
+ * can contain a list of attribute to return, those attribute could be associated
+ * with options.
+ * 
+ * Those options are stored into a Set.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 655151 $
+ */
+public class AttributeTypeOptions
+{
+    /** The attributeType */
+    private AttributeType attributeType;
+    
+    /** The options, if any */
+    private Set<String> options;
+    
+    
+    /**
+     * Creates a new instance of AttributeTypeOptions, containing an attributeType, 
+     * but no options.
+     *
+     * @param attributeType The associated AttributeType
+     */
+    public AttributeTypeOptions( AttributeType attributeType )
+    {
+        this.attributeType = attributeType;
+    }
+
+
+    /**
+     * Creates a new instance of AttributeTypeOptions, containing an attributeType, 
+     * and options.
+     *
+     * @param attributeType the associated AttributeType
+     * @param options the associated options
+     */
+    public AttributeTypeOptions( AttributeType attributeType, Set<String> options )
+    {
+        this.attributeType = attributeType;
+        this.options = options;
+    }
+    
+    
+    /**
+     * @return the inner attributeType
+     */
+    public AttributeType getAttributeType()
+    {
+        return attributeType;
+    }
+
+    
+    /**
+     * @return the associated options
+     */
+    public Set<String> getOptions()
+    {
+        return options;
+    }
+    
+    
+    /**
+     * @return <code>true</code> if the attributeType has at least one option
+     */
+    public boolean hasOption()
+    {
+        return ( options != null ) && ( options.size() != 0 );
+    }
+    
+    
+    /**
+     * @param option the option to check
+     * @return <code>true</code> if the attributeType has the given option
+     */
+    public boolean hasOption( String option )
+    {
+        if ( hasOption() )
+        {
+            return options.contains( StringTools.toLowerCase( StringTools.trim( option ) ) );
+        }
+        else 
+        {
+            return false;
+        }
+    }
+    
+    
+    /**
+     * Add a new option to the option set for this attributeType.
+     *
+     * @param option the option to add
+     */
+    public void addOption( String option )
+    {
+        if ( options == null )
+        {
+            options = new HashSet<String>();
+        }
+        
+        options.add( StringTools.toLowerCase( StringTools.trim( option ) ) );
+    }
+
+
+    /**
+     * Add a set of optionS to the option set for this attributeType.
+     *
+     * @param options the options to add
+     */
+    public void addOptions( Set<String> options )
+    {
+        if ( this.options == null )
+        {
+            this.options = options;
+        }
+        else
+        {
+            this.options.addAll( options );
+        }
+    }
+    
+    
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+        
+        sb.append( "<" ).append( attributeType.getName() );
+        
+        if ( hasOption() )
+        {
+            for ( String option:options )
+            {
+                sb.append( ";" ).append( option );
+            }
+        }
+
+        return sb.append( ">" ).toString();
+    }
+}

Modified: directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/schema/SchemaUtils.java
URL: http://svn.apache.org/viewvc/directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/schema/SchemaUtils.java?rev=659865&r1=659864&r2=659865&view=diff
==============================================================================
--- directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/schema/SchemaUtils.java (original)
+++ directory/shared/branches/bigbang/ldap/src/main/java/org/apache/directory/shared/ldap/schema/SchemaUtils.java Sat May 24 13:06:53 2008
@@ -20,8 +20,10 @@
 package org.apache.directory.shared.ldap.schema;
 
 
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
@@ -34,6 +36,7 @@
 import org.apache.directory.shared.ldap.schema.syntax.AbstractAdsSchemaDescription;
 import org.apache.directory.shared.ldap.schema.syntax.AbstractSchemaDescription;
 import org.apache.directory.shared.ldap.schema.syntax.AttributeTypeDescription;
+import org.apache.directory.shared.ldap.util.StringTools;
 
 
 /**
@@ -1088,4 +1091,62 @@
 
         return values.get( 0 );
     }
+
+
+    /**
+     * Remove the options from the attributeType, and returns the ID.
+     * 
+     * RFC 4512 :
+     * attributedescription = attributetype options
+     * attributetype = oid
+     * options = *( SEMI option )
+     * option = 1*keychar
+     */
+    public static String stripOptions( String attributeId )
+    {
+        int optionsPos = attributeId.indexOf( ";" ); 
+        
+        if ( optionsPos != -1 )
+        {
+            return attributeId.substring( 0, optionsPos );
+        }
+        else
+        {
+            return attributeId;
+        }
+    }
+    
+    /**
+     * Get the options from the attributeType.
+     * 
+     * For instance, given :
+     * jpegphoto;binary;lang=jp
+     * 
+     * your get back a set containing { "binary", "lang=jp" }
+     */
+    public static Set<String> getOptions( String attributeId )
+    {
+        int optionsPos = attributeId.indexOf( ";" ); 
+
+        if ( optionsPos != -1 )
+        {
+            Set<String> options = new HashSet<String>();
+            
+            String[] res = attributeId.substring( optionsPos + 1 ).split( ";" );
+            
+            for ( String option:res )
+            {
+                if ( !StringTools.isEmpty( option ) )
+                {
+                    options.add( option );
+                }
+            }
+            
+            return options;
+        }
+        else
+        {
+            return null;
+        }
+    }
 }