org.chililog.server.workbench.workers.RepositoryRuntimeWorker.java Source code

Java tutorial

Introduction

Here is the source code for org.chililog.server.workbench.workers.RepositoryRuntimeWorker.java

Source

//
// Copyright 2010 Cinch Logic Pty Ltd.
//
// http://www.chililog.com
//
// 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.chililog.server.workbench.workers;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.naming.OperationNotSupportedException;

import org.apache.commons.lang.StringUtils;
import org.bson.types.ObjectId;
import org.chililog.server.common.ChiliLogException;
import org.chililog.server.data.MongoConnection;
import org.chililog.server.data.MongoJsonSerializer;
import org.chililog.server.data.RepositoryConfigBO.Status;
import org.chililog.server.data.RepositoryEntryController;
import org.chililog.server.data.RepositoryEntryListCriteria;
import org.chililog.server.data.UserBO;
import org.chililog.server.data.RepositoryEntryListCriteria.QueryType;
import org.chililog.server.engine.Repository;
import org.chililog.server.engine.RepositoryService;
import org.chililog.server.workbench.Strings;
import org.jboss.netty.handler.codec.http.HttpMethod;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBObject;

/**
 * <p>
 * Repository Runtime Info worker provides the following services to manage repositories at run time:
 * <ul>
 * <li>start all - HTTP POST /api/repositories?action=start</li>
 * <li>start one - HTTP POST /api/repositories/{id}?action=start</li>
 * <li>stop all - HTTP POST /api/repositories?action=stop</li>
 * <li>stop one - HTTP POST /api/repositories/{id}?action=stop</li>
 * <li>reload all - HTTP POST /api/repositories?action=reload</li>
 * <li>read all - HTTP GET /api/repositories</li>
 * <li>read one - HTTP GET /api/repositories/{id}</li>
 * <li>read entry - HTTP GET /api/repositories/{id}/entries?query_type=find</li>
 * </p>
 * <p>
 * Runtime information refers to the current status of an instance of a repository.
 * </p>
 */
public class RepositoryRuntimeWorker extends Worker {

    public static final String ACTION_URI_QUERYSTRING_PARAMETER_NAME = "action";
    public static final String ONLINE_OPERATION = "online";
    public static final String READONLY_OPERATION = "readonly";
    public static final String OFFLINE_OPERATION = "offline";

    public static final String ENTRY_QUERY_TYPE_QUERYSTRING_PARAMETER_NAME = "query_type";
    public static final String ENTRY_QUERY_FIELDS_QUERYSTRING_PARAMETER_NAME = "fields";
    public static final String ENTRY_QUERY_FROM_TIMESTAMP_QUERYSTRING_PARAMETER_NAME = "from";
    public static final String ENTRY_QUERY_TO_TIMESTAMP_QUERYSTRING_PARAMETER_NAME = "to";
    public static final String ENTRY_QUERY_KEYWORD_USAGE_QUERYSTRING_PARAMETER_NAME = "keyword_usage";
    public static final String ENTRY_QUERY_KEYWORDS_QUERYSTRING_PARAMETER_NAME = "keywords";
    public static final String ENTRY_QUERY_SEVERITY_QUERYSTRING_PARAMETER_NAME = "severity";
    public static final String ENTRY_QUERY_HOST_QUERYSTRING_PARAMETER_NAME = "host";
    public static final String ENTRY_QUERY_SOURCE_QUERYSTRING_PARAMETER_NAME = "source";
    public static final String ENTRY_QUERY_CONDITIONS_QUERYSTRING_PARAMETER_NAME = "conditions";
    public static final String ENTRY_QUERY_ORDER_BY_QUERYSTRING_PARAMETER_NAME = "order_by";
    public static final String ENTRY_QUERY_INITIAL_QUERYSTRING_PARAMETER_NAME = "initial";
    public static final String ENTRY_QUERY_REDUCE_QUERYSTRING_PARAMETER_NAME = "reduce";
    public static final String ENTRY_QUERY_FINALIZE_QUERYSTRING_PARAMETER_NAME = "finalize";

    public static final String ENTRY_QUERY_TYPE_HEADER_NAME = "X-ChiliLog-Query-Type";
    public static final String ENTRY_QUERY_FIELDS_HEADER_NAME = "X-ChiliLog-Fields";
    public static final String ENTRY_QUERY_FROM_TIMESTAMP_HEADER_NAME = "X-ChiliLog-From";
    public static final String ENTRY_QUERY_TO_TIMESTAMP_HEADER_NAME = "X-ChiliLog-To";
    public static final String ENTRY_QUERY_KEYWORD_USAGE_HEADER_NAME = "X-ChiliLog-Keywords-Usage";
    public static final String ENTRY_QUERY_KEYWORDS_HEADER_NAME = "X-ChiliLog-Keywords";
    public static final String ENTRY_QUERY_SEVERITY_HEADER_NAME = "X-ChiliLog-Severity";
    public static final String ENTRY_QUERY_HOST_HEADER_NAME = "X-ChiliLog-Host";
    public static final String ENTRY_QUERY_SOURCE_HEADER_NAME = "X-ChiliLog-Source";
    public static final String ENTRY_QUERY_CONDITIONS_HEADER_NAME = "X-ChiliLog-Conditions";
    public static final String ENTRY_QUERY_ORDER_BY_HEADER_NAME = "X-ChiliLog-Order-By";
    public static final String ENTRY_QUERY_INITIAL_HEADER_NAME = "X-ChiliLog-Initial";
    public static final String ENTRY_QUERY_REDUCE_HEADER_NAME = "X-ChiliLog-Reduce";
    public static final String ENTRY_QUERY_FINALIZE_HEADER_NAME = "X-ChiliLog-Finalize";

    /**
     * Constructor
     */
    public RepositoryRuntimeWorker(HttpRequest request) {
        super(request);
        return;
    }

    /**
     * Can only create and delete sessions
     */
    @Override
    public HttpMethod[] getSupportedMethods() {
        return new HttpMethod[] { HttpMethod.GET, HttpMethod.POST };
    }

    /**
     * Let's validate if the user is able to access these functions
     */
    @Override
    protected ApiResult validateAuthenticatedUserRole() {
        // Do checks when we execute
        return new ApiResult();
    }

    /**
     * Start
     * 
     * @throws Exception
     */
    @Override
    public ApiResult processPost(Object requestContent) throws Exception {
        try {
            UserBO user = this.getAuthenticatedUser();
            String action = this.getUriQueryStringParameter(ACTION_URI_QUERYSTRING_PARAMETER_NAME, false);
            Object responseContent = null;

            if (this.getUriPathParameters() == null || this.getUriPathParameters().length == 0) {
                // Start/Stop/Reload all
                // Only available to system administrators

                if (!user.isSystemAdministrator()) {
                    return new ApiResult(HttpResponseStatus.UNAUTHORIZED,
                            new ChiliLogException(Strings.NOT_AUTHORIZED_ERROR));
                }

                if (action.equalsIgnoreCase(ONLINE_OPERATION)) {
                    RepositoryService.getInstance().bringAllRepositoriesOnline();
                } else if (action.equalsIgnoreCase(OFFLINE_OPERATION)) {
                    RepositoryService.getInstance().takeAllRepositoriesOffline();
                } else {
                    throw new UnsupportedOperationException(String.format("Action '%s' not supported.", action));
                }

                Repository[] list = RepositoryService.getInstance().getRepositories();
                if (list != null && list.length > 0) {
                    ArrayList<RepositoryStatusAO> aoList = new ArrayList<RepositoryStatusAO>();
                    for (Repository repo : list) {
                        aoList.add(new RepositoryStatusAO(repo));
                    }

                    if (!aoList.isEmpty()) {
                        responseContent = aoList.toArray(new RepositoryStatusAO[] {});
                    }
                }
            } else {
                // Online/ReadOnly/Offline specific one
                // Only available to system administrators and repo admin
                String id = this.getUriPathParameters()[ID_URI_PATH_PARAMETER_INDEX];
                ObjectId objectId = parseDocumentObjectID(id);
                Repository repo = RepositoryService.getInstance().getRepository(objectId);

                if (!user.isSystemAdministrator()
                        && !user.hasRole(repo.getRepoConfig().getAdministratorRoleName())) {
                    return new ApiResult(HttpResponseStatus.UNAUTHORIZED,
                            new ChiliLogException(Strings.NOT_AUTHORIZED_ERROR));
                }

                if (action.equalsIgnoreCase(ONLINE_OPERATION)) {
                    repo = RepositoryService.getInstance()
                            .bringRepositoryOnline(repo.getRepoConfig().getDocumentID());
                    responseContent = new RepositoryStatusAO(repo);
                } else if (action.equalsIgnoreCase(READONLY_OPERATION)) {
                    repo = RepositoryService.getInstance()
                            .makeRepositoryReadOnly(repo.getRepoConfig().getDocumentID());
                    responseContent = new RepositoryStatusAO(repo);
                } else if (action.equalsIgnoreCase(OFFLINE_OPERATION)) {
                    RepositoryService.getInstance().takeRepositoryOffline(repo.getRepoConfig().getDocumentID());
                    repo = RepositoryService.getInstance().getRepository(objectId);
                    responseContent = new RepositoryStatusAO(repo);
                } else {
                    throw new UnsupportedOperationException(String.format("Action '%s' not supported.", action));
                }
            }

            // Return response
            return new ApiResult(this.getAuthenticationToken(), JSON_CONTENT_TYPE, responseContent);
        } catch (Exception ex) {
            return new ApiResult(HttpResponseStatus.BAD_REQUEST, ex);
        }
    }

    /**
     * Read
     * 
     * @throws Exception
     */
    @SuppressWarnings("rawtypes")
    @Override
    public ApiResult processGet() throws Exception {
        try {
            UserBO user = this.getAuthenticatedUser();
            List<String> allowedRepositories = Arrays.asList(this.getAuthenticatedUserAllowedRepository());

            DB db = MongoConnection.getInstance().getConnection();
            Object responseContent = null;

            // Get info on all repositories
            // HTTP GET /api/repositories
            if (this.getUriPathParameters() == null || this.getUriPathParameters().length == 0) {
                Repository[] list = RepositoryService.getInstance().getRepositories();
                if (list != null && list.length > 0) {
                    ArrayList<RepositoryStatusAO> aoList = new ArrayList<RepositoryStatusAO>();
                    for (Repository repo : list) {
                        if (user.isSystemAdministrator()
                                || allowedRepositories.contains(repo.getRepoConfig().getName())) {
                            aoList.add(new RepositoryStatusAO(repo));
                        }
                    }

                    if (!aoList.isEmpty()) {
                        responseContent = aoList.toArray(new RepositoryStatusAO[] {});
                    }
                }
            } else if (this.getUriPathParameters().length == 1) {
                // Get info on specified repository
                // HTTP GET /api/repositories/{id}
                String id = this.getUriPathParameters()[ID_URI_PATH_PARAMETER_INDEX];
                ObjectId objectId = parseDocumentObjectID(id);
                Repository repo = RepositoryService.getInstance().getRepository(objectId);
                if (user.isSystemAdministrator() || allowedRepositories.contains(repo.getRepoConfig().getName())) {
                    responseContent = new RepositoryStatusAO(repo);
                } else {
                    // Assume not found
                    throw new ChiliLogException(Strings.REPOSITORY_NOT_FOUND_ERROR, id);
                }
            } else if (this.getUriPathParameters().length == 2) {
                // HTTP GET /api/repositories/{id}/entries?query_type=find
                // Get entries for a specific repository
                String id = this.getUriPathParameters()[ID_URI_PATH_PARAMETER_INDEX];
                ObjectId objectId = parseDocumentObjectID(id);
                Repository repo = RepositoryService.getInstance().getRepository(objectId);
                if (!user.isSystemAdministrator()
                        && !allowedRepositories.contains(repo.getRepoConfig().getName())) {
                    // Assume not found
                    throw new ChiliLogException(Strings.REPOSITORY_NOT_FOUND_ERROR, id);
                } else if (repo.getStatus() == Status.OFFLINE) {
                    // Cannot search if repository is offline
                    throw new ChiliLogException(Strings.REPOSITORY_OFFLINE_ERROR, id);
                }

                // Load criteria
                QueryType queryType = Enum.valueOf(QueryType.class,
                        this.getQueryStringOrHeaderValue(ENTRY_QUERY_TYPE_QUERYSTRING_PARAMETER_NAME,
                                ENTRY_QUERY_TYPE_HEADER_NAME, false).toUpperCase());
                RepositoryEntryListCriteria criteria = loadCriteria();

                // Convert to JSON ourselves because this is not a simple AO object.
                // mongoDB object JSON serialization required
                StringBuilder json = new StringBuilder();

                // Get controller and execute query
                RepositoryEntryController controller = RepositoryEntryController.getInstance(repo.getRepoConfig());
                if (queryType == QueryType.FIND) {
                    ArrayList<DBObject> list = controller.executeFindQuery(db, criteria);

                    if (list != null && !list.isEmpty()) {
                        MongoJsonSerializer.serialize(new BasicDBObject("find", list), json);
                    }
                } else if (queryType == QueryType.COUNT) {
                    int count = controller.executeCountQuery(db, criteria);
                    MongoJsonSerializer.serialize(new BasicDBObject("count", count), json);
                } else if (queryType == QueryType.DISTINCT) {
                    List l = controller.executeDistinctQuery(db, criteria);
                    MongoJsonSerializer.serialize(new BasicDBObject("distinct", l), json);
                } else if (queryType == QueryType.GROUP) {
                    DBObject groupObject = controller.executeGroupQuery(db, criteria);
                    MongoJsonSerializer.serialize(new BasicDBObject("group", groupObject), json);
                } else {
                    throw new OperationNotSupportedException("Unsupported query type: " + queryType.toString());
                }

                // If there is no json, skip this and a 204 No Content will be returned
                if (json.length() > 0) {
                    responseContent = json.toString().getBytes(Worker.JSON_CHARSET);
                    ApiResult result = new ApiResult(this.getAuthenticationToken(), JSON_CONTENT_TYPE,
                            responseContent);

                    if (criteria.getDoPageCount()) {
                        result.getHeaders().put(PAGE_COUNT_HEADER, new Integer(criteria.getPageCount()).toString());
                    }
                    return result;
                }
            }

            // Return response
            return new ApiResult(this.getAuthenticationToken(), JSON_CONTENT_TYPE, responseContent);
        } catch (Exception ex) {
            return new ApiResult(HttpResponseStatus.BAD_REQUEST, ex);
        }
    }

    /**
     * Parse a string repository document id
     * 
     * @param id
     *            id string
     * @return ObjectID
     * @throws ChiliLogException
     */
    private ObjectId parseDocumentObjectID(String id) throws ChiliLogException {
        try {
            return new ObjectId(id);
        } catch (Exception ex) {
            throw new ChiliLogException(Strings.REPOSITORY_NOT_FOUND_ERROR, id);
        }
    }

    /**
     * Load our criteria from query string and headers (in case it is too big for query string)
     * 
     * @returns query criteria
     * @throws ChiliLogException
     * @throws ParseException 
     */
    private RepositoryEntryListCriteria loadCriteria() throws ChiliLogException, ParseException {
        String s;

        RepositoryEntryListCriteria criteria = new RepositoryEntryListCriteria();
        this.loadBaseListCriteriaParameters(criteria);

        s = this.getQueryStringOrHeaderValue(ENTRY_QUERY_FIELDS_QUERYSTRING_PARAMETER_NAME,
                ENTRY_QUERY_FIELDS_HEADER_NAME, true);
        if (!StringUtils.isBlank(s)) {
            criteria.setFields(s);
        }

        s = this.getQueryStringOrHeaderValue(ENTRY_QUERY_FROM_TIMESTAMP_QUERYSTRING_PARAMETER_NAME,
                ENTRY_QUERY_FROM_TIMESTAMP_HEADER_NAME, true);
        if (!StringUtils.isBlank(s)) {
            criteria.setFrom(s);
        }

        s = this.getQueryStringOrHeaderValue(ENTRY_QUERY_TO_TIMESTAMP_QUERYSTRING_PARAMETER_NAME,
                ENTRY_QUERY_TO_TIMESTAMP_HEADER_NAME, true);
        if (!StringUtils.isBlank(s)) {
            criteria.setTo(s);
        }

        s = this.getQueryStringOrHeaderValue(ENTRY_QUERY_KEYWORD_USAGE_QUERYSTRING_PARAMETER_NAME,
                ENTRY_QUERY_KEYWORD_USAGE_HEADER_NAME, true);
        if (!StringUtils.isBlank(s)) {
            criteria.setKeywordUsage(Enum.valueOf(RepositoryEntryListCriteria.KeywordUsage.class, s));
        }

        s = this.getQueryStringOrHeaderValue(ENTRY_QUERY_CONDITIONS_QUERYSTRING_PARAMETER_NAME,
                ENTRY_QUERY_CONDITIONS_HEADER_NAME, true);
        if (!StringUtils.isBlank(s)) {
            criteria.setConditions(s);
        }

        s = this.getQueryStringOrHeaderValue(ENTRY_QUERY_KEYWORD_USAGE_QUERYSTRING_PARAMETER_NAME,
                ENTRY_QUERY_KEYWORD_USAGE_HEADER_NAME, true);
        if (!StringUtils.isBlank(s)) {
            criteria.setKeywordUsage(Enum.valueOf(RepositoryEntryListCriteria.KeywordUsage.class, s));
        }

        s = this.getQueryStringOrHeaderValue(ENTRY_QUERY_KEYWORDS_QUERYSTRING_PARAMETER_NAME,
                ENTRY_QUERY_KEYWORDS_HEADER_NAME, true);
        if (!StringUtils.isBlank(s)) {
            criteria.setKeywords(s);
        }

        s = this.getQueryStringOrHeaderValue(ENTRY_QUERY_SEVERITY_QUERYSTRING_PARAMETER_NAME,
                ENTRY_QUERY_SEVERITY_HEADER_NAME, true);
        if (!StringUtils.isBlank(s)) {
            criteria.setSeverity(s);
        }

        s = this.getQueryStringOrHeaderValue(ENTRY_QUERY_HOST_QUERYSTRING_PARAMETER_NAME,
                ENTRY_QUERY_HOST_HEADER_NAME, true);
        if (!StringUtils.isBlank(s)) {
            criteria.setHost(s);
        }

        s = this.getQueryStringOrHeaderValue(ENTRY_QUERY_SOURCE_QUERYSTRING_PARAMETER_NAME,
                ENTRY_QUERY_SOURCE_HEADER_NAME, true);
        if (!StringUtils.isBlank(s)) {
            criteria.setSource(s);
        }

        s = this.getQueryStringOrHeaderValue(ENTRY_QUERY_CONDITIONS_QUERYSTRING_PARAMETER_NAME,
                ENTRY_QUERY_CONDITIONS_HEADER_NAME, true);
        if (!StringUtils.isBlank(s)) {
            criteria.setConditions(s);
        }

        s = this.getQueryStringOrHeaderValue(ENTRY_QUERY_ORDER_BY_QUERYSTRING_PARAMETER_NAME,
                ENTRY_QUERY_ORDER_BY_HEADER_NAME, true);
        if (!StringUtils.isBlank(s)) {
            criteria.setOrderBy(s.trim());
        }

        s = this.getQueryStringOrHeaderValue(ENTRY_QUERY_INITIAL_QUERYSTRING_PARAMETER_NAME,
                ENTRY_QUERY_INITIAL_HEADER_NAME, true);
        if (!StringUtils.isBlank(s)) {
            criteria.setInitial(s);
        }

        s = this.getQueryStringOrHeaderValue(ENTRY_QUERY_INITIAL_HEADER_NAME, ENTRY_QUERY_REDUCE_HEADER_NAME, true);
        if (!StringUtils.isBlank(s)) {
            criteria.setReduceFunction(s);
        }

        s = this.getQueryStringOrHeaderValue(ENTRY_QUERY_FINALIZE_QUERYSTRING_PARAMETER_NAME,
                ENTRY_QUERY_FINALIZE_HEADER_NAME, true);
        if (!StringUtils.isBlank(s)) {
            criteria.setFinalizeFunction(s);
        }

        return criteria;
    }
}