001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 */
020 package org.apache.directory.shared.ldap.schema.syntaxCheckers;
021
022
023 import java.util.HashSet;
024 import java.util.Set;
025
026 import org.apache.directory.shared.ldap.constants.SchemaConstants;
027 import org.apache.directory.shared.ldap.schema.SyntaxChecker;
028 import org.apache.directory.shared.ldap.util.StringTools;
029 import org.slf4j.Logger;
030 import org.slf4j.LoggerFactory;
031
032
033 /**
034 * A SyntaxChecker which verifies that a value is a delivery method
035 * according to RFC 4517.
036 *
037 * From RFC 4517 & RFC 4512:
038 *
039 * DeliveryMethod = pdm *( WSP DOLLAR WSP pdm )
040 *
041 * pdm = "any" | "mhs" | "physical" | "telex" | "teletex" |
042 * "g3fax" | "g4fax" | "ia5" | "videotex" | "telephone"
043 *
044 * WSP = 0*SPACE ; zero or more " "
045 * DOLLAR = %x24 ; dollar sign ("$")
046 * SPACE = %x20 ; space (" ")
047 *
048 *
049 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
050 * @version $Rev$
051 */
052 public class DeliveryMethodSyntaxChecker extends SyntaxChecker
053 {
054 /** A logger for this class */
055 private static final Logger LOG = LoggerFactory.getLogger( DeliveryMethodSyntaxChecker.class );
056
057 /** The serialVersionUID */
058 private static final long serialVersionUID = 1L;
059
060 private static final String[] PDMS =
061 {
062 "any", "mhs", "physical", "telex", "teletex",
063 "g3fax", "g4fax", "ia5", "videotex", "telephone"
064 };
065
066 /** The Set which contains the delivery methods */
067 private static final Set<String> DELIVERY_METHODS = new HashSet<String>();
068
069 /** Initialization of the delivery methods set */
070 static
071 {
072 for ( String country:PDMS )
073 {
074 DELIVERY_METHODS.add( country );
075 }
076 }
077
078 /**
079 *
080 * Creates a new instance of DeliveryMethodSyntaxChecker.
081 *
082 */
083 public DeliveryMethodSyntaxChecker()
084 {
085 super( SchemaConstants.DELIVERY_METHOD_SYNTAX );
086 }
087
088
089 /**
090 *
091 * Check if the string contains a delivery method which has
092 * not already been found.
093 *
094 * @param strValue The string we want to look into for a PDM
095 * @param pos The current position in the string
096 * @param pdms The set containing all the PDM
097 * @return if a Prefered Delivery Method is found in the given string, returns
098 * its position, otherwise, returns -1
099 */
100 private int isPdm( String strValue, int start, Set<String> pdms )
101 {
102 int pos = start;
103
104 while ( StringTools.isAlphaDigit( strValue, pos ) )
105 {
106 pos++;
107 }
108
109 // No ascii string, this is not a delivery method
110 if ( pos == start )
111 {
112 return -1;
113 }
114
115 String pdm = strValue.substring( start, pos );
116
117 if ( ! DELIVERY_METHODS.contains( pdm ) )
118 {
119 // The delivery method is unknown
120 return -1;
121 }
122 else
123 {
124 if ( pdms.contains( pdm ) )
125 {
126 // The delivery method has already been found
127 return -1;
128 }
129 else
130 {
131 pdms.add( pdm );
132 return pos;
133 }
134 }
135 }
136
137
138 /**
139 * {@inheritDoc}
140 */
141 public boolean isValidSyntax( Object value )
142 {
143 String strValue = null;
144
145 if ( value == null )
146 {
147 LOG.debug( "Syntax invalid for '{}'", value );
148 return false;
149 }
150
151 if ( value instanceof String )
152 {
153 strValue = ( String ) value;
154 }
155 else if ( value instanceof byte[] )
156 {
157 strValue = StringTools.utf8ToString( ( byte[] ) value );
158 }
159 else
160 {
161 strValue = value.toString();
162 }
163
164 if ( strValue.length() == 0 )
165 {
166 LOG.debug( "Syntax invalid for '{}'", value );
167 return false;
168 }
169
170 // We will get the first delivery method
171 int length = strValue.length();
172 int pos = 0;
173 Set<String> pmds = new HashSet<String>();
174
175 if ( ( pos = isPdm( strValue, pos, pmds ) ) == -1)
176 {
177 LOG.debug( "Syntax invalid for '{}'", value );
178 return false;
179 }
180
181 // We have found at least the first pmd,
182 // now iterate through the other ones. We may have
183 // SP* '$' SP* before each pmd.
184 while ( pos < length )
185 {
186 // Skip spaces
187 while ( StringTools.isCharASCII( strValue, pos, ' ' ) )
188 {
189 pos++;
190 }
191
192 if ( ! StringTools.isCharASCII( strValue, pos, '$' ) )
193 {
194 // A '$' was expected
195 LOG.debug( "Syntax invalid for '{}'", value );
196 return false;
197 }
198 else
199 {
200 pos++;
201 }
202
203 // Skip spaces
204 while ( StringTools.isCharASCII( strValue, pos, ' ' ) )
205 {
206 pos++;
207 }
208
209 if ( ( pos = isPdm( strValue, pos, pmds ) ) == -1 )
210 {
211 LOG.debug( "Syntax invalid for '{}'", value );
212 return false;
213 }
214 }
215
216 LOG.debug( "Syntax valid for '{}'", value );
217 return true;
218 }
219 }