5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster/**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The contents of this file are subject to the terms
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * of the Common Development and Distribution License
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * (the License). You may not use this file except in
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * compliance with the License.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * You can obtain a copy of the License at
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * opensso/legal/CDDLv1.0.txt
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * See the License for the specific language governing
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * permission and limitations under the License.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * When distributing Covered Code, include this CDDL
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Header Notice in each file and include the License file
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * at opensso/legal/CDDLv1.0.txt.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If applicable, add the following below the CDDL Header,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * with the fields enclosed by brackets [] replaced by
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * your own identifying information:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * "Portions Copyrighted [year] [name of copyright owner]"
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * $Id: XSDurationValidator.java,v 1.2 2008/06/25 05:53:07 qcheng Exp $
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterpackage com.sun.identity.shared.validation;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport com.sun.identity.shared.DateUtils;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.text.ParseException;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.util.Iterator;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterimport java.util.Set;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster/**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Validator for <code>xs:duration</code> format.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The validation of the cache duration is done based on the following:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If the number of years, months, days, hours, minutes, or seconds in
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * any expression equals zero, the number and its corresponding
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * designator may be omitted. However, at least one number and its
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * designator must be present.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The seconds part may have a decimal fraction.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The designator 'T' must be absent if and only if all of the
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * time items are absent.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The designator 'P' must always be present.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterpublic class XSDurationValidator
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster extends ValidatorBase
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster{
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static XSDurationValidator instance = new XSDurationValidator();
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private static boolean debug = false;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private XSDurationValidator() {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Returns an instance of this validator.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return an instance of this validator.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public static XSDurationValidator getInstance() {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return instance;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /* validate the cache duration string */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster protected void performValidation(String strData)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throws ValidationException
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // if the string is null or empty or less then 3 charactors
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // then throw error
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((strData == null) || (strData.trim().length() == 0)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster || (strData.trim().length() < 3)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throw new ValidationException(resourceBundleName, "errorCode4");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // expecting this format P1Y2M4DT9H8M20S
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // first character should be a P
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (strData.charAt(0) != 'P') {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throw new ValidationException(resourceBundleName, "errorCode4");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // time data validation
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster String timeStr = null;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster String dateStr = null;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (strData.indexOf('T') != -1) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // T without time elements H M S error
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (strData.charAt(strData.length()-1) == 'T' ) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throw new ValidationException(resourceBundleName,"errorCode4");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster int strIndex = strData.indexOf("T");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster timeStr = strData.substring(strIndex+1,strData.length());
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster dateStr = strData.substring(1,strIndex);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // time elements without T not allowed.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (strData.indexOf("H") != -1 || strData.indexOf("S") != -1) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throw new ValidationException(resourceBundleName,"errorCode4");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster dateStr = strData.substring(1);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster int start = 0;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster processTimeStr(timeStr);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster processDateStr(dateStr);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private int getIntegerValue(String strData, int start, int end)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throws ValidationException
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster int value = 0;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster String str = strData.substring(start, end);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster try {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster value = Integer.parseInt(str);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (value < 0) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throw new ValidationException(resourceBundleName, "errorCode4");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } catch (NumberFormatException e) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throw new ValidationException(resourceBundleName, "errorCode4");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return value;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private double getDoubleValue(String strData, int start, int end)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throws ValidationException
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster double value = 0;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster String str = strData.substring(start, end);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster try {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster value = Double.parseDouble(str);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (value < 0) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throw new ValidationException(resourceBundleName, "errorCode4");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } catch (NumberFormatException e) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throw new ValidationException(resourceBundleName, "errorCode4");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return value;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /* Process the Time String in the Duration */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private void processTimeStr(String timeStr) throws ValidationException {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (timeStr != null) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((timeStr.indexOf("Y") != -1) || (timeStr.indexOf("D") != -1)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throw new ValidationException(resourceBundleName, "errorCode4");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // Seconds should be preceded by a decimal number , if there
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // is a "." then should have some number after it.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster int idxH = timeStr.indexOf('H');
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster int idxM = timeStr.indexOf('M');
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster int idxS = timeStr.indexOf('S');
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((idxH != -1) && ((idxM != -1 && idxM < idxH)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster || (idxS != -1 && idxS < idxH))) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throw new ValidationException(resourceBundleName,"errorCode4");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((idxM != -1) && (idxS != -1 && idxS < idxM)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throw new ValidationException(resourceBundleName,"errorCode4");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster int start=0;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (idxH != -1) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster int a = getIntegerValue(timeStr,start,idxH);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster idxM = timeStr.indexOf('M',idxH+1);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster start = idxH+1;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (idxM != -1) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster int b = getIntegerValue(timeStr,start,idxM);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster idxS = timeStr.indexOf('S',idxM +1);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster start = idxM + 1;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (idxS != -1) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (timeStr.charAt(idxS-1) == '.') {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throw new ValidationException(
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster resourceBundleName, "errorCode4");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster getDoubleValue(timeStr,start,idxS);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /* Process the Date String in the Duration */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster private void processDateStr(String dateStr) throws ValidationException {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (dateStr != null) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((dateStr.indexOf("H") != 1) && (dateStr.indexOf("S") != -1)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throw new ValidationException(resourceBundleName,"errorCode4");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster int idxY = dateStr.indexOf('Y');
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster int idxM = dateStr.indexOf('M');
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster int idxD = dateStr.indexOf('D');
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((idxY != -1) && ((idxM != -1 && idxM < idxY)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster || (idxD != -1 && idxD < idxY))) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throw new ValidationException(resourceBundleName,"errorCode4");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((idxM != -1) && (idxD != -1 && idxD < idxM)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster throw new ValidationException(resourceBundleName,"errorCode4");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster int start = 0;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (idxY != -1) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster getIntegerValue(dateStr, start, idxY);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster idxM = dateStr.indexOf('M',idxY+1);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster start = idxY +1;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (idxM != -1) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster getIntegerValue(dateStr,start,idxM);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster idxD = dateStr.indexOf('D',idxM+1);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster start = idxM + 1;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (idxD != -1) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster getIntegerValue(dateStr, start, idxD);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster}