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 generalized time 34 * according to RFC 4517. 35 * 36 * From RFC 4517 : 37 * GeneralizedTime = century year month day hour 38 * [ minute [ second / leap-second ] ] 39 * [ fraction ] 40 * g-time-zone 41 * 42 * century = 2(%x30-39) ; "00" to "99" 43 * year = 2(%x30-39) ; "00" to "99" 44 * month = ( %x30 %x31-39 ) ; "01" (January) to "09" 45 * | ( %x31 %x30-32 ) ; "10" to "12" 46 * day = ( %x30 %x31-39 ) ; "01" to "09" 47 * | ( %x31-32 %x30-39 ) ; "10" to "29" 48 * | ( %x33 %x30-31 ) ; "30" to "31" 49 * hour = ( %x30-31 %x30-39 ) 50 * | ( %x32 %x30-33 ) ; "00" to "23" 51 * minute = %x30-35 %x30-39 ; "00" to "59" 52 * 53 * second = ( %x30-35 %x30-39 ) ; "00" to "59" 54 * leap-second = ( %x36 %x30 ) ; "60" 55 * 56 * fraction = ( DOT / COMMA ) 1*(%x30-39) 57 * g-time-zone = %x5A ; "Z" 58 * | g-differential 59 * g-differential = ( MINUS / PLUS ) hour [ minute ] 60 * MINUS = %x2D ; minus sign ("-") 61 * 62 * From RFC 4512 : 63 * PLUS = %x2B ; plus sign ("+") 64 * DOT = %x2E ; period (".") 65 * COMMA = %x2C ; comma (",") 66 * 67 * 68 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 69 */ 70 @SuppressWarnings("serial") 71 public class GeneralizedTimeSyntaxChecker extends SyntaxChecker 72 { 73 /** A logger for this class */ 74 private static final Logger LOG = LoggerFactory.getLogger( GeneralizedTimeSyntaxChecker.class ); 75 76 /** The GeneralizedDate pattern matching */ 77 private static final String GENERALIZED_TIME_PATTERN = 78 "^\\d{4}" // century + year : 0000 to 9999 79 + "(0[1-9]|1[0-2])" // month : 01 to 12 80 + "(0[1-9]|[12]\\d|3[01])" // day : 01 to 31 81 + "([01]\\d|2[0-3])" // hour : 00 to 23 82 + "(" 83 + "([0-5]\\d)" // optional minute : 00 to 59 84 + "([0-5]\\d|60)?" // optional second | leap second 85 + ")?" 86 + "([.,]\\d+)?" // fraction 87 + "(Z|[+-]([01]\\d|2[0-3])([0-5]\\d)?)$"; // time-zone 88 89 /** The date pattern. The regexp pattern is immutable, only one instance needed. */ 90 private static final Pattern DATE_PATTERN = Pattern.compile( GENERALIZED_TIME_PATTERN ); 91 92 93 /** 94 * Creates a new instance of GeneralizedTimeSyntaxChecker. 95 */ 96 public GeneralizedTimeSyntaxChecker() 97 { 98 super( SchemaConstants.GENERALIZED_TIME_SYNTAX ); 99 } 100 101 102 /** 103 * {@inheritDoc} 104 */ 105 public boolean isValidSyntax( Object value ) 106 { 107 String strValue = null; 108 109 if ( value == null ) 110 { 111 LOG.debug( "Syntax invalid for 'null'" ); 112 return false; 113 } 114 115 if ( value instanceof String ) 116 { 117 strValue = ( String ) value; 118 } 119 else if ( value instanceof byte[] ) 120 { 121 strValue = Strings.utf8ToString( ( byte[] ) value ); 122 } 123 else 124 { 125 strValue = value.toString(); 126 } 127 128 // A generalized time must have a minimal length of 11 129 if ( strValue.length() < 11 ) 130 { 131 LOG.debug( "Syntax invalid for '{}'", value ); 132 return false; 133 } 134 135 // Start the date parsing 136 boolean result = DATE_PATTERN.matcher( strValue ).find(); 137 138 if ( result ) 139 { 140 LOG.debug( "Syntax valid for '{}'", value ); 141 } 142 else 143 { 144 LOG.debug( "Syntax invalid for '{}'", value ); 145 } 146 147 return result; 148 } 149 }