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.regex.Pattern; 024 025 import org.apache.directory.shared.ldap.constants.SchemaConstants; 026 import org.apache.directory.shared.ldap.schema.SyntaxChecker; 027 import org.apache.directory.shared.ldap.util.StringTools; 028 import org.slf4j.Logger; 029 import org.slf4j.LoggerFactory; 030 031 032 /** 033 * A SyntaxChecker which verifies that a value is a generalized time 034 * according to RFC 4517. 035 * 036 * From RFC 4517 : 037 * GeneralizedTime = century year month day hour 038 * [ minute [ second / leap-second ] ] 039 * [ fraction ] 040 * g-time-zone 041 * 042 * century = 2(%x30-39) ; "00" to "99" 043 * year = 2(%x30-39) ; "00" to "99" 044 * month = ( %x30 %x31-39 ) ; "01" (January) to "09" 045 * | ( %x31 %x30-32 ) ; "10" to "12" 046 * day = ( %x30 %x31-39 ) ; "01" to "09" 047 * | ( %x31-32 %x30-39 ) ; "10" to "29" 048 * | ( %x33 %x30-31 ) ; "30" to "31" 049 * hour = ( %x30-31 %x30-39 ) 050 * | ( %x32 %x30-33 ) ; "00" to "23" 051 * minute = %x30-35 %x30-39 ; "00" to "59" 052 * 053 * second = ( %x30-35 %x30-39 ) ; "00" to "59" 054 * leap-second = ( %x36 %x30 ) ; "60" 055 * 056 * fraction = ( DOT / COMMA ) 1*(%x30-39) 057 * g-time-zone = %x5A ; "Z" 058 * | g-differential 059 * g-differential = ( MINUS / PLUS ) hour [ minute ] 060 * MINUS = %x2D ; minus sign ("-") 061 * 062 * From RFC 4512 : 063 * PLUS = %x2B ; plus sign ("+") 064 * DOT = %x2E ; period (".") 065 * COMMA = %x2C ; comma (",") 066 * 067 * 068 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 069 * @version $Rev$ 070 */ 071 public class GeneralizedTimeSyntaxChecker extends SyntaxChecker 072 { 073 /** A logger for this class */ 074 private static final Logger LOG = LoggerFactory.getLogger( GeneralizedTimeSyntaxChecker.class ); 075 076 /** The serialVersionUID */ 077 private static final long serialVersionUID = 1L; 078 079 /** The GeneralizedDate pattern matching */ 080 private static final String GENERALIZED_TIME_PATTERN = 081 "^\\d{4}" + // century + year : 0000 to 9999 082 "(0[1-9]|1[0-2])" + // month : 01 to 12 083 "(0[1-9]|[12]\\d|3[01])" + // day : 01 to 31 084 "([01]\\d|2[0-3])" + // hour : 00 to 23 085 "(" + 086 "([0-5]\\d)" + // optionnal minute : 00 to 59 087 "([0-5]\\d|60)?" + // optionnal second | leap second 088 ")?" + 089 "([.,]\\d+)?" + // fraction 090 "(Z|[+-]([01]\\d|2[0-3])([0-5]\\d)?)$"; // time-zone 091 092 // The regexp pattern matcher 093 private Pattern datePattern = Pattern.compile( GENERALIZED_TIME_PATTERN ); 094 095 /** 096 * Creates a new instance of GeneralizedTimeSyntaxChecker. 097 */ 098 public GeneralizedTimeSyntaxChecker() 099 { 100 super( SchemaConstants.GENERALIZED_TIME_SYNTAX ); 101 } 102 103 104 /** 105 * {@inheritDoc} 106 */ 107 public boolean isValidSyntax( Object value ) 108 { 109 String strValue = null; 110 111 if ( value == null ) 112 { 113 LOG.debug( "Syntax invalid for '{}'", value ); 114 return false; 115 } 116 117 if ( value instanceof String ) 118 { 119 strValue = ( String ) value; 120 } 121 else if ( value instanceof byte[] ) 122 { 123 strValue = StringTools.utf8ToString( ( byte[] ) value ); 124 } 125 else 126 { 127 strValue = value.toString(); 128 } 129 130 // A generalized time must have a minimal length of 11 131 if ( strValue.length() < 11 ) 132 { 133 LOG.debug( "Syntax invalid for '{}'", value ); 134 return false; 135 } 136 137 // Start the date parsing 138 boolean result = datePattern.matcher( strValue ).find(); 139 140 if ( result ) 141 { 142 LOG.debug( "Syntax valid for '{}'", value ); 143 } 144 else 145 { 146 LOG.debug( "Syntax invalid for '{}'", value ); 147 } 148 149 return result; 150 } 151 }