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, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019
020package org.apache.oozie.util;
021
022import java.io.IOException;
023import java.text.ParseException;
024import java.text.SimpleDateFormat;
025import java.util.Date;
026import java.util.HashSet;
027import java.util.Map;
028
029import org.apache.commons.lang.StringUtils;
030import org.apache.oozie.ErrorCode;
031import org.apache.oozie.client.rest.RestConstants;
032import org.apache.oozie.command.CommandException;
033
034public class XLogUserFilterParam {
035
036    public static final String START_TIME = "START";
037
038    public static final String END_TIME = "END";
039
040    public static final String SEARCH_TEXT = "TEXT";
041
042    public static final String LOG_LEVEL = "LOGLEVEL";
043
044    public static final String LIMIT = "LIMIT";
045
046    public static final String RECENT_LOG_OFFSET = "RECENT";
047
048    public static final String DEBUG = "DEBUG";
049
050    private Date startTime;
051    private Date endTime;
052    private int startOffset;
053    private int endOffset = -1;
054    private int recent = -1;
055    private String logLevel;
056    private int limit = -1;
057    private boolean isDebug = false;
058    private String searchText;
059
060    private String params;
061
062    public static final ThreadLocal<SimpleDateFormat> dt = new ThreadLocal<SimpleDateFormat>() {
063        @Override
064        protected SimpleDateFormat initialValue() {
065            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
066        }
067    };
068
069    static final HashSet<String> LOG_LEVELS = new HashSet<String>();
070    static {
071        LOG_LEVELS.add("ALL");
072        LOG_LEVELS.add("DEBUG");
073        LOG_LEVELS.add("ERROR");
074        LOG_LEVELS.add("INFO");
075        LOG_LEVELS.add("TRACE");
076        LOG_LEVELS.add("WARN");
077        LOG_LEVELS.add("FATAL");
078    }
079
080    public XLogUserFilterParam() {
081    }
082
083    /**
084     * Instantiates a new log user param.
085     *
086     * @param params the params
087     * @throws CommandException the command exception
088     */
089    public XLogUserFilterParam(Map<String, String[]> params) throws CommandException {
090        if (params != null && params.get(RestConstants.LOG_FILTER_OPTION) != null
091                && params.get(RestConstants.LOG_FILTER_OPTION).length > 0) {
092            try {
093                parseFilterParam(params.get(RestConstants.LOG_FILTER_OPTION)[0]);
094            }
095            catch (Exception e) {
096               throw new CommandException(ErrorCode.E0302, e.getMessage());
097
098            }
099        }
100    }
101
102    /**
103     * Parse filter param
104     *
105     * @param param the param
106     * @throws Exception
107     */
108    private void parseFilterParam(String param) throws Exception {
109        this.params = param;
110
111        if (StringUtils.isEmpty(param) || StringUtils.equalsIgnoreCase(param, "null")) {
112            return;
113        }
114        for (String keyValue : param.split(";")) {
115            String[] pairs = keyValue.split("=");
116            String key = pairs[0].toUpperCase();
117            String value = pairs.length == 1 ? "" : pairs[1];
118            if (key.equals(START_TIME)) {
119                startTime = getDate(value);
120                if (startTime == null) {
121                    startOffset = getOffsetInMinute(value);
122                }
123            }
124            else if (key.equals(END_TIME)) {
125                endTime = getDate(value);
126                if (endTime == null) {
127                    endOffset = getOffsetInMinute(value);
128                }
129
130            }
131            else if (key.equals(RECENT_LOG_OFFSET)) {
132                recent = getOffsetInMinute(value);
133            }
134            else if (key.equals(LIMIT)) {
135                limit = Integer.parseInt(value);
136
137            }
138            else if (key.equals(LOG_LEVEL)) {
139                logLevel = value;
140                validateLogLevel(logLevel);
141
142            }
143            else if (key.equals(DEBUG)) {
144                isDebug = true;
145
146            }
147            else if (key.equals(SEARCH_TEXT)) {
148                searchText = value;
149
150            }
151            else {
152                throw new Exception("Unsupported log filter " + key);
153            }
154        }
155    }
156
157    /**
158     * Gets the log level.
159     *
160     * @return the log level
161     */
162    public String getLogLevel() {
163        return logLevel;
164
165    }
166
167    /**
168     * Gets the start date.
169     *
170     * @return the start date
171     */
172    public Date getStartDate() {
173        return startTime;
174    }
175
176    /**
177     * Gets the end date.
178     *
179     * @return the end date
180     */
181    public Date getEndDate() {
182        return endTime;
183    }
184
185    /**
186     * Gets the search text.
187     *
188     * @return the search text
189     */
190    public String getSearchText() {
191        return searchText;
192    }
193
194    /**
195     * Validate log level.
196     *
197     * @param loglevel the log level to validate
198     * @throws CommandException in case of a non-supported log level.
199     */
200    public void validateLogLevel(String loglevel) throws CommandException {
201        if (StringUtils.isEmpty(loglevel)) {
202            return;
203        }
204        for (String level : getLogLevel().split("\\|")) {
205            if (!LOG_LEVELS.contains(level)) {
206                throw new CommandException(ErrorCode.E0302, "Supported log level are " + LOG_LEVELS.toString());
207            }
208        }
209    }
210
211    /**
212     * Validate search text.
213     *
214     * @throws CommandException the command exception
215     */
216    public void validateSearchText() throws CommandException {
217        // No restriction on search text.
218
219    }
220
221    /**
222     * Gets the date. Date can in TZ or yyyy-MM-dd HH:mm:ss,SSS format
223     *
224     * @param date date
225     * @return the date
226     */
227    public Date getDate(String date) {
228        try {
229            return DateUtils.parseDateOozieTZ(date);
230        }
231        catch (ParseException e) {
232            try {
233                return dt.get().parse(date);
234            }
235            catch (ParseException e1) {
236                return null;
237            }
238        }
239    }
240
241    /**
242     * Checks if is debug.
243     *
244     * @return true, if it's debug
245     */
246    public boolean isDebug() {
247        return isDebug;
248    }
249
250    public Date getEndTime() {
251        return endTime;
252    }
253
254    public int getEndOffset() {
255        return endOffset;
256    }
257
258    public int getRecent() {
259        return recent;
260    }
261
262    public int getLimit() {
263        return limit;
264    }
265
266    public int getStartOffset() {
267        return startOffset;
268    }
269
270    @Override
271    public String toString() {
272        return params;
273    }
274
275    private int getOffsetInMinute(String offset) throws IOException {
276
277        if (Character.isLetter(offset.charAt(offset.length() - 1))) {
278            switch (offset.charAt(offset.length() - 1)) {
279                case 'h':
280                    return Integer.parseInt(offset.substring(0, offset.length() - 1)) * 60;
281                case 'm':
282                    return Integer.parseInt(offset.substring(0, offset.length() - 1));
283                default:
284                    throw new IOException("Unsupported offset " + offset);
285            }
286        }
287        else {
288            if (StringUtils.isNumeric(offset)) {
289                return Integer.parseInt(offset) * 60;
290            }
291            else {
292                throw new IOException("Unsupported time : " + offset);
293            }
294        }
295    }
296
297}