001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.converter; 018 019import java.util.regex.Matcher; 020import java.util.regex.Pattern; 021 022import org.apache.camel.Converter; 023import org.slf4j.Logger; 024import org.slf4j.LoggerFactory; 025 026/** 027 * Converter from String syntax to milli seconds. 028 * Code is copied to org.apache.camel.catalog.TimePatternConverter in camel-catalog 029 */ 030@Converter 031public final class TimePatternConverter { 032 private static final Logger LOG = LoggerFactory.getLogger(TimePatternConverter.class); 033 private static final Pattern NUMBERS_ONLY_STRING_PATTERN = Pattern.compile("^[-]?(\\d)+$", Pattern.CASE_INSENSITIVE); 034 private static final Pattern HOUR_REGEX_PATTERN = Pattern.compile("((\\d)*(\\d))h(our(s)?)?", Pattern.CASE_INSENSITIVE); 035 private static final Pattern MINUTES_REGEX_PATTERN = Pattern.compile("((\\d)*(\\d))m(in(ute(s)?)?)?", Pattern.CASE_INSENSITIVE); 036 private static final Pattern SECONDS_REGEX_PATTERN = Pattern.compile("((\\d)*(\\d))s(ec(ond)?(s)?)?", Pattern.CASE_INSENSITIVE); 037 038 /** 039 * Utility classes should not have a public constructor. 040 */ 041 private TimePatternConverter() { 042 } 043 044 @Converter 045 public static long toMilliSeconds(String source) throws IllegalArgumentException { 046 // quick conversion if its only digits 047 boolean digit = true; 048 for (int i = 0; i < source.length(); i++) { 049 char ch = source.charAt(i); 050 // special for fist as it can be negative number 051 if (i == 0 && ch == '-') { 052 continue; 053 } 054 // quick check if its 0..9 055 if (ch < '0' || ch > '9') { 056 digit = false; 057 break; 058 } 059 } 060 if (digit) { 061 return Long.valueOf(source); 062 } 063 064 long milliseconds = 0; 065 boolean foundFlag = false; 066 067 checkCorrectnessOfPattern(source); 068 Matcher matcher; 069 070 matcher = createMatcher(NUMBERS_ONLY_STRING_PATTERN, source); 071 if (matcher.find()) { 072 // Note: This will also be used for regular numeric strings. 073 // This String -> long converter will be used for all strings. 074 milliseconds = Long.valueOf(source); 075 } else { 076 matcher = createMatcher(HOUR_REGEX_PATTERN, source); 077 if (matcher.find()) { 078 milliseconds = milliseconds + (3600000 * Long.valueOf(matcher.group(1))); 079 foundFlag = true; 080 } 081 082 matcher = createMatcher(MINUTES_REGEX_PATTERN, source); 083 if (matcher.find()) { 084 long minutes = Long.valueOf(matcher.group(1)); 085 if ((minutes > 59) && foundFlag) { 086 throw new IllegalArgumentException("Minutes should contain a valid value between 0 and 59: " + source); 087 } 088 foundFlag = true; 089 milliseconds = milliseconds + (60000 * minutes); 090 } 091 092 matcher = createMatcher(SECONDS_REGEX_PATTERN, source); 093 if (matcher.find()) { 094 long seconds = Long.valueOf(matcher.group(1)); 095 if ((seconds > 59) && foundFlag) { 096 throw new IllegalArgumentException("Seconds should contain a valid value between 0 and 59: " + source); 097 } 098 foundFlag = true; 099 milliseconds = milliseconds + (1000 * seconds); 100 } 101 102 // No pattern matched... initiating fallback check and conversion (if required). 103 // The source at this point may contain illegal values or special characters 104 if (!foundFlag) { 105 milliseconds = Long.valueOf(source); 106 } 107 } 108 109 LOG.trace("source: {} milliseconds: ", source, milliseconds); 110 111 return milliseconds; 112 } 113 114 private static void checkCorrectnessOfPattern(String source) { 115 //replace only numbers once 116 Matcher matcher = createMatcher(NUMBERS_ONLY_STRING_PATTERN, source); 117 String replaceSource = matcher.replaceFirst(""); 118 119 //replace hour string once 120 matcher = createMatcher(HOUR_REGEX_PATTERN, replaceSource); 121 if (matcher.find() && matcher.find()) { 122 throw new IllegalArgumentException("Hours should not be specified more then once: " + source); 123 } 124 replaceSource = matcher.replaceFirst(""); 125 126 //replace minutes once 127 matcher = createMatcher(MINUTES_REGEX_PATTERN, replaceSource); 128 if (matcher.find() && matcher.find()) { 129 throw new IllegalArgumentException("Minutes should not be specified more then once: " + source); 130 } 131 replaceSource = matcher.replaceFirst(""); 132 133 //replace seconds once 134 matcher = createMatcher(SECONDS_REGEX_PATTERN, replaceSource); 135 if (matcher.find() && matcher.find()) { 136 throw new IllegalArgumentException("Seconds should not be specified more then once: " + source); 137 } 138 replaceSource = matcher.replaceFirst(""); 139 140 if (replaceSource.length() > 0) { 141 throw new IllegalArgumentException("Illegal characters: " + source); 142 } 143 } 144 145 private static Matcher createMatcher(Pattern pattern, String source) { 146 return pattern.matcher(source); 147 } 148}