All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.ws.security.util.XmlSchemaDateFormat Maven / Gradle / Ivy

Go to download

The Apache WSS4J project provides a Java implementation of the primary security standards for Web Services, namely the OASIS Web Services Security (WS-Security) specifications from the OASIS Web Services Security TC.

There is a newer version: 1.6.19
Show newest version
/*
 * Copyright  2003-2005 The Apache Software Foundation.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package org.apache.ws.security.util;

import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.TimeZone;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * A {@link DateFormat} for the format of the dateTime simpleType as specified in the
 * XML Schema specification. See 
 * XML Schema Part 2: Datatypes, W3C Recommendation 02 May 2001, Section 3.2.7.1.
 *
 * @author Ian P. Springer
 * @author Werner Dittmann
 */
public class XmlSchemaDateFormat extends DateFormat {
	/**
	 * Logger.
	 */
	private static Log log = LogFactory.getLog(XmlSchemaDateFormat.class);

	private static boolean doDebug = false;

	static {
		doDebug = log.isDebugEnabled();
	}

	/**
	 * Message retriever.
	 */
	//   private static final MessageRetriever MSG = ResourceKeys.MSG;
	/**
	 * DateFormat for Zulu (UTC) form of an XML Schema dateTime string.
	 */
	private static final DateFormat DATEFORMAT_XSD_ZULU = new SimpleDateFormat(
			"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

	static {
		DATEFORMAT_XSD_ZULU.setTimeZone(TimeZone.getTimeZone("UTC"));
	}

	/**
	 * This method was snarfed from org.apache.axis.encoding.ser.CalendarDeserializer,
	 * which was written by Sam Ruby ([email protected]) and Rich Scheuerle ([email protected]).
	 * Better error reporting was added.
	 *
	 * @see DateFormat#parse(java.lang.String)
	 */
	public Date parse(String src, ParsePosition parse_pos) {
		Date date;

		// validate fixed portion of format
		int index = 0;
		try {
			if (src != null) {
				if ((src.charAt(0) == '+') || (src.charAt(0) == '-')) {
					src = src.substring(1);
				}

				if (src.length() < 19) {
					parse_pos.setIndex(src.length() - 1);
					handleParseError(parse_pos, "TOO_FEW_CHARS");
				}
				validateChar(src, parse_pos, index = 4, '-', "EXPECTED_DASH");
				validateChar(src, parse_pos, index = 7, '-', "EXPECTED_DASH");
				validateChar(src, parse_pos, index = 10, 'T', "EXPECTED_CAPITAL_T");
				validateChar(src, parse_pos, index = 13, ':', "EXPECTED_COLON_IN_TIME");
				validateChar(src, parse_pos, index = 16, ':', "EXPECTED_COLON_IN_TIME");
			}

			// convert what we have validated so far
			try {
				synchronized (DATEFORMAT_XSD_ZULU) {
					date = DATEFORMAT_XSD_ZULU.parse((src == null) ? null
							: (src.substring(0, 19) + ".000Z"));
				}
			} catch (Exception e) {
				throw new NumberFormatException(e.toString());
			}

			index = 19;

			// parse optional milliseconds
			if (src != null) {
				if ((index < src.length()) && (src.charAt(index) == '.')) {
					int milliseconds = 0;
					int start = ++index;

					while ((index < src.length())
							&& Character.isDigit(src.charAt(index))) {
						index++;
					}

					String decimal = src.substring(start, index);

					if (decimal.length() == 3) {
						milliseconds = Integer.parseInt(decimal);
					} else if (decimal.length() < 3) {
						milliseconds = Integer.parseInt((decimal + "000")
								.substring(0, 3));
					} else {
						milliseconds = Integer
								.parseInt(decimal.substring(0, 3));

						if (decimal.charAt(3) >= '5') {
							++milliseconds;
						}
					}

					// add milliseconds to the current date
					date.setTime(date.getTime() + milliseconds);
				}

				// parse optional timezone
				if (((index + 5) < src.length())
						&& ((src.charAt(index) == '+') || (src.charAt(index) == '-'))) {
					validateCharIsDigit(src, parse_pos, index + 1, "EXPECTED_NUMERAL");
					validateCharIsDigit(src, parse_pos, index + 2, "EXPECTED_NUMERAL");
					validateChar(src, parse_pos, index + 3, ':', "EXPECTED_COLON_IN_TIMEZONE");
					validateCharIsDigit(src, parse_pos, index + 4, "EXPECTED_NUMERAL");
					validateCharIsDigit(src, parse_pos, index + 5, "EXPECTED_NUMERAL");

					final int hours = (((src.charAt(index + 1) - '0') * 10) + src
							.charAt(index + 2)) - '0';
					final int mins = (((src.charAt(index + 4) - '0') * 10) + src
							.charAt(index + 5)) - '0';
					int millisecs = ((hours * 60) + mins) * 60 * 1000;

					// subtract millisecs from current date to obtain GMT
					if (src.charAt(index) == '+') {
						millisecs = -millisecs;
					}

					date.setTime(date.getTime() + millisecs);
					index += 6;
				}

				if ((index < src.length()) && (src.charAt(index) == 'Z')) {
					index++;
				}

				if (index < src.length()) {
					handleParseError(parse_pos, "TOO_MANY_CHARS");
				}
			}
		} catch (ParseException pe) {
			log.error(pe.toString());
			index = 0; // IMPORTANT: this tells DateFormat.parse() to throw a ParseException
			parse_pos.setErrorIndex(index);
			date = null;
		}
		parse_pos.setIndex(index);
		return (date);
	}

	/**
	 * @see DateFormat#format(java.util.Date)
	 */
	public StringBuffer format(Date date, StringBuffer append_buf,
			FieldPosition field_pos) {
		String str;

		synchronized (DATEFORMAT_XSD_ZULU) {
			str = DATEFORMAT_XSD_ZULU.format(date);
		}

		if (append_buf == null) {
			append_buf = new StringBuffer();
		}

		append_buf.append(str);

		return (append_buf);
	}

	private void validateChar(String str, ParsePosition parse_pos, int index,
			char expected, String error_reason) throws ParseException {
		if (str.charAt(index) != expected) {
			handleParseError(parse_pos, error_reason);
		}
	}

	private void validateCharIsDigit(String str, ParsePosition parse_pos,
			int index, String error_reason) throws ParseException {
		if (!Character.isDigit(str.charAt(index))) {
			handleParseError(parse_pos, error_reason);
		}
	}

	private void handleParseError(ParsePosition parse_pos, String error_reason)
			throws ParseException {
		throw new ParseException("INVALID_XSD_DATETIME", parse_pos.getErrorIndex());
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy