View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.ldap.model.schema.syntaxCheckers;
21  
22  
23  import java.util.regex.Pattern;
24  
25  import org.apache.directory.api.ldap.model.constants.SchemaConstants;
26  import org.apache.directory.api.ldap.model.schema.SyntaxChecker;
27  import org.apache.directory.api.util.Strings;
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  
31  
32  /**
33   * A SyntaxChecker which verifies that a value is a UTC time
34   * according to RFC 4517.
35   * 
36   * From RFC 4517 :
37   * UTCTime         = year month day hour minute [ second ] [ u-time-zone ]
38   * u-time-zone     = %x5A          ; "Z" | u-differential
39   * u-differential  = ( MINUS | PLUS ) hour minute
40   *
41   * year    = 2(%x30-39)            ; "00" to "99"
42   * month   = ( %x30 %x31-39 )      ; "01" (January) to "09"
43   *           | ( %x31 %x30-32 )    ; "10" to "12"
44   * day     = ( %x30 %x31-39 )      ; "01" to "09"
45   *           | ( %x31-32 %x30-39 ) ; "10" to "29"
46   *           | ( %x33 %x30-31 )    ; "30" to "31"
47   * hour    = ( %x30-31 %x30-39 ) 
48   *           | ( %x32 %x30-33 )    ; "00" to "23"
49   * minute  = %x30-35 %x30-39       ; "00" to "59"
50   *
51   * second  = ( %x30-35 %x30-39 )   ; "00" to "59"
52   *
53   * g-time-zone = %x5A              ; "Z"
54   *               | g-differential
55   * g-differential = ( MINUS / PLUS ) hour [ minute ]
56   * MINUS   = %x2D  ; minus sign ("-")
57   * 
58   * From RFC 4512 :
59   * PLUS    = %x2B ; plus sign ("+")
60   * 
61   *
62   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
63   */
64  @SuppressWarnings("serial")
65  public class UtcTimeSyntaxChecker extends SyntaxChecker
66  {
67      /** A logger for this class */
68      private static final Logger LOG = LoggerFactory.getLogger( UtcTimeSyntaxChecker.class );
69  
70      /** The GeneralizedDate pattern matching */
71      private static final String UTC_TIME_PATTERN =
72          "^\\d{2}" // year : 00 to 99
73              + "(0[1-9]|1[0-2])" // month : 01 to 12
74              + "(0[1-9]|[12]\\d|3[01])" // day : 01 to 31
75              + "([01]\\d|2[0-3])" // hour: 00 to 23
76              + "([0-5]\\d)" // minute : 00 to 59
77              + "("
78              + "([0-5]\\d)?" // optional second : 00 to 59
79              + "(Z|([+-]([01]\\d|2[0-3])[0-5]\\d))?" // optionnal time-zone
80              + ")$";
81  
82      // The regexp pattern, java.util.regex.Pattern is immutable so only one instance is needed.
83      private static final Pattern DATE_PATTERN = Pattern.compile( UTC_TIME_PATTERN );
84  
85  
86      /**
87       * 
88       * Creates a new instance of UtcTimeSyntaxChecker.
89       *
90       */
91      public UtcTimeSyntaxChecker()
92      {
93          super( SchemaConstants.UTC_TIME_SYNTAX );
94      }
95  
96  
97      /**
98       * {@inheritDoc}
99       */
100     public boolean isValidSyntax( Object value )
101     {
102         String strValue = null;
103 
104         if ( value == null )
105         {
106             LOG.debug( "Syntax invalid for 'null'" );
107             return false;
108         }
109 
110         if ( value instanceof String )
111         {
112             strValue = ( String ) value;
113         }
114         else if ( value instanceof byte[] )
115         {
116             strValue = Strings.utf8ToString( ( byte[] ) value );
117         }
118         else
119         {
120             strValue = value.toString();
121         }
122 
123         // A generalized time must have a minimal length of 11 
124         if ( strValue.length() < 11 )
125         {
126             LOG.debug( "Syntax invalid for '{}'", value );
127             return false;
128         }
129 
130         // Start the date parsing
131         boolean result = DATE_PATTERN.matcher( strValue ).find();
132 
133         if ( result )
134         {
135             LOG.debug( "Syntax valid for '{}'", value );
136         }
137         else
138         {
139             LOG.debug( "Syntax invalid for '{}'", value );
140         }
141         return result;
142     }
143 }