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
019package org.apache.oozie.util;
020
021import java.io.IOException;
022import java.text.ParseException;
023import java.text.SimpleDateFormat;
024import java.util.Date;
025import java.util.HashSet;
026import java.util.Map;
027
028import org.apache.commons.lang.StringUtils;
029import org.apache.oozie.ErrorCode;
030import org.apache.oozie.client.rest.RestConstants;
031import org.apache.oozie.command.CommandException;
032
033public class XLogUserFilterParam {
034
035    public static final String START_TIME = "START";
036
037    public static final String END_TIME = "END";
038
039    public static final String SEARCH_TEXT = "TEXT";
040
041    public static final String LOG_LEVEL = "LOGLEVEL";
042
043    public static final String LIMIT = "LIMIT";
044
045    public static final String RECENT_LOG_OFFSET = "RECENT";
046
047    public static final String DEBUG = "DEBUG";
048
049    private Date startTime;
050    private Date endTime;
051    private int startOffset;
052    private int endOffset = -1;
053    private int recent = -1;
054    private String logLevel;
055    private int limit = -1;
056    private boolean isDebug = false;
057    private String searchText;
058
059    private String params;
060
061    public static final ThreadLocal<SimpleDateFormat> dt = new ThreadLocal<SimpleDateFormat>() {
062        @Override
063        protected SimpleDateFormat initialValue() {
064            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
065        }
066    };
067
068    static final HashSet<String> LOG_LEVELS = new HashSet<String>();
069    static {
070        LOG_LEVELS.add("ALL");
071        LOG_LEVELS.add("DEBUG");
072        LOG_LEVELS.add("ERROR");
073        LOG_LEVELS.add("INFO");
074        LOG_LEVELS.add("TRACE");
075        LOG_LEVELS.add("WARN");
076        LOG_LEVELS.add("FATAL");
077    }
078
079    public XLogUserFilterParam() {
080    }
081
082    /**
083     * Instantiates a new log user param.
084     *
085     * @param params the params
086     * @throws CommandException the command exception
087     */
088    public XLogUserFilterParam(Map<String, String[]> params) throws CommandException {
089        if (params != null && params.get(RestConstants.LOG_FILTER_OPTION) != null
090                && params.get(RestConstants.LOG_FILTER_OPTION).length > 0) {
091            try {
092                parseFilterParam(params.get(RestConstants.LOG_FILTER_OPTION)[0]);
093            }
094            catch (Exception e) {
095               throw new CommandException(ErrorCode.E0302, e.getMessage());
096
097            }
098        }
099    }
100
101    /**
102     * Parse filter param
103     *
104     * @param param the param
105     * @param map the map
106     * @throws Exception
107     */
108    private void parseFilterParam(String param) throws Exception {
109        this.params = param;
110
111        if (StringUtils.isEmpty(param)) {
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     * @throws CommandException
198     */
199    public void validateLogLevel(String loglevel) throws CommandException {
200        if (StringUtils.isEmpty(loglevel)) {
201            return;
202        }
203        for (String level : getLogLevel().split("\\|")) {
204            if (!LOG_LEVELS.contains(level)) {
205                throw new CommandException(ErrorCode.E0302, "Supported log level are " + LOG_LEVELS.toString());
206            }
207        }
208    }
209
210    /**
211     * Validate search text.
212     *
213     * @throws CommandException the command exception
214     */
215    public void validateSearchText() throws CommandException {
216        // No restriction on search text.
217
218    }
219
220    /**
221     * Gets the date. Date can in TZ or yyyy-MM-dd HH:mm:ss,SSS format
222     *
223     * @param String date
224     * @return the date
225     */
226    public Date getDate(String date) {
227        try {
228            return DateUtils.parseDateOozieTZ(date);
229        }
230        catch (ParseException e) {
231            try {
232                return dt.get().parse(date);
233            }
234            catch (ParseException e1) {
235                return null;
236            }
237        }
238    }
239
240    /**
241     * Checks if is debug.
242     *
243     * @return true, if it's debug
244     */
245    public boolean isDebug() {
246        return isDebug;
247    }
248
249    public Date getEndTime() {
250        return endTime;
251    }
252
253    public int getEndOffset() {
254        return endOffset;
255    }
256
257    public int getRecent() {
258        return recent;
259    }
260
261    public int getLimit() {
262        return limit;
263    }
264
265    public int getStartOffset() {
266        return startOffset;
267    }
268
269    @Override
270    public String toString() {
271        return params;
272    }
273
274    private int getOffsetInMinute(String offset) throws IOException {
275
276        if (Character.isLetter(offset.charAt(offset.length() - 1))) {
277            switch (offset.charAt(offset.length() - 1)) {
278                case 'H':
279                case 'h':
280                    return Integer.parseInt(offset.substring(0, offset.length() - 1)) * 60;
281                case 'M':
282                case 'm':
283                    return Integer.parseInt(offset.substring(0, offset.length() - 1));
284                default:
285                    throw new IOException("Unsupported offset " + offset);
286            }
287        }
288        else {
289            if (StringUtils.isNumeric(offset)) {
290                return Integer.parseInt(offset) * 60;
291            }
292            else {
293                throw new IOException("Unsupported time : " + offset);
294            }
295        }
296    }
297
298}