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     * @param map the map
107     * @throws Exception
108     */
109    private void parseFilterParam(String param) throws Exception {
110        this.params = param;
111
112        if (StringUtils.isEmpty(param) || StringUtils.equalsIgnoreCase(param, "null")) {
113            return;
114        }
115        for (String keyValue : param.split(";")) {
116            String[] pairs = keyValue.split("=");
117            String key = pairs[0].toUpperCase();
118            String value = pairs.length == 1 ? "" : pairs[1];
119            if (key.equals(START_TIME)) {
120                startTime = getDate(value);
121                if (startTime == null) {
122                    startOffset = getOffsetInMinute(value);
123                }
124            }
125            else if (key.equals(END_TIME)) {
126                endTime = getDate(value);
127                if (endTime == null) {
128                    endOffset = getOffsetInMinute(value);
129                }
130
131            }
132            else if (key.equals(RECENT_LOG_OFFSET)) {
133                recent = getOffsetInMinute(value);
134            }
135            else if (key.equals(LIMIT)) {
136                limit = Integer.parseInt(value);
137
138            }
139            else if (key.equals(LOG_LEVEL)) {
140                logLevel = value;
141                validateLogLevel(logLevel);
142
143            }
144            else if (key.equals(DEBUG)) {
145                isDebug = true;
146
147            }
148            else if (key.equals(SEARCH_TEXT)) {
149                searchText = value;
150
151            }
152            else {
153                throw new Exception("Unsupported log filter " + key);
154            }
155        }
156    }
157
158    /**
159     * Gets the log level.
160     *
161     * @return the log level
162     */
163    public String getLogLevel() {
164        return logLevel;
165
166    }
167
168    /**
169     * Gets the start date.
170     *
171     * @return the start date
172     */
173    public Date getStartDate() {
174        return startTime;
175    }
176
177    /**
178     * Gets the end date.
179     *
180     * @return the end date
181     */
182    public Date getEndDate() {
183        return endTime;
184    }
185
186    /**
187     * Gets the search text.
188     *
189     * @return the search text
190     */
191    public String getSearchText() {
192        return searchText;
193    }
194
195    /**
196     * Validate log level.
197     *
198     * @throws CommandException
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}