You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by li...@apache.org on 2016/06/25 23:34:13 UTC

[01/13] kylin git commit: KYLIN-1823 split code from kylin-server into kylin-server-base

Repository: kylin
Updated Branches:
  refs/heads/master af093f76e -> 1a124e68f


http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/service/ProjectService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/ProjectService.java b/server/src/main/java/org/apache/kylin/rest/service/ProjectService.java
deleted file mode 100644
index c0610a2..0000000
--- a/server/src/main/java/org/apache/kylin/rest/service/ProjectService.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.service;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.kylin.metadata.project.ProjectInstance;
-import org.apache.kylin.metadata.project.ProjectManager;
-import org.apache.kylin.rest.constant.Constant;
-import org.apache.kylin.rest.exception.InternalErrorException;
-import org.apache.kylin.rest.request.CreateProjectRequest;
-import org.apache.kylin.rest.request.UpdateProjectRequest;
-import org.apache.kylin.rest.security.AclPermission;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.stereotype.Component;
-
-/**
- * @author xduo
- * 
- */
-@Component("projectService")
-public class ProjectService extends BasicService {
-
-    private static final Logger logger = LoggerFactory.getLogger(ProjectService.class);
-
-    @Autowired
-    private AccessService accessService;
-
-    public ProjectInstance createProject(CreateProjectRequest projectRequest) throws IOException {
-        String projectName = projectRequest.getName();
-        String description = projectRequest.getDescription();
-        ProjectInstance currentProject = getProjectManager().getProject(projectName);
-
-        if (currentProject != null) {
-            throw new InternalErrorException("The project named " + projectName + " already exists");
-        }
-        String owner = SecurityContextHolder.getContext().getAuthentication().getName();
-        ProjectInstance createdProject = getProjectManager().createProject(projectName, owner, description);
-        accessService.init(createdProject, AclPermission.ADMINISTRATION);
-        logger.debug("New project created.");
-
-        return createdProject;
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#currentProject, 'ADMINISTRATION') or hasPermission(#currentProject, 'MANAGEMENT')")
-    public ProjectInstance updateProject(UpdateProjectRequest projectRequest, ProjectInstance currentProject) throws IOException {
-        String formerProjectName = projectRequest.getFormerProjectName();
-        String newProjectName = projectRequest.getNewProjectName();
-        String newDescription = projectRequest.getNewDescription();
-
-        if (currentProject == null) {
-            throw new InternalErrorException("The project named " + formerProjectName + " does not exists");
-        }
-
-        ProjectInstance updatedProject = getProjectManager().updateProject(currentProject, newProjectName, newDescription);
-
-        logger.debug("Project updated.");
-
-        return updatedProject;
-    }
-
-    public List<ProjectInstance> listAllProjects(final Integer limit, final Integer offset) {
-        List<ProjectInstance> projects = getProjectManager().listAllProjects();
-
-        int climit = (null == limit) ? Integer.MAX_VALUE : limit;
-        int coffset = (null == offset) ? 0 : offset;
-
-        if (projects.size() <= coffset) {
-            return Collections.emptyList();
-        }
-
-        if ((projects.size() - coffset) < climit) {
-            return projects.subList(coffset, projects.size());
-        }
-
-        return projects.subList(coffset, coffset + climit);
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#project, 'ADMINISTRATION') or hasPermission(#cube, 'MANAGEMENT')")
-    public void deleteProject(String projectName, ProjectInstance project) throws IOException {
-        getProjectManager().dropProject(projectName);
-
-        accessService.clean(project, true);
-    }
-
-    public boolean isTableInAnyProject(String tableName) {
-        for (ProjectInstance projectInstance : ProjectManager.getInstance(getConfig()).listAllProjects()) {
-            if (projectInstance.containsTable(tableName.toUpperCase())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public boolean isTableInProject(String tableName, String projectName) {
-        ProjectInstance projectInstance = ProjectManager.getInstance(getConfig()).getProject(projectName);
-        if (projectInstance != null) {
-            if (projectInstance.containsTable(tableName.toUpperCase())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/service/QueryService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/QueryService.java b/server/src/main/java/org/apache/kylin/rest/service/QueryService.java
deleted file mode 100644
index 84a5c67..0000000
--- a/server/src/main/java/org/apache/kylin/rest/service/QueryService.java
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.service;
-
-import java.io.IOException;
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.sql.Time;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.sql.DataSource;
-
-import org.apache.calcite.avatica.ColumnMetaData.Rep;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.StringUtils;
-import org.apache.hadoop.hbase.client.Get;
-import org.apache.hadoop.hbase.client.HConnection;
-import org.apache.hadoop.hbase.client.HTableInterface;
-import org.apache.hadoop.hbase.client.Put;
-import org.apache.hadoop.hbase.client.Result;
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.common.util.Bytes;
-import org.apache.kylin.cube.CubeInstance;
-import org.apache.kylin.cube.CubeManager;
-import org.apache.kylin.cube.cuboid.Cuboid;
-import org.apache.kylin.query.relnode.OLAPContext;
-import org.apache.kylin.rest.constant.Constant;
-import org.apache.kylin.rest.model.ColumnMeta;
-import org.apache.kylin.rest.model.Query;
-import org.apache.kylin.rest.model.SelectedColumnMeta;
-import org.apache.kylin.rest.model.TableMeta;
-import org.apache.kylin.rest.request.PrepareSqlRequest;
-import org.apache.kylin.rest.request.SQLRequest;
-import org.apache.kylin.rest.response.SQLResponse;
-import org.apache.kylin.rest.util.QueryUtil;
-import org.apache.kylin.rest.util.Serializer;
-import org.apache.kylin.storage.hbase.HBaseConnection;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.AccessDeniedException;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.stereotype.Component;
-
-import com.google.common.collect.Lists;
-
-/**
- * @author xduo
- */
-@Component("queryService")
-public class QueryService extends BasicService {
-
-    private static final Logger logger = LoggerFactory.getLogger(QueryService.class);
-
-    @Autowired
-    private CacheService cacheService;
-
-    public static final String USER_QUERY_FAMILY = "q";
-    private static final String DEFAULT_TABLE_PREFIX = "kylin_metadata";
-    private static final String USER_TABLE_NAME = "_user";
-    private static final String USER_QUERY_COLUMN = "c";
-
-    private final Serializer<Query[]> querySerializer = new Serializer<Query[]>(Query[].class);
-    private final BadQueryDetector badQueryDetector = new BadQueryDetector();
-
-    private final String hbaseUrl;
-    private final String tableNameBase;
-    private final String userTableName;
-
-    public QueryService() {
-        String metadataUrl = KylinConfig.getInstanceFromEnv().getMetadataUrl();
-        // split TABLE@HBASE_URL
-        int cut = metadataUrl.indexOf('@');
-        tableNameBase = cut < 0 ? DEFAULT_TABLE_PREFIX : metadataUrl.substring(0, cut);
-        hbaseUrl = cut < 0 ? metadataUrl : metadataUrl.substring(cut + 1);
-        userTableName = tableNameBase + USER_TABLE_NAME;
-
-        badQueryDetector.start();
-    }
-
-    public List<TableMeta> getMetadata(String project) throws SQLException {
-        return getMetadata(getCubeManager(), project, true);
-    }
-
-    public SQLResponse query(SQLRequest sqlRequest) throws Exception {
-        try {
-            badQueryDetector.queryStart(Thread.currentThread(), sqlRequest);
-
-            return queryWithSqlMassage(sqlRequest);
-
-        } finally {
-            badQueryDetector.queryEnd(Thread.currentThread());
-        }
-    }
-
-    public void saveQuery(final String creator, final Query query) throws IOException {
-        List<Query> queries = getQueries(creator);
-        queries.add(query);
-        Query[] queryArray = new Query[queries.size()];
-
-        byte[] bytes = querySerializer.serialize(queries.toArray(queryArray));
-        HTableInterface htable = null;
-        try {
-            htable = HBaseConnection.get(hbaseUrl).getTable(userTableName);
-            Put put = new Put(Bytes.toBytes(creator));
-            put.add(Bytes.toBytes(USER_QUERY_FAMILY), Bytes.toBytes(USER_QUERY_COLUMN), bytes);
-
-            htable.put(put);
-            htable.flushCommits();
-        } finally {
-            IOUtils.closeQuietly(htable);
-        }
-    }
-
-    public void removeQuery(final String creator, final String id) throws IOException {
-        List<Query> queries = getQueries(creator);
-        Iterator<Query> queryIter = queries.iterator();
-
-        boolean changed = false;
-        while (queryIter.hasNext()) {
-            Query temp = queryIter.next();
-            if (temp.getId().equals(id)) {
-                queryIter.remove();
-                changed = true;
-                break;
-            }
-        }
-
-        if (!changed) {
-            return;
-        }
-
-        Query[] queryArray = new Query[queries.size()];
-        byte[] bytes = querySerializer.serialize(queries.toArray(queryArray));
-        HTableInterface htable = null;
-        try {
-            htable = HBaseConnection.get(hbaseUrl).getTable(userTableName);
-            Put put = new Put(Bytes.toBytes(creator));
-            put.add(Bytes.toBytes(USER_QUERY_FAMILY), Bytes.toBytes(USER_QUERY_COLUMN), bytes);
-
-            htable.put(put);
-            htable.flushCommits();
-        } finally {
-            IOUtils.closeQuietly(htable);
-        }
-    }
-
-    public List<Query> getQueries(final String creator) throws IOException {
-        if (null == creator) {
-            return null;
-        }
-
-        List<Query> queries = new ArrayList<Query>();
-        HTableInterface htable = null;
-        try {
-            HConnection conn = HBaseConnection.get(hbaseUrl);
-            HBaseConnection.createHTableIfNeeded(conn, userTableName, USER_QUERY_FAMILY);
-
-            htable = conn.getTable(userTableName);
-            Get get = new Get(Bytes.toBytes(creator));
-            get.addFamily(Bytes.toBytes(USER_QUERY_FAMILY));
-            Result result = htable.get(get);
-            Query[] query = querySerializer.deserialize(result.getValue(Bytes.toBytes(USER_QUERY_FAMILY), Bytes.toBytes(USER_QUERY_COLUMN)));
-
-            if (null != query) {
-                queries.addAll(Arrays.asList(query));
-            }
-        } finally {
-            IOUtils.closeQuietly(htable);
-        }
-
-        return queries;
-    }
-
-    public void logQuery(final SQLRequest request, final SQLResponse response) {
-        final String user = SecurityContextHolder.getContext().getAuthentication().getName();
-        final Set<String> realizationNames = new HashSet<String>();
-        final Set<Long> cuboidIds = new HashSet<Long>();
-        float duration = response.getDuration() / (float) 1000;
-        boolean storageCacheUsed = response.isStorageCacheUsed();
-
-        if (!response.isHitExceptionCache() && null != OLAPContext.getThreadLocalContexts()) {
-            for (OLAPContext ctx : OLAPContext.getThreadLocalContexts()) {
-                Cuboid cuboid = ctx.storageContext.getCuboid();
-                if (cuboid != null) {
-                    //Some queries do not involve cuboid, e.g. lookup table query
-                    cuboidIds.add(cuboid.getId());
-                }
-
-                if (ctx.realization != null) {
-                    String realizationName = ctx.realization.getName();
-                    realizationNames.add(realizationName);
-                }
-
-            }
-        }
-
-        int resultRowCount = 0;
-        if (!response.getIsException() && response.getResults() != null) {
-            resultRowCount = response.getResults().size();
-        }
-
-        String newLine = System.getProperty("line.separator");
-        StringBuilder stringBuilder = new StringBuilder();
-        stringBuilder.append(newLine);
-        stringBuilder.append("==========================[QUERY]===============================").append(newLine);
-        stringBuilder.append("SQL: ").append(request.getSql()).append(newLine);
-        stringBuilder.append("User: ").append(user).append(newLine);
-        stringBuilder.append("Success: ").append((null == response.getExceptionMessage())).append(newLine);
-        stringBuilder.append("Duration: ").append(duration).append(newLine);
-        stringBuilder.append("Project: ").append(request.getProject()).append(newLine);
-        stringBuilder.append("Realization Names: ").append(realizationNames).append(newLine);
-        stringBuilder.append("Cuboid Ids: ").append(cuboidIds).append(newLine);
-        stringBuilder.append("Total scan count: ").append(response.getTotalScanCount()).append(newLine);
-        stringBuilder.append("Result row count: ").append(resultRowCount).append(newLine);
-        stringBuilder.append("Accept Partial: ").append(request.isAcceptPartial()).append(newLine);
-        stringBuilder.append("Is Partial Result: ").append(response.isPartial()).append(newLine);
-        stringBuilder.append("Hit Exception Cache: ").append(response.isHitExceptionCache()).append(newLine);
-        stringBuilder.append("Storage cache used: ").append(storageCacheUsed).append(newLine);
-        stringBuilder.append("Message: ").append(response.getExceptionMessage()).append(newLine);
-        stringBuilder.append("==========================[QUERY]===============================").append(newLine);
-
-        logger.info(stringBuilder.toString());
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'MANAGEMENT')" + " or hasPermission(#cube, 'OPERATION') or hasPermission(#cube, 'READ')")
-    public void checkAuthorization(CubeInstance cube) throws AccessDeniedException {
-    }
-
-    private SQLResponse queryWithSqlMassage(SQLRequest sqlRequest) throws Exception {
-        SQLResponse fakeResponse = QueryUtil.tableauIntercept(sqlRequest.getSql());
-        if (null != fakeResponse) {
-            logger.debug("Return fake response, is exception? " + fakeResponse.getIsException());
-            return fakeResponse;
-        }
-
-        String correctedSql = QueryUtil.massageSql(sqlRequest);
-        if (correctedSql.equals(sqlRequest.getSql()) == false)
-            logger.info("The corrected query: " + correctedSql);
-
-        // add extra parameters into olap context, like acceptPartial
-        Map<String, String> parameters = new HashMap<String, String>();
-        parameters.put(OLAPContext.PRM_ACCEPT_PARTIAL_RESULT, String.valueOf(sqlRequest.isAcceptPartial()));
-        OLAPContext.setParameters(parameters);
-
-        return execute(correctedSql, sqlRequest);
-
-    }
-
-    protected List<TableMeta> getMetadata(CubeManager cubeMgr, String project, boolean cubedOnly) throws SQLException {
-
-        Connection conn = null;
-        ResultSet columnMeta = null;
-        List<TableMeta> tableMetas = null;
-        if (StringUtils.isBlank(project)) {
-            return Collections.emptyList();
-        }
-        ResultSet JDBCTableMeta = null;
-        try {
-            DataSource dataSource = cacheService.getOLAPDataSource(project);
-            conn = dataSource.getConnection();
-            DatabaseMetaData metaData = conn.getMetaData();
-
-            logger.debug("getting table metas");
-            JDBCTableMeta = metaData.getTables(null, null, null, null);
-
-            tableMetas = new LinkedList<TableMeta>();
-            Map<String, TableMeta> tableMap = new HashMap<String, TableMeta>();
-            while (JDBCTableMeta.next()) {
-                String catalogName = JDBCTableMeta.getString(1);
-                String schemaName = JDBCTableMeta.getString(2);
-
-                // Not every JDBC data provider offers full 10 columns, e.g., PostgreSQL has only 5
-                TableMeta tblMeta = new TableMeta(catalogName == null ? Constant.FakeCatalogName : catalogName, schemaName == null ? Constant.FakeSchemaName : schemaName, JDBCTableMeta.getString(3), JDBCTableMeta.getString(4), JDBCTableMeta.getString(5), null, null, null, null, null);
-
-                if (!cubedOnly || getProjectManager().isExposedTable(project, schemaName + "." + tblMeta.getTABLE_NAME())) {
-                    tableMetas.add(tblMeta);
-                    tableMap.put(tblMeta.getTABLE_SCHEM() + "#" + tblMeta.getTABLE_NAME(), tblMeta);
-                }
-            }
-
-            logger.debug("getting column metas");
-            columnMeta = metaData.getColumns(null, null, null, null);
-
-            while (columnMeta.next()) {
-                String catalogName = columnMeta.getString(1);
-                String schemaName = columnMeta.getString(2);
-
-                // kylin(optiq) is not strictly following JDBC specification
-                ColumnMeta colmnMeta = new ColumnMeta(catalogName == null ? Constant.FakeCatalogName : catalogName, schemaName == null ? Constant.FakeSchemaName : schemaName, columnMeta.getString(3), columnMeta.getString(4), columnMeta.getInt(5), columnMeta.getString(6), columnMeta.getInt(7), getInt(columnMeta.getString(8)), columnMeta.getInt(9), columnMeta.getInt(10), columnMeta.getInt(11), columnMeta.getString(12), columnMeta.getString(13), getInt(columnMeta.getString(14)), getInt(columnMeta.getString(15)), columnMeta.getInt(16), columnMeta.getInt(17), columnMeta.getString(18), columnMeta.getString(19), columnMeta.getString(20), columnMeta.getString(21), getShort(columnMeta.getString(22)), columnMeta.getString(23));
-
-                if (!cubedOnly || getProjectManager().isExposedColumn(project, schemaName + "." + colmnMeta.getTABLE_NAME(), colmnMeta.getCOLUMN_NAME())) {
-                    tableMap.get(colmnMeta.getTABLE_SCHEM() + "#" + colmnMeta.getTABLE_NAME()).addColumn(colmnMeta);
-                }
-            }
-            logger.debug("done column metas");
-        } finally {
-            close(columnMeta, null, conn);
-            if (JDBCTableMeta != null) {
-                JDBCTableMeta.close();
-            }
-        }
-
-        return tableMetas;
-    }
-
-    /**
-     * @param sql
-     * @param sqlRequest
-     * @return
-     * @throws Exception
-     */
-    private SQLResponse execute(String sql, SQLRequest sqlRequest) throws Exception {
-        Connection conn = null;
-        Statement stat = null;
-        ResultSet resultSet = null;
-
-        List<List<String>> results = Lists.newArrayList();
-        List<SelectedColumnMeta> columnMetas = Lists.newArrayList();
-
-        try {
-            conn = cacheService.getOLAPDataSource(sqlRequest.getProject()).getConnection();
-
-            if (sqlRequest instanceof PrepareSqlRequest) {
-                PreparedStatement preparedState = conn.prepareStatement(sql);
-
-                for (int i = 0; i < ((PrepareSqlRequest) sqlRequest).getParams().length; i++) {
-                    setParam(preparedState, i + 1, ((PrepareSqlRequest) sqlRequest).getParams()[i]);
-                }
-
-                resultSet = preparedState.executeQuery();
-            } else {
-                stat = conn.createStatement();
-                resultSet = stat.executeQuery(sql);
-            }
-
-            ResultSetMetaData metaData = resultSet.getMetaData();
-            int columnCount = metaData.getColumnCount();
-
-            // Fill in selected column meta
-            for (int i = 1; i <= columnCount; ++i) {
-                columnMetas.add(new SelectedColumnMeta(metaData.isAutoIncrement(i), metaData.isCaseSensitive(i), metaData.isSearchable(i), metaData.isCurrency(i), metaData.isNullable(i), metaData.isSigned(i), metaData.getColumnDisplaySize(i), metaData.getColumnLabel(i), metaData.getColumnName(i), metaData.getSchemaName(i), metaData.getCatalogName(i), metaData.getTableName(i), metaData.getPrecision(i), metaData.getScale(i), metaData.getColumnType(i), metaData.getColumnTypeName(i), metaData.isReadOnly(i), metaData.isWritable(i), metaData.isDefinitelyWritable(i)));
-            }
-
-            // fill in results
-            while (resultSet.next()) {
-                List<String> oneRow = Lists.newArrayListWithCapacity(columnCount);
-                for (int i = 0; i < columnCount; i++) {
-                    oneRow.add((resultSet.getString(i + 1)));
-                }
-
-                results.add(oneRow);
-            }
-        } finally {
-            close(resultSet, stat, conn);
-        }
-
-        boolean isPartialResult = false;
-        String cube = "";
-        StringBuilder sb = new StringBuilder("Scan count for each storageContext: ");
-        long totalScanCount = 0;
-        if (OLAPContext.getThreadLocalContexts() != null) { // contexts can be null in case of 'explain plan for'
-            for (OLAPContext ctx : OLAPContext.getThreadLocalContexts()) {
-                if (ctx.realization != null) {
-                    isPartialResult |= ctx.storageContext.isPartialResultReturned();
-                    cube = ctx.realization.getName();
-                    totalScanCount += ctx.storageContext.getTotalScanCount();
-                    sb.append(ctx.storageContext.getTotalScanCount() + ",");
-                }
-            }
-        }
-        logger.info(sb.toString());
-
-        SQLResponse response = new SQLResponse(columnMetas, results, cube, 0, false, null, isPartialResult);
-        response.setTotalScanCount(totalScanCount);
-
-        return response;
-    }
-
-    /**
-     * @param preparedState
-     * @param param
-     * @throws SQLException
-     */
-    private void setParam(PreparedStatement preparedState, int index, PrepareSqlRequest.StateParam param) throws SQLException {
-        boolean isNull = (null == param.getValue());
-
-        Class<?> clazz;
-        try {
-            clazz = Class.forName(param.getClassName());
-        } catch (ClassNotFoundException e) {
-            throw new RuntimeException(e.getMessage(), e);
-        }
-
-        Rep rep = Rep.of(clazz);
-
-        switch (rep) {
-        case PRIMITIVE_CHAR:
-        case CHARACTER:
-        case STRING:
-            preparedState.setString(index, isNull ? null : String.valueOf(param.getValue()));
-            break;
-        case PRIMITIVE_INT:
-        case INTEGER:
-            preparedState.setInt(index, isNull ? 0 : Integer.valueOf(param.getValue()));
-            break;
-        case PRIMITIVE_SHORT:
-        case SHORT:
-            preparedState.setShort(index, isNull ? 0 : Short.valueOf(param.getValue()));
-            break;
-        case PRIMITIVE_LONG:
-        case LONG:
-            preparedState.setLong(index, isNull ? 0 : Long.valueOf(param.getValue()));
-            break;
-        case PRIMITIVE_FLOAT:
-        case FLOAT:
-            preparedState.setFloat(index, isNull ? 0 : Float.valueOf(param.getValue()));
-            break;
-        case PRIMITIVE_DOUBLE:
-        case DOUBLE:
-            preparedState.setDouble(index, isNull ? 0 : Double.valueOf(param.getValue()));
-            break;
-        case PRIMITIVE_BOOLEAN:
-        case BOOLEAN:
-            preparedState.setBoolean(index, !isNull && Boolean.parseBoolean(param.getValue()));
-            break;
-        case PRIMITIVE_BYTE:
-        case BYTE:
-            preparedState.setByte(index, isNull ? 0 : Byte.valueOf(param.getValue()));
-            break;
-        case JAVA_UTIL_DATE:
-        case JAVA_SQL_DATE:
-            preparedState.setDate(index, isNull ? null : java.sql.Date.valueOf(param.getValue()));
-            break;
-        case JAVA_SQL_TIME:
-            preparedState.setTime(index, isNull ? null : Time.valueOf(param.getValue()));
-            break;
-        case JAVA_SQL_TIMESTAMP:
-            preparedState.setTimestamp(index, isNull ? null : Timestamp.valueOf(param.getValue()));
-            break;
-        default:
-            preparedState.setObject(index, isNull ? null : param.getValue());
-        }
-    }
-
-    private int getInt(String content) {
-        try {
-            return Integer.parseInt(content);
-        } catch (Exception e) {
-            return -1;
-        }
-    }
-
-    private short getShort(String content) {
-        try {
-            return Short.parseShort(content);
-        } catch (Exception e) {
-            return -1;
-        }
-    }
-
-    private static void close(ResultSet resultSet, Statement stat, Connection conn) {
-        OLAPContext.clearParameter();
-
-        if (resultSet != null)
-            try {
-                resultSet.close();
-            } catch (SQLException e) {
-                logger.error("failed to close", e);
-            }
-        if (stat != null)
-            try {
-                stat.close();
-            } catch (SQLException e) {
-                logger.error("failed to close", e);
-            }
-        if (conn != null)
-            try {
-                conn.close();
-            } catch (SQLException e) {
-                logger.error("failed to close", e);
-            }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/service/StreamingService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/StreamingService.java b/server/src/main/java/org/apache/kylin/rest/service/StreamingService.java
deleted file mode 100644
index e49e882..0000000
--- a/server/src/main/java/org/apache/kylin/rest/service/StreamingService.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.service;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.kylin.engine.streaming.StreamingConfig;
-import org.apache.kylin.rest.constant.Constant;
-import org.apache.kylin.rest.exception.InternalErrorException;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PostFilter;
-import org.springframework.stereotype.Component;
-
-@Component("streamingMgmtService")
-public class StreamingService extends BasicService {
-
-    @Autowired
-    private AccessService accessService;
-
-    @PostFilter(Constant.ACCESS_POST_FILTER_READ)
-    public List<StreamingConfig> listAllStreamingConfigs(final String table) throws IOException {
-        List<StreamingConfig> streamingConfigs = new ArrayList();
-        if (StringUtils.isEmpty(table)) {
-            streamingConfigs = getStreamingManager().listAllStreaming();
-        } else {
-            StreamingConfig config = getStreamingManager().getConfig(table);
-            if (config != null) {
-                streamingConfigs.add(config);
-            }
-        }
-
-        return streamingConfigs;
-    }
-
-    public List<StreamingConfig> getStreamingConfigs(final String table, final Integer limit, final Integer offset) throws IOException {
-
-        List<StreamingConfig> streamingConfigs;
-        streamingConfigs = listAllStreamingConfigs(table);
-
-        if (limit == null || offset == null) {
-            return streamingConfigs;
-        }
-
-        if ((streamingConfigs.size() - offset) < limit) {
-            return streamingConfigs.subList(offset, streamingConfigs.size());
-        }
-
-        return streamingConfigs.subList(offset, offset + limit);
-    }
-
-    public StreamingConfig createStreamingConfig(StreamingConfig config) throws IOException {
-        if (getStreamingManager().getStreamingConfig(config.getName()) != null) {
-            throw new InternalErrorException("The streamingConfig named " + config.getName() + " already exists");
-        }
-        StreamingConfig streamingConfig = getStreamingManager().saveStreamingConfig(config);
-        return streamingConfig;
-    }
-
-    //    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
-    public StreamingConfig updateStreamingConfig(StreamingConfig config) throws IOException {
-        return getStreamingManager().updateStreamingConfig(config);
-    }
-
-    //    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
-    public void dropStreamingConfig(StreamingConfig config) throws IOException {
-        getStreamingManager().removeStreamingConfig(config);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/service/UserService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/UserService.java b/server/src/main/java/org/apache/kylin/rest/service/UserService.java
deleted file mode 100644
index 07c7c6f..0000000
--- a/server/src/main/java/org/apache/kylin/rest/service/UserService.java
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.service;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import javax.annotation.PostConstruct;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.hadoop.hbase.client.Delete;
-import org.apache.hadoop.hbase.client.Get;
-import org.apache.hadoop.hbase.client.HTableInterface;
-import org.apache.hadoop.hbase.client.Put;
-import org.apache.hadoop.hbase.client.Result;
-import org.apache.hadoop.hbase.client.ResultScanner;
-import org.apache.hadoop.hbase.client.Scan;
-import org.apache.kylin.common.util.Bytes;
-import org.apache.kylin.common.util.Pair;
-import org.apache.kylin.rest.security.AclHBaseStorage;
-import org.apache.kylin.rest.util.Serializer;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.userdetails.User;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.security.provisioning.UserDetailsManager;
-import org.springframework.stereotype.Component;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-
-/**
- */
-@Component("userService")
-public class UserService implements UserDetailsManager {
-
-    private static final String PWD_PREFIX = "PWD:";
-
-    private Serializer<UserGrantedAuthority[]> ugaSerializer = new Serializer<UserGrantedAuthority[]>(UserGrantedAuthority[].class);
-
-    private String userTableName = null;
-
-    @Autowired
-    protected AclHBaseStorage aclHBaseStorage;
-
-    @PostConstruct
-    public void init() throws IOException {
-        userTableName = aclHBaseStorage.prepareHBaseTable(UserService.class);
-    }
-
-    @Override
-    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
-        HTableInterface htable = null;
-        try {
-            htable = aclHBaseStorage.getTable(userTableName);
-
-            Get get = new Get(Bytes.toBytes(username));
-            get.addFamily(Bytes.toBytes(AclHBaseStorage.USER_AUTHORITY_FAMILY));
-            Result result = htable.get(get);
-
-            User user = hbaseRowToUser(result);
-            if (user == null)
-                throw new UsernameNotFoundException("User " + username + " not found.");
-
-            return user;
-        } catch (IOException e) {
-            throw new RuntimeException(e.getMessage(), e);
-        } finally {
-            IOUtils.closeQuietly(htable);
-        }
-    }
-
-    private User hbaseRowToUser(Result result) throws JsonParseException, JsonMappingException, IOException {
-        if (null == result || result.isEmpty())
-            return null;
-
-        String username = Bytes.toString(result.getRow());
-
-        byte[] valueBytes = result.getValue(Bytes.toBytes(AclHBaseStorage.USER_AUTHORITY_FAMILY), Bytes.toBytes(AclHBaseStorage.USER_AUTHORITY_COLUMN));
-        UserGrantedAuthority[] deserialized = ugaSerializer.deserialize(valueBytes);
-
-        String password = "";
-        List<UserGrantedAuthority> authorities = Collections.emptyList();
-
-        // password is stored at [0] of authorities for backward compatibility
-        if (deserialized != null) {
-            if (deserialized.length > 0 && deserialized[0].getAuthority().startsWith(PWD_PREFIX)) {
-                password = deserialized[0].getAuthority().substring(PWD_PREFIX.length());
-                authorities = Arrays.asList(deserialized).subList(1, deserialized.length);
-            } else {
-                authorities = Arrays.asList(deserialized);
-            }
-        }
-
-        return new User(username, password, authorities);
-    }
-
-    private Pair<byte[], byte[]> userToHBaseRow(UserDetails user) throws JsonProcessingException {
-        byte[] key = Bytes.toBytes(user.getUsername());
-
-        Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
-        if (authorities == null)
-            authorities = Collections.emptyList();
-
-        UserGrantedAuthority[] serializing = new UserGrantedAuthority[authorities.size() + 1];
-
-        // password is stored as the [0] authority
-        serializing[0] = new UserGrantedAuthority(PWD_PREFIX + user.getPassword());
-        int i = 1;
-        for (GrantedAuthority a : authorities) {
-            serializing[i++] = new UserGrantedAuthority(a.getAuthority());
-        }
-
-        byte[] value = ugaSerializer.serialize(serializing);
-        return Pair.newPair(key, value);
-    }
-
-    @Override
-    public void createUser(UserDetails user) {
-        updateUser(user);
-    }
-
-    @Override
-    public void updateUser(UserDetails user) {
-        HTableInterface htable = null;
-        try {
-            htable = aclHBaseStorage.getTable(userTableName);
-
-            Pair<byte[], byte[]> pair = userToHBaseRow(user);
-            Put put = new Put(pair.getKey());
-            put.add(Bytes.toBytes(AclHBaseStorage.USER_AUTHORITY_FAMILY), Bytes.toBytes(AclHBaseStorage.USER_AUTHORITY_COLUMN), pair.getSecond());
-
-            htable.put(put);
-            htable.flushCommits();
-        } catch (IOException e) {
-            throw new RuntimeException(e.getMessage(), e);
-        } finally {
-            IOUtils.closeQuietly(htable);
-        }
-    }
-
-    @Override
-    public void deleteUser(String username) {
-        HTableInterface htable = null;
-        try {
-            htable = aclHBaseStorage.getTable(userTableName);
-
-            Delete delete = new Delete(Bytes.toBytes(username));
-
-            htable.delete(delete);
-            htable.flushCommits();
-        } catch (IOException e) {
-            throw new RuntimeException(e.getMessage(), e);
-        } finally {
-            IOUtils.closeQuietly(htable);
-        }
-    }
-
-    @Override
-    public void changePassword(String oldPassword, String newPassword) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean userExists(String username) {
-        HTableInterface htable = null;
-        try {
-            htable = aclHBaseStorage.getTable(userTableName);
-
-            Result result = htable.get(new Get(Bytes.toBytes(username)));
-
-            return null != result && !result.isEmpty();
-        } catch (IOException e) {
-            throw new RuntimeException(e.getMessage(), e);
-        } finally {
-            IOUtils.closeQuietly(htable);
-        }
-    }
-
-    public List<String> listUserAuthorities() {
-        List<String> all = new ArrayList<String>();
-        for (UserDetails user : listUsers()) {
-            for (GrantedAuthority auth : user.getAuthorities()) {
-                if (!all.contains(auth.getAuthority())) {
-                    all.add(auth.getAuthority());
-                }
-            }
-        }
-        return all;
-    }
-
-    public List<UserDetails> listUsers() {
-        Scan s = new Scan();
-        s.addColumn(Bytes.toBytes(AclHBaseStorage.USER_AUTHORITY_FAMILY), Bytes.toBytes(AclHBaseStorage.USER_AUTHORITY_COLUMN));
-
-        List<UserDetails> all = new ArrayList<UserDetails>();
-        HTableInterface htable = null;
-        ResultScanner scanner = null;
-        try {
-            htable = aclHBaseStorage.getTable(userTableName);
-            scanner = htable.getScanner(s);
-
-            for (Result result = scanner.next(); result != null; result = scanner.next()) {
-                User user = hbaseRowToUser(result);
-                all.add(user);
-            }
-        } catch (IOException e) {
-            throw new RuntimeException("Failed to scan users", e);
-        } finally {
-            IOUtils.closeQuietly(scanner);
-            IOUtils.closeQuietly(htable);
-        }
-        return all;
-    }
-
-    public static class UserGrantedAuthority implements GrantedAuthority {
-        private static final long serialVersionUID = -5128905636841891058L;
-        private String authority;
-
-        public UserGrantedAuthority() {
-        }
-
-        public UserGrantedAuthority(String authority) {
-            setAuthority(authority);
-        }
-
-        @Override
-        public String getAuthority() {
-            return authority;
-        }
-
-        public void setAuthority(String authority) {
-            this.authority = authority;
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + ((authority == null) ? 0 : authority.hashCode());
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj)
-                return true;
-            if (obj == null)
-                return false;
-            if (getClass() != obj.getClass())
-                return false;
-            UserGrantedAuthority other = (UserGrantedAuthority) obj;
-            if (authority == null) {
-                if (other.authority != null)
-                    return false;
-            } else if (!authority.equals(other.authority))
-                return false;
-            return true;
-        }
-
-        @Override
-        public String toString() {
-            return authority;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/util/Log4jConfigListener.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/util/Log4jConfigListener.java b/server/src/main/java/org/apache/kylin/rest/util/Log4jConfigListener.java
deleted file mode 100644
index 7e79511..0000000
--- a/server/src/main/java/org/apache/kylin/rest/util/Log4jConfigListener.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.util;
-
-import javax.servlet.ServletContextEvent;
-
-import org.apache.kylin.common.KylinConfig;
-
-public class Log4jConfigListener extends org.springframework.web.util.Log4jConfigListener {
-
-    private boolean isDebugTomcat;
-
-    public Log4jConfigListener() {
-        this.isDebugTomcat = KylinConfig.getInstanceFromEnv().isDevEnv();
-    }
-
-    @Override
-    public void contextInitialized(ServletContextEvent event) {
-        if (!isDebugTomcat) {
-            super.contextInitialized(event);
-        }
-    }
-
-    @Override
-    public void contextDestroyed(ServletContextEvent event) {
-        if (!isDebugTomcat) {
-            super.contextDestroyed(event);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/util/QueryUtil.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/util/QueryUtil.java b/server/src/main/java/org/apache/kylin/rest/util/QueryUtil.java
deleted file mode 100644
index c15e5f9..0000000
--- a/server/src/main/java/org/apache/kylin/rest/util/QueryUtil.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.util;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.kylin.rest.model.SelectedColumnMeta;
-import org.apache.kylin.rest.request.SQLRequest;
-import org.apache.kylin.rest.response.SQLResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- */
-public class QueryUtil {
-
-    protected static final Logger logger = LoggerFactory.getLogger(QueryUtil.class);
-
-    private static final String S0 = "\\s*";
-    private static final String S1 = "\\s";
-    private static final String SM = "\\s+";
-    private static final Pattern PTN_GROUP_BY = Pattern.compile(S1 + "GROUP" + SM + "BY" + S1, Pattern.CASE_INSENSITIVE);
-    private static final Pattern PTN_HAVING_COUNT_GREATER_THAN_ZERO = Pattern.compile(S1 + "HAVING" + SM + "[(]?" + S0 + "COUNT" + S0 + "[(]" + S0 + "1" + S0 + "[)]" + S0 + ">" + S0 + "0" + S0 + "[)]?", Pattern.CASE_INSENSITIVE);
-    private static final Pattern PTN_SUM_1 = Pattern.compile(S1 + "SUM" + S0 + "[(]" + S0 + "[1]" + S0 + "[)]" + S1, Pattern.CASE_INSENSITIVE);
-
-    // private static final Pattern PTN_HAVING_ESCAPE_FUNCTION =
-    // Pattern.compile("\\{fn" + "(" + S0 + ")" + "\\}",
-    // Pattern.CASE_INSENSITIVE);
-    private static final Pattern PTN_HAVING_ESCAPE_FUNCTION = Pattern.compile("\\{fn" + "(.*?)" + "\\}", Pattern.CASE_INSENSITIVE);
-
-    private static String[] tableauTestQueries = new String[] { "SELECT 1", //
-            "CREATE LOCAL TEMPORARY TABLE \"XTableau_B_Connect\" ( \"COL\" INTEGER ) ON COMMIT PRESERVE ROWS", //
-            "DROP TABLE \"XTableau_B_Connect\"", //
-            "SELECT \"COL\" FROM (SELECT 1 AS \"COL\") AS \"SUBQUERY\"", //
-            "SELECT TOP 1 \"COL\" FROM (SELECT 1 AS \"COL\") AS \"CHECKTOP\"", "SELECT \"COL\" FROM (SELECT 1 AS \"COL\") AS \"CHECKTOP\" LIMIT 1", //
-            "SELECT \"SUBCOL\" AS \"COL\"  FROM (   SELECT 1 AS \"SUBCOL\" ) \"SUBQUERY\" GROUP BY 1", "SELECT \"SUBCOL\" AS \"COL\" FROM (   SELECT 1 AS \"SUBCOL\" ) \"SUBQUERY\" GROUP BY 2", "INSERT INTO \"XTableau_C_Connect\" SELECT * FROM (SELECT 1 AS COL) AS CHECKTEMP LIMIT 1", "DROP TABLE \"XTableau_C_Connect\"", "INSERT INTO \"XTableau_B_Connect\" SELECT * FROM (SELECT 1 AS COL) AS CHECKTEMP LIMIT 1" };
-
-    private static SQLResponse temp = new SQLResponse(new LinkedList<SelectedColumnMeta>() {
-        private static final long serialVersionUID = -8086728462624901359L;
-
-        {
-            add(new SelectedColumnMeta(false, false, true, false, 2, true, 11, "COL", "COL", "", "", "", 10, 0, 4, "int4", false, true, false));
-        }
-    }, new LinkedList<List<String>>() {
-        private static final long serialVersionUID = -470083340592928073L;
-
-        {
-            add(new LinkedList<String>() {
-                private static final long serialVersionUID = -3673192785838230054L;
-
-                {
-                    add("1");
-                }
-            });
-        }
-    }, 0, false, null);
-
-    private static SQLResponse[] fakeResponses = new SQLResponse[] { temp, new SQLResponse(null, null, 0, false, null), //
-            new SQLResponse(null, null, 0, false, null), //
-            temp, //
-            new SQLResponse(null, null, 0, true, "near 1 syntax error"), //
-            temp, //
-            new SQLResponse(null, null, 0, true, "group by 1????"), //
-            new SQLResponse(null, null, 0, true, "group by 2????"), //
-            new SQLResponse(null, null, 0, true, "XTableau_C_Connect not exist"), //
-            new SQLResponse(null, null, 0, true, "XTableau_C_Connect not exist"), new SQLResponse(null, null, 0, true, "XTableau_B_Connect not exist"), };
-
-    private static ArrayList<HashSet<String>> tableauTestQueriesInToken = new ArrayList<HashSet<String>>();
-
-    static {
-        for (String q : tableauTestQueries) {
-            HashSet<String> temp = new HashSet<String>();
-            for (String token : q.split("[\r\n\t \\(\\)]")) {
-                temp.add(token);
-            }
-            temp.add("");
-            tableauTestQueriesInToken.add(temp);
-        }
-    }
-
-    public static String massageSql(SQLRequest sqlRequest) {
-        String sql = sqlRequest.getSql();
-        sql = sql.trim();
-
-        while (sql.endsWith(";"))
-            sql = sql.substring(0, sql.length() - 1);
-
-        int limit = sqlRequest.getLimit();
-        if (limit > 0 && !sql.toLowerCase().contains("limit")) {
-            sql += ("\nLIMIT " + limit);
-        }
-
-        int offset = sqlRequest.getOffset();
-        if (offset > 0 && !sql.toLowerCase().contains("offset")) {
-            sql += ("\nOFFSET " + offset);
-        }
-
-        return healSickSql(sql);
-    }
-
-    // correct sick / invalid SQL
-    private static String healSickSql(String sql) {
-        Matcher m;
-
-        // Case fn{ EXTRACT(...) }
-        // Use non-greedy regrex matching to remove escape functions
-        while (true) {
-            m = PTN_HAVING_ESCAPE_FUNCTION.matcher(sql);
-            if (!m.find())
-                break;
-            sql = sql.substring(0, m.start()) + m.group(1) + sql.substring(m.end());
-        }
-
-        // Case: HAVING COUNT(1)>0 without Group By
-        // Tableau generates: SELECT SUM(1) AS "COL" FROM "VAC_SW" HAVING
-        // COUNT(1)>0
-        m = PTN_HAVING_COUNT_GREATER_THAN_ZERO.matcher(sql);
-        if (m.find() && PTN_GROUP_BY.matcher(sql).find() == false) {
-            sql = sql.substring(0, m.start()) + " " + sql.substring(m.end());
-        }
-
-        // Case: SUM(1)
-        // Replace it with COUNT(1)
-        while (true) {
-            m = PTN_SUM_1.matcher(sql);
-            if (!m.find())
-                break;
-            sql = sql.substring(0, m.start()) + " COUNT(1) " + sql.substring(m.end());
-        }
-
-        return sql;
-    }
-
-    public static SQLResponse tableauIntercept(String sql) {
-
-        String[] tokens = sql.split("[\r\n\t \\(\\)]");
-        for (int i = 0; i < tableauTestQueries.length; ++i) {
-            if (isTokenWiseEqual(tokens, tableauTestQueriesInToken.get(i))) {
-                logger.info("Hit fake response " + i);
-                return fakeResponses[i];
-            }
-        }
-
-        return null;
-    }
-
-    public static String makeErrorMsgUserFriendly(Throwable e) {
-        String msg = e.getMessage();
-
-        // pick ParseException error message if possible
-        Throwable cause = e;
-        while (cause != null) {
-            if (cause.getClass().getName().contains("ParseException")) {
-                msg = cause.getMessage();
-                break;
-            }
-            cause = cause.getCause();
-        }
-
-        return makeErrorMsgUserFriendly(msg);
-    }
-
-    public static String makeErrorMsgUserFriendly(String errorMsg) {
-        try {
-            // make one line
-            errorMsg = errorMsg.replaceAll("\\s", " ");
-
-            // move cause to be ahead of sql, calcite creates the message pattern below
-            Pattern pattern = Pattern.compile("error while executing SQL \"(.*)\":(.*)");
-            Matcher matcher = pattern.matcher(errorMsg);
-            if (matcher.find()) {
-                return matcher.group(2).trim() + "\n" + "while executing SQL: \"" + matcher.group(1).trim() + "\"";
-            } else
-                return errorMsg;
-        } catch (Exception e) {
-            return errorMsg;
-        }
-    }
-
-    private static boolean isTokenWiseEqual(String[] tokens, HashSet<String> tokenSet) {
-        for (String token : tokens) {
-            if (!tokenSet.contains(token)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/util/Serializer.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/util/Serializer.java b/server/src/main/java/org/apache/kylin/rest/util/Serializer.java
deleted file mode 100644
index d726e06..0000000
--- a/server/src/main/java/org/apache/kylin/rest/util/Serializer.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.util;
-
-import java.io.IOException;
-
-import org.apache.kylin.common.util.JsonUtil;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-
-public class Serializer<T> {
-    private final Class<T> type;
-
-    public Serializer(Class<T> type) {
-        this.type = type;
-    }
-
-    public T deserialize(byte[] value) throws JsonParseException, JsonMappingException, IOException {
-        if (null == value) {
-            return null;
-        }
-
-        return JsonUtil.readValue(value, type);
-    }
-
-    public byte[] serialize(T obj) throws JsonProcessingException {
-        if (null == obj) {
-            return null;
-        }
-
-        return JsonUtil.writeValueAsBytes(obj);
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/test/java/org/apache/kylin/rest/bean/BeanTest.java
----------------------------------------------------------------------
diff --git a/server/src/test/java/org/apache/kylin/rest/bean/BeanTest.java b/server/src/test/java/org/apache/kylin/rest/bean/BeanTest.java
deleted file mode 100644
index 03d4dad..0000000
--- a/server/src/test/java/org/apache/kylin/rest/bean/BeanTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.bean;
-
-import java.beans.IntrospectionException;
-
-import org.apache.kylin.rest.constant.Constant;
-import org.apache.kylin.rest.model.ColumnMeta;
-import org.apache.kylin.rest.model.SelectedColumnMeta;
-import org.apache.kylin.rest.model.TableMeta;
-import org.apache.kylin.rest.request.AccessRequest;
-import org.apache.kylin.rest.request.CubeRequest;
-import org.apache.kylin.rest.request.JobListRequest;
-import org.apache.kylin.rest.request.SQLRequest;
-import org.apache.kylin.rest.response.AccessEntryResponse;
-import org.apache.kylin.rest.response.SQLResponse;
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * @author xduo
- * 
- */
-public class BeanTest {
-
-    @Test
-    public void test() {
-        try {
-            BeanValidator.validateAccssor(ColumnMeta.class, new String[0]);
-            BeanValidator.validateAccssor(TableMeta.class, new String[0]);
-            BeanValidator.validateAccssor(SelectedColumnMeta.class, new String[0]);
-            BeanValidator.validateAccssor(AccessRequest.class, new String[0]);
-            BeanValidator.validateAccssor(CubeRequest.class, new String[0]);
-            BeanValidator.validateAccssor(JobListRequest.class, new String[0]);
-            BeanValidator.validateAccssor(SQLRequest.class, new String[0]);
-            BeanValidator.validateAccssor(AccessEntryResponse.class, new String[0]);
-            BeanValidator.validateAccssor(SQLResponse.class, new String[0]);
-        } catch (IntrospectionException e) {
-        }
-
-        new SQLResponse(null, null, null, 0, true, null);
-
-        SelectedColumnMeta coulmnMeta = new SelectedColumnMeta(false, false, false, false, 0, false, 0, null, null, null, null, null, 0, 0, 0, null, false, false, false);
-        Assert.assertTrue(!coulmnMeta.isAutoIncrement());
-        Assert.assertTrue(!coulmnMeta.isCaseSensitive());
-        Assert.assertTrue(!coulmnMeta.isSearchable());
-        Assert.assertTrue(!coulmnMeta.isCurrency());
-        Assert.assertTrue(coulmnMeta.getIsNullable() == 0);
-        Assert.assertTrue(!coulmnMeta.isSigned());
-
-        Assert.assertEquals(Constant.ACCESS_HAS_ROLE_ADMIN, "hasRole('ROLE_ADMIN')");
-        Assert.assertEquals(Constant.ACCESS_POST_FILTER_READ, "hasRole('ROLE_ADMIN') or hasPermission(filterObject, 'READ') or hasPermission(filterObject, 'MANAGEMENT') " + "or hasPermission(filterObject, 'OPERATION') or hasPermission(filterObject, 'ADMINISTRATION')");
-        Assert.assertEquals(Constant.FakeCatalogName, "defaultCatalog");
-        Assert.assertEquals(Constant.FakeSchemaName, "defaultSchema");
-        Assert.assertEquals(Constant.IDENTITY_ROLE, "role");
-        Assert.assertEquals(Constant.IDENTITY_USER, "user");
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/test/java/org/apache/kylin/rest/bean/BeanValidator.java
----------------------------------------------------------------------
diff --git a/server/src/test/java/org/apache/kylin/rest/bean/BeanValidator.java b/server/src/test/java/org/apache/kylin/rest/bean/BeanValidator.java
deleted file mode 100644
index 08010e4..0000000
--- a/server/src/test/java/org/apache/kylin/rest/bean/BeanValidator.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.bean;
-
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.junit.Assert;
-
-/**
- * @author xduo
- * 
- */
-public class BeanValidator {
-
-    /**
-     * Tests the get/set methods of the specified class.
-     */
-    public static <T> void validateAccssor(final Class<T> clazz, final String... skipThese) throws IntrospectionException {
-        final PropertyDescriptor[] props = Introspector.getBeanInfo(clazz).getPropertyDescriptors();
-        for (PropertyDescriptor prop : props) {
-
-            for (String skipThis : skipThese) {
-                if (skipThis.equals(prop.getName())) {
-                    continue;
-                }
-            }
-
-            findBooleanIsMethods(clazz, prop);
-
-            final Method getter = prop.getReadMethod();
-            final Method setter = prop.getWriteMethod();
-
-            if (getter != null && setter != null) {
-                final Class<?> returnType = getter.getReturnType();
-                final Class<?>[] params = setter.getParameterTypes();
-
-                if (params.length == 1 && params[0] == returnType) {
-                    try {
-                        Object value = buildValue(returnType);
-
-                        T bean = clazz.newInstance();
-
-                        setter.invoke(bean, value);
-
-                        Assert.assertEquals(String.format("Failed while testing property %s", prop.getName()), value, getter.invoke(bean));
-
-                    } catch (Exception ex) {
-                        ex.printStackTrace();
-                        System.err.println(String.format("An exception was thrown while testing the property %s: %s", prop.getName(), ex.toString()));
-                    }
-                }
-            }
-        }
-    }
-
-    private static Object buildValue(Class<?> clazz) throws InstantiationException, IllegalAccessException, IllegalArgumentException, SecurityException, InvocationTargetException {
-
-        final Constructor<?>[] ctrs = clazz.getConstructors();
-        for (Constructor<?> ctr : ctrs) {
-            if (ctr.getParameterTypes().length == 0) {
-                return ctr.newInstance();
-            }
-        }
-
-        // Specific rules for common classes
-        if (clazz.isArray()) {
-            return Array.newInstance(clazz.getComponentType(), 1);
-        } else if (List.class.isAssignableFrom(clazz)) {
-            return Collections.emptyList();
-        } else if (Set.class.isAssignableFrom(clazz)) {
-            return Collections.emptySet();
-        } else if (Map.class.isAssignableFrom(clazz)) {
-            return Collections.emptyMap();
-        } else if (clazz == String.class) {
-            return "TEST";
-        } else if (clazz == boolean.class || clazz == Boolean.class) {
-            return true;
-        } else if (clazz == short.class || clazz == Short.class) {
-            return (short) 1;
-        } else if (clazz == int.class || clazz == Integer.class) {
-            return 1;
-        } else if (clazz == long.class || clazz == Long.class) {
-            return 1L;
-        } else if (clazz == double.class || clazz == Double.class) {
-            return 1.0D;
-        } else if (clazz == float.class || clazz == Float.class) {
-            return 1.0F;
-        } else if (clazz == char.class || clazz == Character.class) {
-            return 'T';
-        } else if (clazz.isEnum()) {
-            return clazz.getEnumConstants()[0];
-        } else if (clazz.isInterface()) {
-            return Proxy.newProxyInstance(clazz.getClassLoader(), new java.lang.Class[] { clazz }, new java.lang.reflect.InvocationHandler() {
-                @Override
-                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-                    if (Object.class.getMethod("equals", Object.class).equals(method)) {
-                        return proxy == args[0];
-                    }
-                    if (Object.class.getMethod("hashCode", Object.class).equals(method)) {
-                        return Integer.valueOf(System.identityHashCode(proxy));
-                    }
-                    if (Object.class.getMethod("toString", Object.class).equals(method)) {
-                        return "Bean " + getMockedType(proxy);
-                    }
-
-                    return null;
-                }
-
-            });
-        } else {
-            System.err.println("Unable to build an instance of class " + clazz.getName() + ", please add some code to the " + BeanValidator.class.getName() + " class to do this.");
-            return null;
-        }
-    }
-
-    public static <T> void findBooleanIsMethods(Class<T> clazz, PropertyDescriptor descriptor) throws IntrospectionException {
-        if (descriptor.getReadMethod() == null && descriptor.getPropertyType() == Boolean.class) {
-            try {
-                PropertyDescriptor pd = new PropertyDescriptor(descriptor.getName(), clazz);
-                descriptor.setReadMethod(pd.getReadMethod());
-            } catch (IntrospectionException e) {
-            }
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public static <T, V extends T> Class<T> getMockedType(final V proxy) {
-        if (Proxy.isProxyClass(proxy.getClass())) {
-            return (Class<T>) proxy.getClass().getInterfaces()[0];
-        }
-        return (Class<T>) proxy.getClass().getSuperclass();
-    }
-}


[07/13] kylin git commit: KYLIN-1823 split code from kylin-server into kylin-server-base

Posted by li...@apache.org.
http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/service/ProjectService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/ProjectService.java b/server-base/src/main/java/org/apache/kylin/rest/service/ProjectService.java
new file mode 100644
index 0000000..c0610a2
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/ProjectService.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.service;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.kylin.metadata.project.ProjectInstance;
+import org.apache.kylin.metadata.project.ProjectManager;
+import org.apache.kylin.rest.constant.Constant;
+import org.apache.kylin.rest.exception.InternalErrorException;
+import org.apache.kylin.rest.request.CreateProjectRequest;
+import org.apache.kylin.rest.request.UpdateProjectRequest;
+import org.apache.kylin.rest.security.AclPermission;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author xduo
+ * 
+ */
+@Component("projectService")
+public class ProjectService extends BasicService {
+
+    private static final Logger logger = LoggerFactory.getLogger(ProjectService.class);
+
+    @Autowired
+    private AccessService accessService;
+
+    public ProjectInstance createProject(CreateProjectRequest projectRequest) throws IOException {
+        String projectName = projectRequest.getName();
+        String description = projectRequest.getDescription();
+        ProjectInstance currentProject = getProjectManager().getProject(projectName);
+
+        if (currentProject != null) {
+            throw new InternalErrorException("The project named " + projectName + " already exists");
+        }
+        String owner = SecurityContextHolder.getContext().getAuthentication().getName();
+        ProjectInstance createdProject = getProjectManager().createProject(projectName, owner, description);
+        accessService.init(createdProject, AclPermission.ADMINISTRATION);
+        logger.debug("New project created.");
+
+        return createdProject;
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#currentProject, 'ADMINISTRATION') or hasPermission(#currentProject, 'MANAGEMENT')")
+    public ProjectInstance updateProject(UpdateProjectRequest projectRequest, ProjectInstance currentProject) throws IOException {
+        String formerProjectName = projectRequest.getFormerProjectName();
+        String newProjectName = projectRequest.getNewProjectName();
+        String newDescription = projectRequest.getNewDescription();
+
+        if (currentProject == null) {
+            throw new InternalErrorException("The project named " + formerProjectName + " does not exists");
+        }
+
+        ProjectInstance updatedProject = getProjectManager().updateProject(currentProject, newProjectName, newDescription);
+
+        logger.debug("Project updated.");
+
+        return updatedProject;
+    }
+
+    public List<ProjectInstance> listAllProjects(final Integer limit, final Integer offset) {
+        List<ProjectInstance> projects = getProjectManager().listAllProjects();
+
+        int climit = (null == limit) ? Integer.MAX_VALUE : limit;
+        int coffset = (null == offset) ? 0 : offset;
+
+        if (projects.size() <= coffset) {
+            return Collections.emptyList();
+        }
+
+        if ((projects.size() - coffset) < climit) {
+            return projects.subList(coffset, projects.size());
+        }
+
+        return projects.subList(coffset, coffset + climit);
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#project, 'ADMINISTRATION') or hasPermission(#cube, 'MANAGEMENT')")
+    public void deleteProject(String projectName, ProjectInstance project) throws IOException {
+        getProjectManager().dropProject(projectName);
+
+        accessService.clean(project, true);
+    }
+
+    public boolean isTableInAnyProject(String tableName) {
+        for (ProjectInstance projectInstance : ProjectManager.getInstance(getConfig()).listAllProjects()) {
+            if (projectInstance.containsTable(tableName.toUpperCase())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean isTableInProject(String tableName, String projectName) {
+        ProjectInstance projectInstance = ProjectManager.getInstance(getConfig()).getProject(projectName);
+        if (projectInstance != null) {
+            if (projectInstance.containsTable(tableName.toUpperCase())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/service/QueryService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/QueryService.java b/server-base/src/main/java/org/apache/kylin/rest/service/QueryService.java
new file mode 100644
index 0000000..84a5c67
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/QueryService.java
@@ -0,0 +1,517 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.service;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.sql.DataSource;
+
+import org.apache.calcite.avatica.ColumnMetaData.Rep;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.hadoop.hbase.client.Get;
+import org.apache.hadoop.hbase.client.HConnection;
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.util.Bytes;
+import org.apache.kylin.cube.CubeInstance;
+import org.apache.kylin.cube.CubeManager;
+import org.apache.kylin.cube.cuboid.Cuboid;
+import org.apache.kylin.query.relnode.OLAPContext;
+import org.apache.kylin.rest.constant.Constant;
+import org.apache.kylin.rest.model.ColumnMeta;
+import org.apache.kylin.rest.model.Query;
+import org.apache.kylin.rest.model.SelectedColumnMeta;
+import org.apache.kylin.rest.model.TableMeta;
+import org.apache.kylin.rest.request.PrepareSqlRequest;
+import org.apache.kylin.rest.request.SQLRequest;
+import org.apache.kylin.rest.response.SQLResponse;
+import org.apache.kylin.rest.util.QueryUtil;
+import org.apache.kylin.rest.util.Serializer;
+import org.apache.kylin.storage.hbase.HBaseConnection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+
+import com.google.common.collect.Lists;
+
+/**
+ * @author xduo
+ */
+@Component("queryService")
+public class QueryService extends BasicService {
+
+    private static final Logger logger = LoggerFactory.getLogger(QueryService.class);
+
+    @Autowired
+    private CacheService cacheService;
+
+    public static final String USER_QUERY_FAMILY = "q";
+    private static final String DEFAULT_TABLE_PREFIX = "kylin_metadata";
+    private static final String USER_TABLE_NAME = "_user";
+    private static final String USER_QUERY_COLUMN = "c";
+
+    private final Serializer<Query[]> querySerializer = new Serializer<Query[]>(Query[].class);
+    private final BadQueryDetector badQueryDetector = new BadQueryDetector();
+
+    private final String hbaseUrl;
+    private final String tableNameBase;
+    private final String userTableName;
+
+    public QueryService() {
+        String metadataUrl = KylinConfig.getInstanceFromEnv().getMetadataUrl();
+        // split TABLE@HBASE_URL
+        int cut = metadataUrl.indexOf('@');
+        tableNameBase = cut < 0 ? DEFAULT_TABLE_PREFIX : metadataUrl.substring(0, cut);
+        hbaseUrl = cut < 0 ? metadataUrl : metadataUrl.substring(cut + 1);
+        userTableName = tableNameBase + USER_TABLE_NAME;
+
+        badQueryDetector.start();
+    }
+
+    public List<TableMeta> getMetadata(String project) throws SQLException {
+        return getMetadata(getCubeManager(), project, true);
+    }
+
+    public SQLResponse query(SQLRequest sqlRequest) throws Exception {
+        try {
+            badQueryDetector.queryStart(Thread.currentThread(), sqlRequest);
+
+            return queryWithSqlMassage(sqlRequest);
+
+        } finally {
+            badQueryDetector.queryEnd(Thread.currentThread());
+        }
+    }
+
+    public void saveQuery(final String creator, final Query query) throws IOException {
+        List<Query> queries = getQueries(creator);
+        queries.add(query);
+        Query[] queryArray = new Query[queries.size()];
+
+        byte[] bytes = querySerializer.serialize(queries.toArray(queryArray));
+        HTableInterface htable = null;
+        try {
+            htable = HBaseConnection.get(hbaseUrl).getTable(userTableName);
+            Put put = new Put(Bytes.toBytes(creator));
+            put.add(Bytes.toBytes(USER_QUERY_FAMILY), Bytes.toBytes(USER_QUERY_COLUMN), bytes);
+
+            htable.put(put);
+            htable.flushCommits();
+        } finally {
+            IOUtils.closeQuietly(htable);
+        }
+    }
+
+    public void removeQuery(final String creator, final String id) throws IOException {
+        List<Query> queries = getQueries(creator);
+        Iterator<Query> queryIter = queries.iterator();
+
+        boolean changed = false;
+        while (queryIter.hasNext()) {
+            Query temp = queryIter.next();
+            if (temp.getId().equals(id)) {
+                queryIter.remove();
+                changed = true;
+                break;
+            }
+        }
+
+        if (!changed) {
+            return;
+        }
+
+        Query[] queryArray = new Query[queries.size()];
+        byte[] bytes = querySerializer.serialize(queries.toArray(queryArray));
+        HTableInterface htable = null;
+        try {
+            htable = HBaseConnection.get(hbaseUrl).getTable(userTableName);
+            Put put = new Put(Bytes.toBytes(creator));
+            put.add(Bytes.toBytes(USER_QUERY_FAMILY), Bytes.toBytes(USER_QUERY_COLUMN), bytes);
+
+            htable.put(put);
+            htable.flushCommits();
+        } finally {
+            IOUtils.closeQuietly(htable);
+        }
+    }
+
+    public List<Query> getQueries(final String creator) throws IOException {
+        if (null == creator) {
+            return null;
+        }
+
+        List<Query> queries = new ArrayList<Query>();
+        HTableInterface htable = null;
+        try {
+            HConnection conn = HBaseConnection.get(hbaseUrl);
+            HBaseConnection.createHTableIfNeeded(conn, userTableName, USER_QUERY_FAMILY);
+
+            htable = conn.getTable(userTableName);
+            Get get = new Get(Bytes.toBytes(creator));
+            get.addFamily(Bytes.toBytes(USER_QUERY_FAMILY));
+            Result result = htable.get(get);
+            Query[] query = querySerializer.deserialize(result.getValue(Bytes.toBytes(USER_QUERY_FAMILY), Bytes.toBytes(USER_QUERY_COLUMN)));
+
+            if (null != query) {
+                queries.addAll(Arrays.asList(query));
+            }
+        } finally {
+            IOUtils.closeQuietly(htable);
+        }
+
+        return queries;
+    }
+
+    public void logQuery(final SQLRequest request, final SQLResponse response) {
+        final String user = SecurityContextHolder.getContext().getAuthentication().getName();
+        final Set<String> realizationNames = new HashSet<String>();
+        final Set<Long> cuboidIds = new HashSet<Long>();
+        float duration = response.getDuration() / (float) 1000;
+        boolean storageCacheUsed = response.isStorageCacheUsed();
+
+        if (!response.isHitExceptionCache() && null != OLAPContext.getThreadLocalContexts()) {
+            for (OLAPContext ctx : OLAPContext.getThreadLocalContexts()) {
+                Cuboid cuboid = ctx.storageContext.getCuboid();
+                if (cuboid != null) {
+                    //Some queries do not involve cuboid, e.g. lookup table query
+                    cuboidIds.add(cuboid.getId());
+                }
+
+                if (ctx.realization != null) {
+                    String realizationName = ctx.realization.getName();
+                    realizationNames.add(realizationName);
+                }
+
+            }
+        }
+
+        int resultRowCount = 0;
+        if (!response.getIsException() && response.getResults() != null) {
+            resultRowCount = response.getResults().size();
+        }
+
+        String newLine = System.getProperty("line.separator");
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append(newLine);
+        stringBuilder.append("==========================[QUERY]===============================").append(newLine);
+        stringBuilder.append("SQL: ").append(request.getSql()).append(newLine);
+        stringBuilder.append("User: ").append(user).append(newLine);
+        stringBuilder.append("Success: ").append((null == response.getExceptionMessage())).append(newLine);
+        stringBuilder.append("Duration: ").append(duration).append(newLine);
+        stringBuilder.append("Project: ").append(request.getProject()).append(newLine);
+        stringBuilder.append("Realization Names: ").append(realizationNames).append(newLine);
+        stringBuilder.append("Cuboid Ids: ").append(cuboidIds).append(newLine);
+        stringBuilder.append("Total scan count: ").append(response.getTotalScanCount()).append(newLine);
+        stringBuilder.append("Result row count: ").append(resultRowCount).append(newLine);
+        stringBuilder.append("Accept Partial: ").append(request.isAcceptPartial()).append(newLine);
+        stringBuilder.append("Is Partial Result: ").append(response.isPartial()).append(newLine);
+        stringBuilder.append("Hit Exception Cache: ").append(response.isHitExceptionCache()).append(newLine);
+        stringBuilder.append("Storage cache used: ").append(storageCacheUsed).append(newLine);
+        stringBuilder.append("Message: ").append(response.getExceptionMessage()).append(newLine);
+        stringBuilder.append("==========================[QUERY]===============================").append(newLine);
+
+        logger.info(stringBuilder.toString());
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'MANAGEMENT')" + " or hasPermission(#cube, 'OPERATION') or hasPermission(#cube, 'READ')")
+    public void checkAuthorization(CubeInstance cube) throws AccessDeniedException {
+    }
+
+    private SQLResponse queryWithSqlMassage(SQLRequest sqlRequest) throws Exception {
+        SQLResponse fakeResponse = QueryUtil.tableauIntercept(sqlRequest.getSql());
+        if (null != fakeResponse) {
+            logger.debug("Return fake response, is exception? " + fakeResponse.getIsException());
+            return fakeResponse;
+        }
+
+        String correctedSql = QueryUtil.massageSql(sqlRequest);
+        if (correctedSql.equals(sqlRequest.getSql()) == false)
+            logger.info("The corrected query: " + correctedSql);
+
+        // add extra parameters into olap context, like acceptPartial
+        Map<String, String> parameters = new HashMap<String, String>();
+        parameters.put(OLAPContext.PRM_ACCEPT_PARTIAL_RESULT, String.valueOf(sqlRequest.isAcceptPartial()));
+        OLAPContext.setParameters(parameters);
+
+        return execute(correctedSql, sqlRequest);
+
+    }
+
+    protected List<TableMeta> getMetadata(CubeManager cubeMgr, String project, boolean cubedOnly) throws SQLException {
+
+        Connection conn = null;
+        ResultSet columnMeta = null;
+        List<TableMeta> tableMetas = null;
+        if (StringUtils.isBlank(project)) {
+            return Collections.emptyList();
+        }
+        ResultSet JDBCTableMeta = null;
+        try {
+            DataSource dataSource = cacheService.getOLAPDataSource(project);
+            conn = dataSource.getConnection();
+            DatabaseMetaData metaData = conn.getMetaData();
+
+            logger.debug("getting table metas");
+            JDBCTableMeta = metaData.getTables(null, null, null, null);
+
+            tableMetas = new LinkedList<TableMeta>();
+            Map<String, TableMeta> tableMap = new HashMap<String, TableMeta>();
+            while (JDBCTableMeta.next()) {
+                String catalogName = JDBCTableMeta.getString(1);
+                String schemaName = JDBCTableMeta.getString(2);
+
+                // Not every JDBC data provider offers full 10 columns, e.g., PostgreSQL has only 5
+                TableMeta tblMeta = new TableMeta(catalogName == null ? Constant.FakeCatalogName : catalogName, schemaName == null ? Constant.FakeSchemaName : schemaName, JDBCTableMeta.getString(3), JDBCTableMeta.getString(4), JDBCTableMeta.getString(5), null, null, null, null, null);
+
+                if (!cubedOnly || getProjectManager().isExposedTable(project, schemaName + "." + tblMeta.getTABLE_NAME())) {
+                    tableMetas.add(tblMeta);
+                    tableMap.put(tblMeta.getTABLE_SCHEM() + "#" + tblMeta.getTABLE_NAME(), tblMeta);
+                }
+            }
+
+            logger.debug("getting column metas");
+            columnMeta = metaData.getColumns(null, null, null, null);
+
+            while (columnMeta.next()) {
+                String catalogName = columnMeta.getString(1);
+                String schemaName = columnMeta.getString(2);
+
+                // kylin(optiq) is not strictly following JDBC specification
+                ColumnMeta colmnMeta = new ColumnMeta(catalogName == null ? Constant.FakeCatalogName : catalogName, schemaName == null ? Constant.FakeSchemaName : schemaName, columnMeta.getString(3), columnMeta.getString(4), columnMeta.getInt(5), columnMeta.getString(6), columnMeta.getInt(7), getInt(columnMeta.getString(8)), columnMeta.getInt(9), columnMeta.getInt(10), columnMeta.getInt(11), columnMeta.getString(12), columnMeta.getString(13), getInt(columnMeta.getString(14)), getInt(columnMeta.getString(15)), columnMeta.getInt(16), columnMeta.getInt(17), columnMeta.getString(18), columnMeta.getString(19), columnMeta.getString(20), columnMeta.getString(21), getShort(columnMeta.getString(22)), columnMeta.getString(23));
+
+                if (!cubedOnly || getProjectManager().isExposedColumn(project, schemaName + "." + colmnMeta.getTABLE_NAME(), colmnMeta.getCOLUMN_NAME())) {
+                    tableMap.get(colmnMeta.getTABLE_SCHEM() + "#" + colmnMeta.getTABLE_NAME()).addColumn(colmnMeta);
+                }
+            }
+            logger.debug("done column metas");
+        } finally {
+            close(columnMeta, null, conn);
+            if (JDBCTableMeta != null) {
+                JDBCTableMeta.close();
+            }
+        }
+
+        return tableMetas;
+    }
+
+    /**
+     * @param sql
+     * @param sqlRequest
+     * @return
+     * @throws Exception
+     */
+    private SQLResponse execute(String sql, SQLRequest sqlRequest) throws Exception {
+        Connection conn = null;
+        Statement stat = null;
+        ResultSet resultSet = null;
+
+        List<List<String>> results = Lists.newArrayList();
+        List<SelectedColumnMeta> columnMetas = Lists.newArrayList();
+
+        try {
+            conn = cacheService.getOLAPDataSource(sqlRequest.getProject()).getConnection();
+
+            if (sqlRequest instanceof PrepareSqlRequest) {
+                PreparedStatement preparedState = conn.prepareStatement(sql);
+
+                for (int i = 0; i < ((PrepareSqlRequest) sqlRequest).getParams().length; i++) {
+                    setParam(preparedState, i + 1, ((PrepareSqlRequest) sqlRequest).getParams()[i]);
+                }
+
+                resultSet = preparedState.executeQuery();
+            } else {
+                stat = conn.createStatement();
+                resultSet = stat.executeQuery(sql);
+            }
+
+            ResultSetMetaData metaData = resultSet.getMetaData();
+            int columnCount = metaData.getColumnCount();
+
+            // Fill in selected column meta
+            for (int i = 1; i <= columnCount; ++i) {
+                columnMetas.add(new SelectedColumnMeta(metaData.isAutoIncrement(i), metaData.isCaseSensitive(i), metaData.isSearchable(i), metaData.isCurrency(i), metaData.isNullable(i), metaData.isSigned(i), metaData.getColumnDisplaySize(i), metaData.getColumnLabel(i), metaData.getColumnName(i), metaData.getSchemaName(i), metaData.getCatalogName(i), metaData.getTableName(i), metaData.getPrecision(i), metaData.getScale(i), metaData.getColumnType(i), metaData.getColumnTypeName(i), metaData.isReadOnly(i), metaData.isWritable(i), metaData.isDefinitelyWritable(i)));
+            }
+
+            // fill in results
+            while (resultSet.next()) {
+                List<String> oneRow = Lists.newArrayListWithCapacity(columnCount);
+                for (int i = 0; i < columnCount; i++) {
+                    oneRow.add((resultSet.getString(i + 1)));
+                }
+
+                results.add(oneRow);
+            }
+        } finally {
+            close(resultSet, stat, conn);
+        }
+
+        boolean isPartialResult = false;
+        String cube = "";
+        StringBuilder sb = new StringBuilder("Scan count for each storageContext: ");
+        long totalScanCount = 0;
+        if (OLAPContext.getThreadLocalContexts() != null) { // contexts can be null in case of 'explain plan for'
+            for (OLAPContext ctx : OLAPContext.getThreadLocalContexts()) {
+                if (ctx.realization != null) {
+                    isPartialResult |= ctx.storageContext.isPartialResultReturned();
+                    cube = ctx.realization.getName();
+                    totalScanCount += ctx.storageContext.getTotalScanCount();
+                    sb.append(ctx.storageContext.getTotalScanCount() + ",");
+                }
+            }
+        }
+        logger.info(sb.toString());
+
+        SQLResponse response = new SQLResponse(columnMetas, results, cube, 0, false, null, isPartialResult);
+        response.setTotalScanCount(totalScanCount);
+
+        return response;
+    }
+
+    /**
+     * @param preparedState
+     * @param param
+     * @throws SQLException
+     */
+    private void setParam(PreparedStatement preparedState, int index, PrepareSqlRequest.StateParam param) throws SQLException {
+        boolean isNull = (null == param.getValue());
+
+        Class<?> clazz;
+        try {
+            clazz = Class.forName(param.getClassName());
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+
+        Rep rep = Rep.of(clazz);
+
+        switch (rep) {
+        case PRIMITIVE_CHAR:
+        case CHARACTER:
+        case STRING:
+            preparedState.setString(index, isNull ? null : String.valueOf(param.getValue()));
+            break;
+        case PRIMITIVE_INT:
+        case INTEGER:
+            preparedState.setInt(index, isNull ? 0 : Integer.valueOf(param.getValue()));
+            break;
+        case PRIMITIVE_SHORT:
+        case SHORT:
+            preparedState.setShort(index, isNull ? 0 : Short.valueOf(param.getValue()));
+            break;
+        case PRIMITIVE_LONG:
+        case LONG:
+            preparedState.setLong(index, isNull ? 0 : Long.valueOf(param.getValue()));
+            break;
+        case PRIMITIVE_FLOAT:
+        case FLOAT:
+            preparedState.setFloat(index, isNull ? 0 : Float.valueOf(param.getValue()));
+            break;
+        case PRIMITIVE_DOUBLE:
+        case DOUBLE:
+            preparedState.setDouble(index, isNull ? 0 : Double.valueOf(param.getValue()));
+            break;
+        case PRIMITIVE_BOOLEAN:
+        case BOOLEAN:
+            preparedState.setBoolean(index, !isNull && Boolean.parseBoolean(param.getValue()));
+            break;
+        case PRIMITIVE_BYTE:
+        case BYTE:
+            preparedState.setByte(index, isNull ? 0 : Byte.valueOf(param.getValue()));
+            break;
+        case JAVA_UTIL_DATE:
+        case JAVA_SQL_DATE:
+            preparedState.setDate(index, isNull ? null : java.sql.Date.valueOf(param.getValue()));
+            break;
+        case JAVA_SQL_TIME:
+            preparedState.setTime(index, isNull ? null : Time.valueOf(param.getValue()));
+            break;
+        case JAVA_SQL_TIMESTAMP:
+            preparedState.setTimestamp(index, isNull ? null : Timestamp.valueOf(param.getValue()));
+            break;
+        default:
+            preparedState.setObject(index, isNull ? null : param.getValue());
+        }
+    }
+
+    private int getInt(String content) {
+        try {
+            return Integer.parseInt(content);
+        } catch (Exception e) {
+            return -1;
+        }
+    }
+
+    private short getShort(String content) {
+        try {
+            return Short.parseShort(content);
+        } catch (Exception e) {
+            return -1;
+        }
+    }
+
+    private static void close(ResultSet resultSet, Statement stat, Connection conn) {
+        OLAPContext.clearParameter();
+
+        if (resultSet != null)
+            try {
+                resultSet.close();
+            } catch (SQLException e) {
+                logger.error("failed to close", e);
+            }
+        if (stat != null)
+            try {
+                stat.close();
+            } catch (SQLException e) {
+                logger.error("failed to close", e);
+            }
+        if (conn != null)
+            try {
+                conn.close();
+            } catch (SQLException e) {
+                logger.error("failed to close", e);
+            }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/service/StreamingService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/StreamingService.java b/server-base/src/main/java/org/apache/kylin/rest/service/StreamingService.java
new file mode 100644
index 0000000..e49e882
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/StreamingService.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.service;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.kylin.engine.streaming.StreamingConfig;
+import org.apache.kylin.rest.constant.Constant;
+import org.apache.kylin.rest.exception.InternalErrorException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PostFilter;
+import org.springframework.stereotype.Component;
+
+@Component("streamingMgmtService")
+public class StreamingService extends BasicService {
+
+    @Autowired
+    private AccessService accessService;
+
+    @PostFilter(Constant.ACCESS_POST_FILTER_READ)
+    public List<StreamingConfig> listAllStreamingConfigs(final String table) throws IOException {
+        List<StreamingConfig> streamingConfigs = new ArrayList();
+        if (StringUtils.isEmpty(table)) {
+            streamingConfigs = getStreamingManager().listAllStreaming();
+        } else {
+            StreamingConfig config = getStreamingManager().getConfig(table);
+            if (config != null) {
+                streamingConfigs.add(config);
+            }
+        }
+
+        return streamingConfigs;
+    }
+
+    public List<StreamingConfig> getStreamingConfigs(final String table, final Integer limit, final Integer offset) throws IOException {
+
+        List<StreamingConfig> streamingConfigs;
+        streamingConfigs = listAllStreamingConfigs(table);
+
+        if (limit == null || offset == null) {
+            return streamingConfigs;
+        }
+
+        if ((streamingConfigs.size() - offset) < limit) {
+            return streamingConfigs.subList(offset, streamingConfigs.size());
+        }
+
+        return streamingConfigs.subList(offset, offset + limit);
+    }
+
+    public StreamingConfig createStreamingConfig(StreamingConfig config) throws IOException {
+        if (getStreamingManager().getStreamingConfig(config.getName()) != null) {
+            throw new InternalErrorException("The streamingConfig named " + config.getName() + " already exists");
+        }
+        StreamingConfig streamingConfig = getStreamingManager().saveStreamingConfig(config);
+        return streamingConfig;
+    }
+
+    //    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
+    public StreamingConfig updateStreamingConfig(StreamingConfig config) throws IOException {
+        return getStreamingManager().updateStreamingConfig(config);
+    }
+
+    //    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
+    public void dropStreamingConfig(StreamingConfig config) throws IOException {
+        getStreamingManager().removeStreamingConfig(config);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/service/UserService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/UserService.java b/server-base/src/main/java/org/apache/kylin/rest/service/UserService.java
new file mode 100644
index 0000000..07c7c6f
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/UserService.java
@@ -0,0 +1,289 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.service;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.hadoop.hbase.client.Delete;
+import org.apache.hadoop.hbase.client.Get;
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.ResultScanner;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.kylin.common.util.Bytes;
+import org.apache.kylin.common.util.Pair;
+import org.apache.kylin.rest.security.AclHBaseStorage;
+import org.apache.kylin.rest.util.Serializer;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.provisioning.UserDetailsManager;
+import org.springframework.stereotype.Component;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+
+/**
+ */
+@Component("userService")
+public class UserService implements UserDetailsManager {
+
+    private static final String PWD_PREFIX = "PWD:";
+
+    private Serializer<UserGrantedAuthority[]> ugaSerializer = new Serializer<UserGrantedAuthority[]>(UserGrantedAuthority[].class);
+
+    private String userTableName = null;
+
+    @Autowired
+    protected AclHBaseStorage aclHBaseStorage;
+
+    @PostConstruct
+    public void init() throws IOException {
+        userTableName = aclHBaseStorage.prepareHBaseTable(UserService.class);
+    }
+
+    @Override
+    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+        HTableInterface htable = null;
+        try {
+            htable = aclHBaseStorage.getTable(userTableName);
+
+            Get get = new Get(Bytes.toBytes(username));
+            get.addFamily(Bytes.toBytes(AclHBaseStorage.USER_AUTHORITY_FAMILY));
+            Result result = htable.get(get);
+
+            User user = hbaseRowToUser(result);
+            if (user == null)
+                throw new UsernameNotFoundException("User " + username + " not found.");
+
+            return user;
+        } catch (IOException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        } finally {
+            IOUtils.closeQuietly(htable);
+        }
+    }
+
+    private User hbaseRowToUser(Result result) throws JsonParseException, JsonMappingException, IOException {
+        if (null == result || result.isEmpty())
+            return null;
+
+        String username = Bytes.toString(result.getRow());
+
+        byte[] valueBytes = result.getValue(Bytes.toBytes(AclHBaseStorage.USER_AUTHORITY_FAMILY), Bytes.toBytes(AclHBaseStorage.USER_AUTHORITY_COLUMN));
+        UserGrantedAuthority[] deserialized = ugaSerializer.deserialize(valueBytes);
+
+        String password = "";
+        List<UserGrantedAuthority> authorities = Collections.emptyList();
+
+        // password is stored at [0] of authorities for backward compatibility
+        if (deserialized != null) {
+            if (deserialized.length > 0 && deserialized[0].getAuthority().startsWith(PWD_PREFIX)) {
+                password = deserialized[0].getAuthority().substring(PWD_PREFIX.length());
+                authorities = Arrays.asList(deserialized).subList(1, deserialized.length);
+            } else {
+                authorities = Arrays.asList(deserialized);
+            }
+        }
+
+        return new User(username, password, authorities);
+    }
+
+    private Pair<byte[], byte[]> userToHBaseRow(UserDetails user) throws JsonProcessingException {
+        byte[] key = Bytes.toBytes(user.getUsername());
+
+        Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
+        if (authorities == null)
+            authorities = Collections.emptyList();
+
+        UserGrantedAuthority[] serializing = new UserGrantedAuthority[authorities.size() + 1];
+
+        // password is stored as the [0] authority
+        serializing[0] = new UserGrantedAuthority(PWD_PREFIX + user.getPassword());
+        int i = 1;
+        for (GrantedAuthority a : authorities) {
+            serializing[i++] = new UserGrantedAuthority(a.getAuthority());
+        }
+
+        byte[] value = ugaSerializer.serialize(serializing);
+        return Pair.newPair(key, value);
+    }
+
+    @Override
+    public void createUser(UserDetails user) {
+        updateUser(user);
+    }
+
+    @Override
+    public void updateUser(UserDetails user) {
+        HTableInterface htable = null;
+        try {
+            htable = aclHBaseStorage.getTable(userTableName);
+
+            Pair<byte[], byte[]> pair = userToHBaseRow(user);
+            Put put = new Put(pair.getKey());
+            put.add(Bytes.toBytes(AclHBaseStorage.USER_AUTHORITY_FAMILY), Bytes.toBytes(AclHBaseStorage.USER_AUTHORITY_COLUMN), pair.getSecond());
+
+            htable.put(put);
+            htable.flushCommits();
+        } catch (IOException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        } finally {
+            IOUtils.closeQuietly(htable);
+        }
+    }
+
+    @Override
+    public void deleteUser(String username) {
+        HTableInterface htable = null;
+        try {
+            htable = aclHBaseStorage.getTable(userTableName);
+
+            Delete delete = new Delete(Bytes.toBytes(username));
+
+            htable.delete(delete);
+            htable.flushCommits();
+        } catch (IOException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        } finally {
+            IOUtils.closeQuietly(htable);
+        }
+    }
+
+    @Override
+    public void changePassword(String oldPassword, String newPassword) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean userExists(String username) {
+        HTableInterface htable = null;
+        try {
+            htable = aclHBaseStorage.getTable(userTableName);
+
+            Result result = htable.get(new Get(Bytes.toBytes(username)));
+
+            return null != result && !result.isEmpty();
+        } catch (IOException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        } finally {
+            IOUtils.closeQuietly(htable);
+        }
+    }
+
+    public List<String> listUserAuthorities() {
+        List<String> all = new ArrayList<String>();
+        for (UserDetails user : listUsers()) {
+            for (GrantedAuthority auth : user.getAuthorities()) {
+                if (!all.contains(auth.getAuthority())) {
+                    all.add(auth.getAuthority());
+                }
+            }
+        }
+        return all;
+    }
+
+    public List<UserDetails> listUsers() {
+        Scan s = new Scan();
+        s.addColumn(Bytes.toBytes(AclHBaseStorage.USER_AUTHORITY_FAMILY), Bytes.toBytes(AclHBaseStorage.USER_AUTHORITY_COLUMN));
+
+        List<UserDetails> all = new ArrayList<UserDetails>();
+        HTableInterface htable = null;
+        ResultScanner scanner = null;
+        try {
+            htable = aclHBaseStorage.getTable(userTableName);
+            scanner = htable.getScanner(s);
+
+            for (Result result = scanner.next(); result != null; result = scanner.next()) {
+                User user = hbaseRowToUser(result);
+                all.add(user);
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to scan users", e);
+        } finally {
+            IOUtils.closeQuietly(scanner);
+            IOUtils.closeQuietly(htable);
+        }
+        return all;
+    }
+
+    public static class UserGrantedAuthority implements GrantedAuthority {
+        private static final long serialVersionUID = -5128905636841891058L;
+        private String authority;
+
+        public UserGrantedAuthority() {
+        }
+
+        public UserGrantedAuthority(String authority) {
+            setAuthority(authority);
+        }
+
+        @Override
+        public String getAuthority() {
+            return authority;
+        }
+
+        public void setAuthority(String authority) {
+            this.authority = authority;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((authority == null) ? 0 : authority.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            UserGrantedAuthority other = (UserGrantedAuthority) obj;
+            if (authority == null) {
+                if (other.authority != null)
+                    return false;
+            } else if (!authority.equals(other.authority))
+                return false;
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            return authority;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/util/Log4jConfigListener.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/util/Log4jConfigListener.java b/server-base/src/main/java/org/apache/kylin/rest/util/Log4jConfigListener.java
new file mode 100644
index 0000000..7e79511
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/util/Log4jConfigListener.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.util;
+
+import javax.servlet.ServletContextEvent;
+
+import org.apache.kylin.common.KylinConfig;
+
+public class Log4jConfigListener extends org.springframework.web.util.Log4jConfigListener {
+
+    private boolean isDebugTomcat;
+
+    public Log4jConfigListener() {
+        this.isDebugTomcat = KylinConfig.getInstanceFromEnv().isDevEnv();
+    }
+
+    @Override
+    public void contextInitialized(ServletContextEvent event) {
+        if (!isDebugTomcat) {
+            super.contextInitialized(event);
+        }
+    }
+
+    @Override
+    public void contextDestroyed(ServletContextEvent event) {
+        if (!isDebugTomcat) {
+            super.contextDestroyed(event);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/util/QueryUtil.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/util/QueryUtil.java b/server-base/src/main/java/org/apache/kylin/rest/util/QueryUtil.java
new file mode 100644
index 0000000..c15e5f9
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/util/QueryUtil.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.util;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.kylin.rest.model.SelectedColumnMeta;
+import org.apache.kylin.rest.request.SQLRequest;
+import org.apache.kylin.rest.response.SQLResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ */
+public class QueryUtil {
+
+    protected static final Logger logger = LoggerFactory.getLogger(QueryUtil.class);
+
+    private static final String S0 = "\\s*";
+    private static final String S1 = "\\s";
+    private static final String SM = "\\s+";
+    private static final Pattern PTN_GROUP_BY = Pattern.compile(S1 + "GROUP" + SM + "BY" + S1, Pattern.CASE_INSENSITIVE);
+    private static final Pattern PTN_HAVING_COUNT_GREATER_THAN_ZERO = Pattern.compile(S1 + "HAVING" + SM + "[(]?" + S0 + "COUNT" + S0 + "[(]" + S0 + "1" + S0 + "[)]" + S0 + ">" + S0 + "0" + S0 + "[)]?", Pattern.CASE_INSENSITIVE);
+    private static final Pattern PTN_SUM_1 = Pattern.compile(S1 + "SUM" + S0 + "[(]" + S0 + "[1]" + S0 + "[)]" + S1, Pattern.CASE_INSENSITIVE);
+
+    // private static final Pattern PTN_HAVING_ESCAPE_FUNCTION =
+    // Pattern.compile("\\{fn" + "(" + S0 + ")" + "\\}",
+    // Pattern.CASE_INSENSITIVE);
+    private static final Pattern PTN_HAVING_ESCAPE_FUNCTION = Pattern.compile("\\{fn" + "(.*?)" + "\\}", Pattern.CASE_INSENSITIVE);
+
+    private static String[] tableauTestQueries = new String[] { "SELECT 1", //
+            "CREATE LOCAL TEMPORARY TABLE \"XTableau_B_Connect\" ( \"COL\" INTEGER ) ON COMMIT PRESERVE ROWS", //
+            "DROP TABLE \"XTableau_B_Connect\"", //
+            "SELECT \"COL\" FROM (SELECT 1 AS \"COL\") AS \"SUBQUERY\"", //
+            "SELECT TOP 1 \"COL\" FROM (SELECT 1 AS \"COL\") AS \"CHECKTOP\"", "SELECT \"COL\" FROM (SELECT 1 AS \"COL\") AS \"CHECKTOP\" LIMIT 1", //
+            "SELECT \"SUBCOL\" AS \"COL\"  FROM (   SELECT 1 AS \"SUBCOL\" ) \"SUBQUERY\" GROUP BY 1", "SELECT \"SUBCOL\" AS \"COL\" FROM (   SELECT 1 AS \"SUBCOL\" ) \"SUBQUERY\" GROUP BY 2", "INSERT INTO \"XTableau_C_Connect\" SELECT * FROM (SELECT 1 AS COL) AS CHECKTEMP LIMIT 1", "DROP TABLE \"XTableau_C_Connect\"", "INSERT INTO \"XTableau_B_Connect\" SELECT * FROM (SELECT 1 AS COL) AS CHECKTEMP LIMIT 1" };
+
+    private static SQLResponse temp = new SQLResponse(new LinkedList<SelectedColumnMeta>() {
+        private static final long serialVersionUID = -8086728462624901359L;
+
+        {
+            add(new SelectedColumnMeta(false, false, true, false, 2, true, 11, "COL", "COL", "", "", "", 10, 0, 4, "int4", false, true, false));
+        }
+    }, new LinkedList<List<String>>() {
+        private static final long serialVersionUID = -470083340592928073L;
+
+        {
+            add(new LinkedList<String>() {
+                private static final long serialVersionUID = -3673192785838230054L;
+
+                {
+                    add("1");
+                }
+            });
+        }
+    }, 0, false, null);
+
+    private static SQLResponse[] fakeResponses = new SQLResponse[] { temp, new SQLResponse(null, null, 0, false, null), //
+            new SQLResponse(null, null, 0, false, null), //
+            temp, //
+            new SQLResponse(null, null, 0, true, "near 1 syntax error"), //
+            temp, //
+            new SQLResponse(null, null, 0, true, "group by 1????"), //
+            new SQLResponse(null, null, 0, true, "group by 2????"), //
+            new SQLResponse(null, null, 0, true, "XTableau_C_Connect not exist"), //
+            new SQLResponse(null, null, 0, true, "XTableau_C_Connect not exist"), new SQLResponse(null, null, 0, true, "XTableau_B_Connect not exist"), };
+
+    private static ArrayList<HashSet<String>> tableauTestQueriesInToken = new ArrayList<HashSet<String>>();
+
+    static {
+        for (String q : tableauTestQueries) {
+            HashSet<String> temp = new HashSet<String>();
+            for (String token : q.split("[\r\n\t \\(\\)]")) {
+                temp.add(token);
+            }
+            temp.add("");
+            tableauTestQueriesInToken.add(temp);
+        }
+    }
+
+    public static String massageSql(SQLRequest sqlRequest) {
+        String sql = sqlRequest.getSql();
+        sql = sql.trim();
+
+        while (sql.endsWith(";"))
+            sql = sql.substring(0, sql.length() - 1);
+
+        int limit = sqlRequest.getLimit();
+        if (limit > 0 && !sql.toLowerCase().contains("limit")) {
+            sql += ("\nLIMIT " + limit);
+        }
+
+        int offset = sqlRequest.getOffset();
+        if (offset > 0 && !sql.toLowerCase().contains("offset")) {
+            sql += ("\nOFFSET " + offset);
+        }
+
+        return healSickSql(sql);
+    }
+
+    // correct sick / invalid SQL
+    private static String healSickSql(String sql) {
+        Matcher m;
+
+        // Case fn{ EXTRACT(...) }
+        // Use non-greedy regrex matching to remove escape functions
+        while (true) {
+            m = PTN_HAVING_ESCAPE_FUNCTION.matcher(sql);
+            if (!m.find())
+                break;
+            sql = sql.substring(0, m.start()) + m.group(1) + sql.substring(m.end());
+        }
+
+        // Case: HAVING COUNT(1)>0 without Group By
+        // Tableau generates: SELECT SUM(1) AS "COL" FROM "VAC_SW" HAVING
+        // COUNT(1)>0
+        m = PTN_HAVING_COUNT_GREATER_THAN_ZERO.matcher(sql);
+        if (m.find() && PTN_GROUP_BY.matcher(sql).find() == false) {
+            sql = sql.substring(0, m.start()) + " " + sql.substring(m.end());
+        }
+
+        // Case: SUM(1)
+        // Replace it with COUNT(1)
+        while (true) {
+            m = PTN_SUM_1.matcher(sql);
+            if (!m.find())
+                break;
+            sql = sql.substring(0, m.start()) + " COUNT(1) " + sql.substring(m.end());
+        }
+
+        return sql;
+    }
+
+    public static SQLResponse tableauIntercept(String sql) {
+
+        String[] tokens = sql.split("[\r\n\t \\(\\)]");
+        for (int i = 0; i < tableauTestQueries.length; ++i) {
+            if (isTokenWiseEqual(tokens, tableauTestQueriesInToken.get(i))) {
+                logger.info("Hit fake response " + i);
+                return fakeResponses[i];
+            }
+        }
+
+        return null;
+    }
+
+    public static String makeErrorMsgUserFriendly(Throwable e) {
+        String msg = e.getMessage();
+
+        // pick ParseException error message if possible
+        Throwable cause = e;
+        while (cause != null) {
+            if (cause.getClass().getName().contains("ParseException")) {
+                msg = cause.getMessage();
+                break;
+            }
+            cause = cause.getCause();
+        }
+
+        return makeErrorMsgUserFriendly(msg);
+    }
+
+    public static String makeErrorMsgUserFriendly(String errorMsg) {
+        try {
+            // make one line
+            errorMsg = errorMsg.replaceAll("\\s", " ");
+
+            // move cause to be ahead of sql, calcite creates the message pattern below
+            Pattern pattern = Pattern.compile("error while executing SQL \"(.*)\":(.*)");
+            Matcher matcher = pattern.matcher(errorMsg);
+            if (matcher.find()) {
+                return matcher.group(2).trim() + "\n" + "while executing SQL: \"" + matcher.group(1).trim() + "\"";
+            } else
+                return errorMsg;
+        } catch (Exception e) {
+            return errorMsg;
+        }
+    }
+
+    private static boolean isTokenWiseEqual(String[] tokens, HashSet<String> tokenSet) {
+        for (String token : tokens) {
+            if (!tokenSet.contains(token)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/util/Serializer.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/util/Serializer.java b/server-base/src/main/java/org/apache/kylin/rest/util/Serializer.java
new file mode 100644
index 0000000..d726e06
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/util/Serializer.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.util;
+
+import java.io.IOException;
+
+import org.apache.kylin.common.util.JsonUtil;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+
+public class Serializer<T> {
+    private final Class<T> type;
+
+    public Serializer(Class<T> type) {
+        this.type = type;
+    }
+
+    public T deserialize(byte[] value) throws JsonParseException, JsonMappingException, IOException {
+        if (null == value) {
+            return null;
+        }
+
+        return JsonUtil.readValue(value, type);
+    }
+
+    public byte[] serialize(T obj) throws JsonProcessingException {
+        if (null == obj) {
+            return null;
+        }
+
+        return JsonUtil.writeValueAsBytes(obj);
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/test/java/org/apache/kylin/rest/bean/BeanTest.java
----------------------------------------------------------------------
diff --git a/server-base/src/test/java/org/apache/kylin/rest/bean/BeanTest.java b/server-base/src/test/java/org/apache/kylin/rest/bean/BeanTest.java
new file mode 100644
index 0000000..03d4dad
--- /dev/null
+++ b/server-base/src/test/java/org/apache/kylin/rest/bean/BeanTest.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.bean;
+
+import java.beans.IntrospectionException;
+
+import org.apache.kylin.rest.constant.Constant;
+import org.apache.kylin.rest.model.ColumnMeta;
+import org.apache.kylin.rest.model.SelectedColumnMeta;
+import org.apache.kylin.rest.model.TableMeta;
+import org.apache.kylin.rest.request.AccessRequest;
+import org.apache.kylin.rest.request.CubeRequest;
+import org.apache.kylin.rest.request.JobListRequest;
+import org.apache.kylin.rest.request.SQLRequest;
+import org.apache.kylin.rest.response.AccessEntryResponse;
+import org.apache.kylin.rest.response.SQLResponse;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author xduo
+ * 
+ */
+public class BeanTest {
+
+    @Test
+    public void test() {
+        try {
+            BeanValidator.validateAccssor(ColumnMeta.class, new String[0]);
+            BeanValidator.validateAccssor(TableMeta.class, new String[0]);
+            BeanValidator.validateAccssor(SelectedColumnMeta.class, new String[0]);
+            BeanValidator.validateAccssor(AccessRequest.class, new String[0]);
+            BeanValidator.validateAccssor(CubeRequest.class, new String[0]);
+            BeanValidator.validateAccssor(JobListRequest.class, new String[0]);
+            BeanValidator.validateAccssor(SQLRequest.class, new String[0]);
+            BeanValidator.validateAccssor(AccessEntryResponse.class, new String[0]);
+            BeanValidator.validateAccssor(SQLResponse.class, new String[0]);
+        } catch (IntrospectionException e) {
+        }
+
+        new SQLResponse(null, null, null, 0, true, null);
+
+        SelectedColumnMeta coulmnMeta = new SelectedColumnMeta(false, false, false, false, 0, false, 0, null, null, null, null, null, 0, 0, 0, null, false, false, false);
+        Assert.assertTrue(!coulmnMeta.isAutoIncrement());
+        Assert.assertTrue(!coulmnMeta.isCaseSensitive());
+        Assert.assertTrue(!coulmnMeta.isSearchable());
+        Assert.assertTrue(!coulmnMeta.isCurrency());
+        Assert.assertTrue(coulmnMeta.getIsNullable() == 0);
+        Assert.assertTrue(!coulmnMeta.isSigned());
+
+        Assert.assertEquals(Constant.ACCESS_HAS_ROLE_ADMIN, "hasRole('ROLE_ADMIN')");
+        Assert.assertEquals(Constant.ACCESS_POST_FILTER_READ, "hasRole('ROLE_ADMIN') or hasPermission(filterObject, 'READ') or hasPermission(filterObject, 'MANAGEMENT') " + "or hasPermission(filterObject, 'OPERATION') or hasPermission(filterObject, 'ADMINISTRATION')");
+        Assert.assertEquals(Constant.FakeCatalogName, "defaultCatalog");
+        Assert.assertEquals(Constant.FakeSchemaName, "defaultSchema");
+        Assert.assertEquals(Constant.IDENTITY_ROLE, "role");
+        Assert.assertEquals(Constant.IDENTITY_USER, "user");
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/test/java/org/apache/kylin/rest/bean/BeanValidator.java
----------------------------------------------------------------------
diff --git a/server-base/src/test/java/org/apache/kylin/rest/bean/BeanValidator.java b/server-base/src/test/java/org/apache/kylin/rest/bean/BeanValidator.java
new file mode 100644
index 0000000..08010e4
--- /dev/null
+++ b/server-base/src/test/java/org/apache/kylin/rest/bean/BeanValidator.java
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.bean;
+
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Assert;
+
+/**
+ * @author xduo
+ * 
+ */
+public class BeanValidator {
+
+    /**
+     * Tests the get/set methods of the specified class.
+     */
+    public static <T> void validateAccssor(final Class<T> clazz, final String... skipThese) throws IntrospectionException {
+        final PropertyDescriptor[] props = Introspector.getBeanInfo(clazz).getPropertyDescriptors();
+        for (PropertyDescriptor prop : props) {
+
+            for (String skipThis : skipThese) {
+                if (skipThis.equals(prop.getName())) {
+                    continue;
+                }
+            }
+
+            findBooleanIsMethods(clazz, prop);
+
+            final Method getter = prop.getReadMethod();
+            final Method setter = prop.getWriteMethod();
+
+            if (getter != null && setter != null) {
+                final Class<?> returnType = getter.getReturnType();
+                final Class<?>[] params = setter.getParameterTypes();
+
+                if (params.length == 1 && params[0] == returnType) {
+                    try {
+                        Object value = buildValue(returnType);
+
+                        T bean = clazz.newInstance();
+
+                        setter.invoke(bean, value);
+
+                        Assert.assertEquals(String.format("Failed while testing property %s", prop.getName()), value, getter.invoke(bean));
+
+                    } catch (Exception ex) {
+                        ex.printStackTrace();
+                        System.err.println(String.format("An exception was thrown while testing the property %s: %s", prop.getName(), ex.toString()));
+                    }
+                }
+            }
+        }
+    }
+
+    private static Object buildValue(Class<?> clazz) throws InstantiationException, IllegalAccessException, IllegalArgumentException, SecurityException, InvocationTargetException {
+
+        final Constructor<?>[] ctrs = clazz.getConstructors();
+        for (Constructor<?> ctr : ctrs) {
+            if (ctr.getParameterTypes().length == 0) {
+                return ctr.newInstance();
+            }
+        }
+
+        // Specific rules for common classes
+        if (clazz.isArray()) {
+            return Array.newInstance(clazz.getComponentType(), 1);
+        } else if (List.class.isAssignableFrom(clazz)) {
+            return Collections.emptyList();
+        } else if (Set.class.isAssignableFrom(clazz)) {
+            return Collections.emptySet();
+        } else if (Map.class.isAssignableFrom(clazz)) {
+            return Collections.emptyMap();
+        } else if (clazz == String.class) {
+            return "TEST";
+        } else if (clazz == boolean.class || clazz == Boolean.class) {
+            return true;
+        } else if (clazz == short.class || clazz == Short.class) {
+            return (short) 1;
+        } else if (clazz == int.class || clazz == Integer.class) {
+            return 1;
+        } else if (clazz == long.class || clazz == Long.class) {
+            return 1L;
+        } else if (clazz == double.class || clazz == Double.class) {
+            return 1.0D;
+        } else if (clazz == float.class || clazz == Float.class) {
+            return 1.0F;
+        } else if (clazz == char.class || clazz == Character.class) {
+            return 'T';
+        } else if (clazz.isEnum()) {
+            return clazz.getEnumConstants()[0];
+        } else if (clazz.isInterface()) {
+            return Proxy.newProxyInstance(clazz.getClassLoader(), new java.lang.Class[] { clazz }, new java.lang.reflect.InvocationHandler() {
+                @Override
+                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+                    if (Object.class.getMethod("equals", Object.class).equals(method)) {
+                        return proxy == args[0];
+                    }
+                    if (Object.class.getMethod("hashCode", Object.class).equals(method)) {
+                        return Integer.valueOf(System.identityHashCode(proxy));
+                    }
+                    if (Object.class.getMethod("toString", Object.class).equals(method)) {
+                        return "Bean " + getMockedType(proxy);
+                    }
+
+                    return null;
+                }
+
+            });
+        } else {
+            System.err.println("Unable to build an instance of class " + clazz.getName() + ", please add some code to the " + BeanValidator.class.getName() + " class to do this.");
+            return null;
+        }
+    }
+
+    public static <T> void findBooleanIsMethods(Class<T> clazz, PropertyDescriptor descriptor) throws IntrospectionException {
+        if (descriptor.getReadMethod() == null && descriptor.getPropertyType() == Boolean.class) {
+            try {
+                PropertyDescriptor pd = new PropertyDescriptor(descriptor.getName(), clazz);
+                descriptor.setReadMethod(pd.getReadMethod());
+            } catch (IntrospectionException e) {
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T, V extends T> Class<T> getMockedType(final V proxy) {
+        if (Proxy.isProxyClass(proxy.getClass())) {
+            return (Class<T>) proxy.getClass().getInterfaces()[0];
+        }
+        return (Class<T>) proxy.getClass().getSuperclass();
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/pom.xml
----------------------------------------------------------------------
diff --git a/server/pom.xml b/server/pom.xml
index 3909d79..e662909 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -39,7 +39,7 @@
 
         <dependency>
             <groupId>org.apache.kylin</groupId>
-            <artifactId>kylin-query</artifactId>
+            <artifactId>kylin-server-base</artifactId>
             <version>${project.parent.version}</version>
             <exclusions>
                 <exclusion>
@@ -52,82 +52,7 @@
                 </exclusion>
             </exclusions>
         </dependency>
-        <dependency>
-            <groupId>org.apache.kylin</groupId>
-            <artifactId>kylin-storage-hbase</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.kylin</groupId>
-            <artifactId>kylin-source-hive</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.kylin</groupId>
-            <artifactId>kylin-source-kafka</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.kylin</groupId>
-            <artifactId>kylin-tool</artifactId>
-            <version>${project.parent.version}</version>
-        </dependency>
-
-        <!-- Test & Env -->
-        <dependency>
-            <groupId>org.apache.kylin</groupId>
-            <artifactId>kylin-core-common</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-            <version>${project.parent.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.kylin</groupId>
-            <artifactId>kylin-storage-hbase</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-            <version>${project.parent.version}</version>
-        </dependency>
 
-        <!-- depends on kylin-jdbc just for running jdbc test cases in server module -->
-        <dependency>
-            <groupId>org.apache.kylin</groupId>
-            <artifactId>kylin-jdbc</artifactId>
-            <version>${project.parent.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>xerces</groupId>
-            <artifactId>xercesImpl</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>xalan</groupId>
-            <artifactId>xalan</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
-            <version>${spring.boot.version}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.springframework.boot</groupId>
-                    <artifactId>spring-boot-starter-tomcat</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>log4j-over-slf4j</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>ch.qos.logback</groupId>
-                    <artifactId>logback-classic</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>com.fasterxml.jackson.core</groupId>
-            <artifactId>jackson-databind</artifactId>
-        </dependency>
         <dependency>
             <groupId>com.thetransactioncompany</groupId>
             <artifactId>cors-filter</artifactId>
@@ -141,92 +66,6 @@
         </dependency>
 
         <dependency>
-            <groupId>log4j</groupId>
-            <artifactId>log4j</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>jcl-over-slf4j</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-log4j12</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-beans</artifactId>
-            <version>${spring.framework.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-webmvc</artifactId>
-            <version>${spring.framework.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-jdbc</artifactId>
-            <version>${spring.framework.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-web</artifactId>
-            <version>${spring.framework.version}</version>
-            <type>jar</type>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-core</artifactId>
-            <version>${spring.framework.version}</version>
-            <type>jar</type>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-aop</artifactId>
-            <version>${spring.framework.version}</version>
-            <type>jar</type>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework</groupId>
-            <artifactId>spring-test</artifactId>
-            <version>${spring.framework.version}</version>
-        </dependency>
-
-        <!-- Spring Security -->
-        <dependency>
-            <groupId>org.springframework.security</groupId>
-            <artifactId>spring-security-core</artifactId>
-            <version>${spring.framework.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.security</groupId>
-            <artifactId>spring-security-web</artifactId>
-            <version>${spring.framework.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.security</groupId>
-            <artifactId>spring-security-config</artifactId>
-            <version>${spring.framework.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.security</groupId>
-            <artifactId>spring-security-acl</artifactId>
-            <version>${spring.framework.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.security</groupId>
-            <artifactId>spring-security-ldap</artifactId>
-            <version>${spring.framework.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.security.extensions</groupId>
-            <artifactId>spring-security-saml2-core</artifactId>
-            <version>${spring.framework.security.extensions.version}</version>
-        </dependency>
-        <dependency>
             <groupId>org.opensaml</groupId>
             <artifactId>opensaml</artifactId>
             <version>${opensaml.version}</version>
@@ -249,35 +88,55 @@
                 </exclusion>
             </exclusions>
         </dependency>
+
         <dependency>
-            <groupId>net.sf.ehcache</groupId>
-            <artifactId>ehcache</artifactId>
-            <version>${ehcache.version}</version>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
         </dependency>
         <dependency>
-            <groupId>cglib</groupId>
-            <artifactId>cglib</artifactId>
-            <version>2.2.2</version>
+            <groupId>org.slf4j</groupId>
+            <artifactId>jcl-over-slf4j</artifactId>
         </dependency>
         <dependency>
-            <groupId>net.sf.supercsv</groupId>
-            <artifactId>super-csv</artifactId>
-            <version>2.1.0</version>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
         </dependency>
-
-        <!-- spring aop -->
         <dependency>
-            <groupId>org.aspectj</groupId>
-            <artifactId>aspectjrt</artifactId>
-            <version>1.6.11</version>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+        </dependency>
+        
+        <!-- Test & Env -->
+        <dependency>
+            <groupId>org.apache.kylin</groupId>
+            <artifactId>kylin-core-common</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+            <version>${project.parent.version}</version>
         </dependency>
         <dependency>
-            <groupId>org.aspectj</groupId>
-            <artifactId>aspectjweaver</artifactId>
-            <version>1.6.11</version>
+            <groupId>org.apache.kylin</groupId>
+            <artifactId>kylin-storage-hbase</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.kylin</groupId>
+            <artifactId>kylin-server-base</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+            <version>${project.parent.version}</version>
+        </dependency>
+        
+        <!-- depends on kylin-jdbc just for running jdbc test cases in server module -->
+        <dependency>
+            <groupId>org.apache.kylin</groupId>
+            <artifactId>kylin-jdbc</artifactId>
+            <version>${project.parent.version}</version>
+            <scope>test</scope>
         </dependency>
 
-        <!-- Env & Test -->
         <dependency>
             <groupId>org.apache.hadoop</groupId>
             <artifactId>hadoop-yarn-server-resourcemanager</artifactId>
@@ -407,6 +266,7 @@
                 </exclusion>
             </exclusions>
         </dependency>
+        
         <!-- Tomcat Env -->
         <dependency>
             <groupId>org.apache.tomcat</groupId>
@@ -426,11 +286,7 @@
             <version>7.0.69</version>
             <scope>provided</scope>
         </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
+
         <dependency>
             <groupId>org.apache.hbase</groupId>
             <artifactId>hbase-testing-util</artifactId>
@@ -470,6 +326,11 @@
             <version>${jetty.version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/constant/Constant.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/constant/Constant.java b/server/src/main/java/org/apache/kylin/rest/constant/Constant.java
deleted file mode 100644
index f068e5f..0000000
--- a/server/src/main/java/org/apache/kylin/rest/constant/Constant.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.constant;
-
-/**
- * @author xduo
- * 
- */
-public class Constant {
-
-    public final static String FakeSchemaName = "defaultSchema";
-    public final static String FakeCatalogName = "defaultCatalog";
-
-    public final static String IDENTITY_USER = "user";
-    public final static String IDENTITY_ROLE = "role";
-
-    public final static String ROLE_ADMIN = "ROLE_ADMIN";
-    public final static String ROLE_MODELER = "ROLE_MODELER";
-    public final static String ROLE_ANALYST = "ROLE_ANALYST";
-
-    public final static String ACCESS_HAS_ROLE_ADMIN = "hasRole('ROLE_ADMIN')";
-    public final static String ACCESS_HAS_ROLE_MODELER = "hasRole('ROLE_MODELER')";
-
-    public final static String ACCESS_POST_FILTER_READ = "hasRole('ROLE_ADMIN') or hasPermission(filterObject, 'READ') or hasPermission(filterObject, 'MANAGEMENT') " + "or hasPermission(filterObject, 'OPERATION') or hasPermission(filterObject, 'ADMINISTRATION')";
-
-    public final static String SERVER_MODE_QUERY = "query";
-    public final static String SERVER_MODE_JOB = "job";
-    public final static String SERVER_MODE_ALL = "all";
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/controller/AccessController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/AccessController.java b/server/src/main/java/org/apache/kylin/rest/controller/AccessController.java
deleted file mode 100644
index 461aa3f..0000000
--- a/server/src/main/java/org/apache/kylin/rest/controller/AccessController.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.controller;
-
-import java.io.IOException;
-import java.util.List;
-
-import org.apache.kylin.common.persistence.AclEntity;
-import org.apache.kylin.rest.request.AccessRequest;
-import org.apache.kylin.rest.response.AccessEntryResponse;
-import org.apache.kylin.rest.security.AclPermissionFactory;
-import org.apache.kylin.rest.service.AccessService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.acls.model.Acl;
-import org.springframework.security.acls.model.Permission;
-import org.springframework.security.acls.model.Sid;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-/**
- * @author xduo
- * 
- */
-@Controller
-@RequestMapping(value = "/access")
-public class AccessController extends BasicController {
-
-    @Autowired
-    private AccessService accessService;
-
-    /**
-     * Get access entry list of a domain object
-     * 
-     * @param uuid
-     * @return
-     * @throws IOException
-     */
-    @RequestMapping(value = "/{type}/{uuid}", method = { RequestMethod.GET })
-    @ResponseBody
-    public List<AccessEntryResponse> getAccessEntities(@PathVariable String type, @PathVariable String uuid) {
-        AclEntity ae = accessService.getAclEntity(type, uuid);
-        Acl acl = accessService.getAcl(ae);
-
-        return accessService.generateAceResponses(acl);
-    }
-
-    /**
-     * Grant a new access on a domain object to a user/role
-     * 
-     * @param accessRequest
-     */
-    @RequestMapping(value = "/{type}/{uuid}", method = { RequestMethod.POST })
-    @ResponseBody
-    public List<AccessEntryResponse> grant(@PathVariable String type, @PathVariable String uuid, @RequestBody AccessRequest accessRequest) {
-        AclEntity ae = accessService.getAclEntity(type, uuid);
-        Sid sid = accessService.getSid(accessRequest.getSid(), accessRequest.isPrincipal());
-        Permission permission = AclPermissionFactory.getPermission(accessRequest.getPermission());
-        Acl acl = accessService.grant(ae, permission, sid);
-
-        return accessService.generateAceResponses(acl);
-    }
-
-    /**
-     * Update a access on a domain object
-     * 
-     * @param accessRequest
-     */
-    @RequestMapping(value = "/{type}/{uuid}", method = { RequestMethod.PUT })
-    @ResponseBody
-    public List<AccessEntryResponse> update(@PathVariable String type, @PathVariable String uuid, @RequestBody AccessRequest accessRequest) {
-        AclEntity ae = accessService.getAclEntity(type, uuid);
-        Permission permission = AclPermissionFactory.getPermission(accessRequest.getPermission());
-        Acl acl = accessService.update(ae, accessRequest.getAccessEntryId(), permission);
-
-        return accessService.generateAceResponses(acl);
-    }
-
-    /**
-     * Revoke access on a domain object from a user/role
-     * 
-     * @param AccessRequest
-     */
-    @RequestMapping(value = "/{type}/{uuid}", method = { RequestMethod.DELETE })
-    public List<AccessEntryResponse> revoke(@PathVariable String type, @PathVariable String uuid, AccessRequest accessRequest) {
-        AclEntity ae = accessService.getAclEntity(type, uuid);
-        Acl acl = accessService.revoke(ae, accessRequest.getAccessEntryId());
-
-        return accessService.generateAceResponses(acl);
-    }
-
-    /**
-     * @param accessService
-     */
-    public void setAccessService(AccessService accessService) {
-        this.accessService = accessService;
-    }
-
-}


[13/13] kylin git commit: KYLIN-1823 split code from kylin-server into kylin-server-base

Posted by li...@apache.org.
KYLIN-1823 split code from kylin-server into kylin-server-base


Project: http://git-wip-us.apache.org/repos/asf/kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/1a124e68
Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/1a124e68
Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/1a124e68

Branch: refs/heads/master
Commit: 1a124e68faab349f34f5f47e5e144a8854172f41
Parents: af093f7
Author: Yang Li <li...@apache.org>
Authored: Sun Jun 26 07:34:01 2016 +0800
Committer: Yang Li <li...@apache.org>
Committed: Sun Jun 26 07:34:01 2016 +0800

----------------------------------------------------------------------
 pom.xml                                         |   1 +
 .../.settings/org.eclipse.core.resources.prefs  |   5 +
 .../.settings/org.eclipse.jdt.core.prefs        | 386 ++++++++++
 server-base/.settings/org.eclipse.jdt.ui.prefs  |   7 +
 server-base/pom.xml                             | 270 +++++++
 .../apache/kylin/rest/constant/Constant.java    |  46 ++
 .../kylin/rest/controller/AccessController.java | 118 +++
 .../kylin/rest/controller/AdminController.java  |  97 +++
 .../kylin/rest/controller/BasicController.java  |  69 ++
 .../kylin/rest/controller/CacheController.java  |  82 +++
 .../kylin/rest/controller/CubeController.java   | 615 ++++++++++++++++
 .../rest/controller/CubeDescController.java     |  95 +++
 .../rest/controller/DiagnosisController.java    | 120 +++
 .../controller/ExternalFilterController.java    |  97 +++
 .../kylin/rest/controller/JobController.java    | 221 ++++++
 .../kylin/rest/controller/ModelController.java  | 236 ++++++
 .../rest/controller/ModelDescController.java    |  57 ++
 .../rest/controller/ProjectController.java      | 257 +++++++
 .../kylin/rest/controller/QueryController.java  | 270 +++++++
 .../rest/controller/StreamingController.java    | 297 ++++++++
 .../kylin/rest/controller/TableController.java  | 350 +++++++++
 .../kylin/rest/controller/UserController.java   |  81 +++
 .../rest/exception/BadRequestException.java     |  61 ++
 .../rest/exception/ForbiddenException.java      |  41 ++
 .../rest/exception/InternalErrorException.java  |  63 ++
 .../kylin/rest/exception/NotFoundException.java |  35 +
 .../apache/kylin/rest/init/ClientInfoTask.java  |  51 ++
 .../org/apache/kylin/rest/init/InitialTask.java |  26 +
 .../kylin/rest/init/InitialTaskManager.java     |  58 ++
 .../org/apache/kylin/rest/model/ColumnMeta.java | 264 +++++++
 .../java/org/apache/kylin/rest/model/Query.java | 121 +++
 .../kylin/rest/model/SelectedColumnMeta.java    | 144 ++++
 .../org/apache/kylin/rest/model/TableMeta.java  | 150 ++++
 .../kylin/rest/request/AccessRequest.java       |  67 ++
 .../kylin/rest/request/CardinalityRequest.java  |  77 ++
 .../rest/request/CreateProjectRequest.java      |  46 ++
 .../apache/kylin/rest/request/CubeRequest.java  | 133 ++++
 .../kylin/rest/request/CubeSegmentRequest.java  | 107 +++
 .../rest/request/ExternalFilterRequest.java     |  63 ++
 .../kylin/rest/request/HiveTableRequest.java    |  22 +
 .../kylin/rest/request/JobBuildRequest.java     |  75 ++
 .../kylin/rest/request/JobBuildRequest2.java    |  63 ++
 .../kylin/rest/request/JobListRequest.java      |  86 +++
 .../apache/kylin/rest/request/MetaRequest.java  |  41 ++
 .../kylin/rest/request/MetricsRequest.java      |  59 ++
 .../apache/kylin/rest/request/ModelRequest.java | 107 +++
 .../kylin/rest/request/PrepareSqlRequest.java   | 121 +++
 .../apache/kylin/rest/request/SQLRequest.java   | 132 ++++
 .../kylin/rest/request/SaveSqlRequest.java      |  72 ++
 .../kylin/rest/request/StreamingRequest.java    |  83 +++
 .../kylin/rest/request/UpdateConfigRequest.java |  46 ++
 .../rest/request/UpdateProjectRequest.java      |  55 ++
 .../rest/response/AccessEntryResponse.java      |  70 ++
 .../kylin/rest/response/ErrorResponse.java      |  38 +
 .../kylin/rest/response/GeneralResponse.java    |  31 +
 .../kylin/rest/response/HBaseResponse.java      | 108 +++
 .../kylin/rest/response/MetricsResponse.java    |  55 ++
 .../apache/kylin/rest/response/SQLResponse.java | 168 +++++
 .../kylin/rest/response/TableDescResponse.java  |  81 +++
 .../kylin/rest/security/AclEntityFactory.java   |  64 ++
 .../kylin/rest/security/AclHBaseStorage.java    |  42 ++
 .../kylin/rest/security/AclPermission.java      |  42 ++
 .../rest/security/AclPermissionFactory.java     |  79 ++
 .../rest/security/AuthoritiesPopulator.java     |  75 ++
 .../kylin/rest/security/CrossDomainFilter.java  |  74 ++
 .../security/KylinAuthenticationProvider.java   | 132 ++++
 .../kylin/rest/security/LdapProvider.java       | 105 +++
 .../rest/security/MockAclHBaseStorage.java      |  80 ++
 .../apache/kylin/rest/security/MockHTable.java  | 729 +++++++++++++++++++
 .../security/PasswordPlaceholderConfigurer.java | 106 +++
 .../rest/security/RealAclHBaseStorage.java      |  68 ++
 .../rest/security/SAMLUserDetailsService.java   |  55 ++
 .../rest/security/UnauthorisedEntryPoint.java   |  44 ++
 .../kylin/rest/service/AccessService.java       | 298 ++++++++
 .../apache/kylin/rest/service/AclService.java   | 465 ++++++++++++
 .../apache/kylin/rest/service/AdminService.java | 109 +++
 .../kylin/rest/service/BadQueryDetector.java    | 248 +++++++
 .../apache/kylin/rest/service/BasicService.java | 158 ++++
 .../apache/kylin/rest/service/CacheService.java | 313 ++++++++
 .../apache/kylin/rest/service/CubeService.java  | 676 +++++++++++++++++
 .../kylin/rest/service/DiagnosisService.java    |  74 ++
 .../kylin/rest/service/ExtFilterService.java    |  76 ++
 .../apache/kylin/rest/service/JobService.java   | 388 ++++++++++
 .../kylin/rest/service/KafkaConfigService.java  |  93 +++
 .../apache/kylin/rest/service/ModelService.java | 146 ++++
 .../kylin/rest/service/ProjectService.java      | 127 ++++
 .../apache/kylin/rest/service/QueryService.java | 517 +++++++++++++
 .../kylin/rest/service/StreamingService.java    |  88 +++
 .../apache/kylin/rest/service/UserService.java  | 289 ++++++++
 .../kylin/rest/util/Log4jConfigListener.java    |  47 ++
 .../org/apache/kylin/rest/util/QueryUtil.java   | 210 ++++++
 .../org/apache/kylin/rest/util/Serializer.java  |  51 ++
 .../org/apache/kylin/rest/bean/BeanTest.java    |  74 ++
 .../apache/kylin/rest/bean/BeanValidator.java   | 160 ++++
 server/pom.xml                                  | 231 ++----
 .../apache/kylin/rest/constant/Constant.java    |  46 --
 .../kylin/rest/controller/AccessController.java | 118 ---
 .../kylin/rest/controller/AdminController.java  |  97 ---
 .../kylin/rest/controller/BasicController.java  |  69 --
 .../kylin/rest/controller/CacheController.java  |  82 ---
 .../kylin/rest/controller/CubeController.java   | 615 ----------------
 .../rest/controller/CubeDescController.java     |  95 ---
 .../rest/controller/DiagnosisController.java    | 120 ---
 .../controller/ExternalFilterController.java    |  97 ---
 .../kylin/rest/controller/JobController.java    | 221 ------
 .../kylin/rest/controller/ModelController.java  | 236 ------
 .../rest/controller/ModelDescController.java    |  57 --
 .../rest/controller/ProjectController.java      | 257 -------
 .../kylin/rest/controller/QueryController.java  | 270 -------
 .../rest/controller/StreamingController.java    | 297 --------
 .../kylin/rest/controller/TableController.java  | 350 ---------
 .../kylin/rest/controller/UserController.java   |  81 ---
 .../rest/exception/BadRequestException.java     |  61 --
 .../rest/exception/ForbiddenException.java      |  41 --
 .../rest/exception/InternalErrorException.java  |  63 --
 .../kylin/rest/exception/NotFoundException.java |  35 -
 .../apache/kylin/rest/init/ClientInfoTask.java  |  51 --
 .../org/apache/kylin/rest/init/InitialTask.java |  26 -
 .../kylin/rest/init/InitialTaskManager.java     |  58 --
 .../org/apache/kylin/rest/model/ColumnMeta.java | 264 -------
 .../java/org/apache/kylin/rest/model/Query.java | 121 ---
 .../kylin/rest/model/SelectedColumnMeta.java    | 144 ----
 .../org/apache/kylin/rest/model/TableMeta.java  | 150 ----
 .../kylin/rest/request/AccessRequest.java       |  67 --
 .../kylin/rest/request/CardinalityRequest.java  |  77 --
 .../rest/request/CreateProjectRequest.java      |  46 --
 .../apache/kylin/rest/request/CubeRequest.java  | 133 ----
 .../kylin/rest/request/CubeSegmentRequest.java  | 107 ---
 .../rest/request/ExternalFilterRequest.java     |  63 --
 .../kylin/rest/request/HiveTableRequest.java    |  22 -
 .../kylin/rest/request/JobBuildRequest.java     |  75 --
 .../kylin/rest/request/JobBuildRequest2.java    |  63 --
 .../kylin/rest/request/JobListRequest.java      |  86 ---
 .../apache/kylin/rest/request/MetaRequest.java  |  41 --
 .../kylin/rest/request/MetricsRequest.java      |  59 --
 .../apache/kylin/rest/request/ModelRequest.java | 107 ---
 .../kylin/rest/request/PrepareSqlRequest.java   | 121 ---
 .../apache/kylin/rest/request/SQLRequest.java   | 132 ----
 .../kylin/rest/request/SaveSqlRequest.java      |  72 --
 .../kylin/rest/request/StreamingRequest.java    |  83 ---
 .../kylin/rest/request/UpdateConfigRequest.java |  46 --
 .../rest/request/UpdateProjectRequest.java      |  55 --
 .../rest/response/AccessEntryResponse.java      |  70 --
 .../kylin/rest/response/ErrorResponse.java      |  38 -
 .../kylin/rest/response/GeneralResponse.java    |  31 -
 .../kylin/rest/response/HBaseResponse.java      | 108 ---
 .../kylin/rest/response/MetricsResponse.java    |  55 --
 .../apache/kylin/rest/response/SQLResponse.java | 168 -----
 .../kylin/rest/response/TableDescResponse.java  |  81 ---
 .../kylin/rest/security/AclEntityFactory.java   |  64 --
 .../kylin/rest/security/AclHBaseStorage.java    |  42 --
 .../kylin/rest/security/AclPermission.java      |  42 --
 .../rest/security/AclPermissionFactory.java     |  79 --
 .../rest/security/AuthoritiesPopulator.java     |  75 --
 .../kylin/rest/security/CrossDomainFilter.java  |  74 --
 .../security/KylinAuthenticationProvider.java   | 132 ----
 .../kylin/rest/security/LdapProvider.java       | 105 ---
 .../rest/security/MockAclHBaseStorage.java      |  80 --
 .../apache/kylin/rest/security/MockHTable.java  | 729 -------------------
 .../security/PasswordPlaceholderConfigurer.java | 106 ---
 .../rest/security/RealAclHBaseStorage.java      |  68 --
 .../rest/security/SAMLUserDetailsService.java   |  55 --
 .../rest/security/UnauthorisedEntryPoint.java   |  44 --
 .../kylin/rest/service/AccessService.java       | 298 --------
 .../apache/kylin/rest/service/AclService.java   | 465 ------------
 .../apache/kylin/rest/service/AdminService.java | 109 ---
 .../kylin/rest/service/BadQueryDetector.java    | 248 -------
 .../apache/kylin/rest/service/BasicService.java | 158 ----
 .../apache/kylin/rest/service/CacheService.java | 313 --------
 .../apache/kylin/rest/service/CubeService.java  | 676 -----------------
 .../kylin/rest/service/DiagnosisService.java    |  74 --
 .../kylin/rest/service/ExtFilterService.java    |  76 --
 .../apache/kylin/rest/service/JobService.java   | 388 ----------
 .../kylin/rest/service/KafkaConfigService.java  |  93 ---
 .../apache/kylin/rest/service/ModelService.java | 146 ----
 .../kylin/rest/service/ProjectService.java      | 127 ----
 .../apache/kylin/rest/service/QueryService.java | 517 -------------
 .../kylin/rest/service/StreamingService.java    |  88 ---
 .../apache/kylin/rest/service/UserService.java  | 289 --------
 .../kylin/rest/util/Log4jConfigListener.java    |  47 --
 .../org/apache/kylin/rest/util/QueryUtil.java   | 210 ------
 .../org/apache/kylin/rest/util/Serializer.java  |  51 --
 .../org/apache/kylin/rest/bean/BeanTest.java    |  74 --
 .../apache/kylin/rest/bean/BeanValidator.java   | 160 ----
 184 files changed, 13145 insertions(+), 12615 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 3a84537..f446a2d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -681,6 +681,7 @@
         <module>source-kafka</module>
         <module>storage-hbase</module>
         <module>query</module>
+        <module>server-base</module>
         <module>server</module>
         <module>jdbc</module>
         <module>invertedindex</module>

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/.settings/org.eclipse.core.resources.prefs
----------------------------------------------------------------------
diff --git a/server-base/.settings/org.eclipse.core.resources.prefs b/server-base/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..839d647
--- /dev/null
+++ b/server-base/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding//src/main/resources=UTF-8
+encoding//src/test/java=UTF-8
+encoding/<project>=UTF-8

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/.settings/org.eclipse.jdt.core.prefs
----------------------------------------------------------------------
diff --git a/server-base/.settings/org.eclipse.jdt.core.prefs b/server-base/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..9c69bac
--- /dev/null
+++ b/server-base/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,386 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
+org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
+org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
+org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
+org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
+org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
+org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
+org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
+org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
+org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
+org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=ignore
+org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=false
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=false
+org.eclipse.jdt.core.formatter.comment.format_line_comments=false
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=999
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_on_off_tags=false
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/.settings/org.eclipse.jdt.ui.prefs
----------------------------------------------------------------------
diff --git a/server-base/.settings/org.eclipse.jdt.ui.prefs b/server-base/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..681b0b0
--- /dev/null
+++ b/server-base/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+formatter_profile=_Space Indent & Long Lines
+formatter_settings_version=12
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=1

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/pom.xml
----------------------------------------------------------------------
diff --git a/server-base/pom.xml b/server-base/pom.xml
new file mode 100644
index 0000000..ad54ecf
--- /dev/null
+++ b/server-base/pom.xml
@@ -0,0 +1,270 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you 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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>kylin-server-base</artifactId>
+    <packaging>jar</packaging>
+    <name>Kylin:RESTServerBase</name>
+
+    <parent>
+        <groupId>org.apache.kylin</groupId>
+        <artifactId>kylin</artifactId>
+        <version>1.5.3-SNAPSHOT</version>
+
+    </parent>
+
+    <properties>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.kylin</groupId>
+            <artifactId>kylin-query</artifactId>
+            <version>${project.parent.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>javax.servlet</groupId>
+                    <artifactId>servlet-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>javax.servlet.jsp</groupId>
+                    <artifactId>jsp-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.kylin</groupId>
+            <artifactId>kylin-storage-hbase</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.kylin</groupId>
+            <artifactId>kylin-source-hive</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.kylin</groupId>
+            <artifactId>kylin-source-kafka</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.kylin</groupId>
+            <artifactId>kylin-tool</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>net.sf.ehcache</groupId>
+            <artifactId>ehcache</artifactId>
+            <version>${ehcache.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>cglib</groupId>
+            <artifactId>cglib</artifactId>
+            <version>2.2.2</version>
+        </dependency>
+        <dependency>
+            <groupId>net.sf.supercsv</groupId>
+            <artifactId>super-csv</artifactId>
+            <version>2.1.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <version>${spring.boot.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>log4j-over-slf4j</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>ch.qos.logback</groupId>
+                    <artifactId>logback-classic</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- Spring Core -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-beans</artifactId>
+            <version>${spring.framework.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-webmvc</artifactId>
+            <version>${spring.framework.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-jdbc</artifactId>
+            <version>${spring.framework.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+            <version>${spring.framework.version}</version>
+            <type>jar</type>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-core</artifactId>
+            <version>${spring.framework.version}</version>
+            <type>jar</type>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-aop</artifactId>
+            <version>${spring.framework.version}</version>
+            <type>jar</type>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-test</artifactId>
+            <version>${spring.framework.version}</version>
+        </dependency>
+        
+        <!-- Spring Security -->
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-core</artifactId>
+            <version>${spring.framework.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-web</artifactId>
+            <version>${spring.framework.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-config</artifactId>
+            <version>${spring.framework.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-acl</artifactId>
+            <version>${spring.framework.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-ldap</artifactId>
+            <version>${spring.framework.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security.extensions</groupId>
+            <artifactId>spring-security-saml2-core</artifactId>
+            <version>${spring.framework.security.extensions.version}</version>
+        </dependency>
+
+        <!-- spring aop -->
+        <dependency>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjrt</artifactId>
+            <version>1.6.11</version>
+        </dependency>
+        <dependency>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjweaver</artifactId>
+            <version>1.6.11</version>
+        </dependency>
+
+        <!-- Test & Env -->
+        <dependency>
+            <groupId>org.apache.kylin</groupId>
+            <artifactId>kylin-core-common</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+            <version>${project.parent.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.tomcat</groupId>
+            <artifactId>tomcat-catalina</artifactId>
+            <version>7.0.69</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.hbase</groupId>
+            <artifactId>hbase-client</artifactId>
+            <scope>provided</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>javax.servlet</groupId>
+                    <artifactId>servlet-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>javax.servlet.jsp</groupId>
+                    <artifactId>jsp-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-server</artifactId>
+            <version>${jetty.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-servlet</artifactId>
+            <version>${jetty.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-webapp</artifactId>
+            <version>${jetty.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <repositories>
+        <repository>
+            <id>spring-snapshots</id>
+            <url>http://repo.spring.io/libs-snapshot</url>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+    <pluginRepositories>
+        <pluginRepository>
+            <id>spring-snapshots</id>
+            <url>http://repo.spring.io/libs-snapshot</url>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </pluginRepository>
+    </pluginRepositories>
+</project>

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/constant/Constant.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/constant/Constant.java b/server-base/src/main/java/org/apache/kylin/rest/constant/Constant.java
new file mode 100644
index 0000000..f068e5f
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/constant/Constant.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.constant;
+
+/**
+ * @author xduo
+ * 
+ */
+public class Constant {
+
+    public final static String FakeSchemaName = "defaultSchema";
+    public final static String FakeCatalogName = "defaultCatalog";
+
+    public final static String IDENTITY_USER = "user";
+    public final static String IDENTITY_ROLE = "role";
+
+    public final static String ROLE_ADMIN = "ROLE_ADMIN";
+    public final static String ROLE_MODELER = "ROLE_MODELER";
+    public final static String ROLE_ANALYST = "ROLE_ANALYST";
+
+    public final static String ACCESS_HAS_ROLE_ADMIN = "hasRole('ROLE_ADMIN')";
+    public final static String ACCESS_HAS_ROLE_MODELER = "hasRole('ROLE_MODELER')";
+
+    public final static String ACCESS_POST_FILTER_READ = "hasRole('ROLE_ADMIN') or hasPermission(filterObject, 'READ') or hasPermission(filterObject, 'MANAGEMENT') " + "or hasPermission(filterObject, 'OPERATION') or hasPermission(filterObject, 'ADMINISTRATION')";
+
+    public final static String SERVER_MODE_QUERY = "query";
+    public final static String SERVER_MODE_JOB = "job";
+    public final static String SERVER_MODE_ALL = "all";
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/controller/AccessController.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/AccessController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/AccessController.java
new file mode 100644
index 0000000..461aa3f
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/controller/AccessController.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.controller;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.kylin.common.persistence.AclEntity;
+import org.apache.kylin.rest.request.AccessRequest;
+import org.apache.kylin.rest.response.AccessEntryResponse;
+import org.apache.kylin.rest.security.AclPermissionFactory;
+import org.apache.kylin.rest.service.AccessService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.acls.model.Acl;
+import org.springframework.security.acls.model.Permission;
+import org.springframework.security.acls.model.Sid;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+/**
+ * @author xduo
+ * 
+ */
+@Controller
+@RequestMapping(value = "/access")
+public class AccessController extends BasicController {
+
+    @Autowired
+    private AccessService accessService;
+
+    /**
+     * Get access entry list of a domain object
+     * 
+     * @param uuid
+     * @return
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{type}/{uuid}", method = { RequestMethod.GET })
+    @ResponseBody
+    public List<AccessEntryResponse> getAccessEntities(@PathVariable String type, @PathVariable String uuid) {
+        AclEntity ae = accessService.getAclEntity(type, uuid);
+        Acl acl = accessService.getAcl(ae);
+
+        return accessService.generateAceResponses(acl);
+    }
+
+    /**
+     * Grant a new access on a domain object to a user/role
+     * 
+     * @param accessRequest
+     */
+    @RequestMapping(value = "/{type}/{uuid}", method = { RequestMethod.POST })
+    @ResponseBody
+    public List<AccessEntryResponse> grant(@PathVariable String type, @PathVariable String uuid, @RequestBody AccessRequest accessRequest) {
+        AclEntity ae = accessService.getAclEntity(type, uuid);
+        Sid sid = accessService.getSid(accessRequest.getSid(), accessRequest.isPrincipal());
+        Permission permission = AclPermissionFactory.getPermission(accessRequest.getPermission());
+        Acl acl = accessService.grant(ae, permission, sid);
+
+        return accessService.generateAceResponses(acl);
+    }
+
+    /**
+     * Update a access on a domain object
+     * 
+     * @param accessRequest
+     */
+    @RequestMapping(value = "/{type}/{uuid}", method = { RequestMethod.PUT })
+    @ResponseBody
+    public List<AccessEntryResponse> update(@PathVariable String type, @PathVariable String uuid, @RequestBody AccessRequest accessRequest) {
+        AclEntity ae = accessService.getAclEntity(type, uuid);
+        Permission permission = AclPermissionFactory.getPermission(accessRequest.getPermission());
+        Acl acl = accessService.update(ae, accessRequest.getAccessEntryId(), permission);
+
+        return accessService.generateAceResponses(acl);
+    }
+
+    /**
+     * Revoke access on a domain object from a user/role
+     * 
+     * @param AccessRequest
+     */
+    @RequestMapping(value = "/{type}/{uuid}", method = { RequestMethod.DELETE })
+    public List<AccessEntryResponse> revoke(@PathVariable String type, @PathVariable String uuid, AccessRequest accessRequest) {
+        AclEntity ae = accessService.getAclEntity(type, uuid);
+        Acl acl = accessService.revoke(ae, accessRequest.getAccessEntryId());
+
+        return accessService.generateAceResponses(acl);
+    }
+
+    /**
+     * @param accessService
+     */
+    public void setAccessService(AccessService accessService) {
+        this.accessService = accessService;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/controller/AdminController.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/AdminController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/AdminController.java
new file mode 100644
index 0000000..de3c4b4
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/controller/AdminController.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.controller;
+
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.rest.request.MetricsRequest;
+import org.apache.kylin.rest.request.UpdateConfigRequest;
+import org.apache.kylin.rest.response.GeneralResponse;
+import org.apache.kylin.rest.response.MetricsResponse;
+import org.apache.kylin.rest.service.AdminService;
+import org.apache.kylin.rest.service.CubeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+/**
+ * Admin Controller is defined as Restful API entrance for UI.
+ * 
+ * @author jianliu
+ * 
+ */
+@Controller
+@RequestMapping(value = "/admin")
+public class AdminController extends BasicController {
+
+    @Autowired
+    private AdminService adminService;
+    @Autowired
+    private CubeService cubeMgmtService;
+
+    @RequestMapping(value = "/env", method = { RequestMethod.GET })
+    @ResponseBody
+    public GeneralResponse getEnv() {
+        String env = adminService.getEnv();
+
+        GeneralResponse envRes = new GeneralResponse();
+        envRes.put("env", env);
+
+        return envRes;
+    }
+
+    @RequestMapping(value = "/config", method = { RequestMethod.GET })
+    @ResponseBody
+    public GeneralResponse getConfig() {
+        String config = adminService.getConfigAsString();
+
+        GeneralResponse configRes = new GeneralResponse();
+        configRes.put("config", config);
+
+        return configRes;
+    }
+
+    @RequestMapping(value = "/metrics/cubes", method = { RequestMethod.GET })
+    @ResponseBody
+    public MetricsResponse cubeMetrics(MetricsRequest request) {
+        return cubeMgmtService.calculateMetrics(request);
+    }
+
+    @RequestMapping(value = "/storage", method = { RequestMethod.DELETE })
+    @ResponseBody
+    public void cleanupStorage() {
+        adminService.cleanupStorage();
+    }
+
+    @RequestMapping(value = "/config", method = { RequestMethod.PUT })
+    public void updateKylinConfig(@RequestBody UpdateConfigRequest updateConfigRequest) {
+        KylinConfig.getInstanceFromEnv().setProperty(updateConfigRequest.getKey(), updateConfigRequest.getValue());
+    }
+
+    public void setAdminService(AdminService adminService) {
+        this.adminService = adminService;
+    }
+
+    public void setCubeMgmtService(CubeService cubeMgmtService) {
+        this.cubeMgmtService = cubeMgmtService;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/controller/BasicController.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/BasicController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/BasicController.java
new file mode 100644
index 0000000..0e4a70c
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/controller/BasicController.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.controller;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.kylin.rest.exception.BadRequestException;
+import org.apache.kylin.rest.exception.ForbiddenException;
+import org.apache.kylin.rest.exception.NotFoundException;
+import org.apache.kylin.rest.response.ErrorResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ */
+public class BasicController {
+
+    private static final Logger logger = LoggerFactory.getLogger(BasicController.class);
+
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    @ExceptionHandler(Exception.class)
+    @ResponseBody
+    ErrorResponse handleError(HttpServletRequest req, Exception ex) {
+        logger.error("", ex);
+        return new ErrorResponse(req.getRequestURL().toString(), ex);
+    }
+
+    @ResponseStatus(HttpStatus.FORBIDDEN)
+    @ExceptionHandler(ForbiddenException.class)
+    @ResponseBody
+    ErrorResponse handleForbidden(HttpServletRequest req, Exception ex) {
+        return new ErrorResponse(req.getRequestURL().toString(), ex);
+    }
+
+    @ResponseStatus(HttpStatus.NOT_FOUND)
+    @ExceptionHandler(NotFoundException.class)
+    @ResponseBody
+    ErrorResponse handleNotFound(HttpServletRequest req, Exception ex) {
+        return new ErrorResponse(req.getRequestURL().toString(), ex);
+    }
+
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    @ExceptionHandler(BadRequestException.class)
+    @ResponseBody
+    ErrorResponse handleBadRequest(HttpServletRequest req, Exception ex) {
+        logger.error("", ex);
+        return new ErrorResponse(req.getRequestURL().toString(), ex);
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/controller/CacheController.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/CacheController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/CacheController.java
new file mode 100644
index 0000000..845ffe0
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/controller/CacheController.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.controller;
+
+import java.io.IOException;
+
+import org.apache.kylin.common.restclient.Broadcaster;
+import org.apache.kylin.common.restclient.Broadcaster.EVENT;
+import org.apache.kylin.rest.service.CacheService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+/**
+ * CubeController is defined as Restful API entrance for UI.
+ *
+ * @author jianliu
+ */
+@Controller
+@RequestMapping(value = "/cache")
+public class CacheController extends BasicController {
+    private static final Logger logger = LoggerFactory.getLogger(CacheController.class);
+
+    @Autowired
+    private CacheService cacheService;
+
+    /**
+     * Wipe system cache
+     *
+     * @param type  {@link Broadcaster.TYPE}
+     * @param event {@link Broadcaster.EVENT}
+     * @param name
+     * @return if the action success
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{type}/{name}/{event}", method = { RequestMethod.PUT })
+    @ResponseBody
+    public void wipeCache(@PathVariable String type, @PathVariable String event, @PathVariable String name) throws IOException {
+
+        Broadcaster.TYPE wipeType = Broadcaster.TYPE.getType(type);
+        EVENT wipeEvent = Broadcaster.EVENT.getEvent(event);
+
+        logger.info("wipe cache type: " + wipeType + " event:" + wipeEvent + " name:" + name);
+
+        switch (wipeEvent) {
+        case CREATE:
+        case UPDATE:
+            cacheService.rebuildCache(wipeType, name);
+            break;
+        case DROP:
+            cacheService.removeCache(wipeType, name);
+            break;
+        default:
+            throw new RuntimeException("invalid type:" + wipeEvent);
+        }
+    }
+
+    public void setCacheService(CacheService cacheService) {
+        this.cacheService = cacheService;
+    }
+}


[04/13] kylin git commit: KYLIN-1823 split code from kylin-server into kylin-server-base

Posted by li...@apache.org.
http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/CubeRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/CubeRequest.java b/server/src/main/java/org/apache/kylin/rest/request/CubeRequest.java
deleted file mode 100644
index fb9952b..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/CubeRequest.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.request;
-
-public class CubeRequest {
-
-    private String uuid;
-    private String cubeName;
-    private String cubeDescData;
-    private String streamingData;
-    private String kafkaData;
-    private boolean successful;
-    private String message;
-    private String project;
-    private String streamingCube;
-
-    public String getUuid() {
-        return uuid;
-    }
-
-    public void setUuid(String uuid) {
-        this.uuid = uuid;
-    }
-
-    /**
-     * @return the message
-     */
-    public String getMessage() {
-        return message;
-    }
-
-    /**
-     * @param message
-     *            the message to set
-     */
-    public void setMessage(String message) {
-        this.message = message;
-    }
-
-    /**
-     * @return the status
-     */
-    public boolean getSuccessful() {
-        return successful;
-    }
-
-    /**
-     * @param status
-     *            the status to set
-     */
-    public void setSuccessful(boolean status) {
-        this.successful = status;
-    }
-
-    public CubeRequest() {
-    }
-
-    public CubeRequest(String cubeName, String cubeDescData) {
-        this.cubeName = cubeName;
-        this.cubeDescData = cubeDescData;
-    }
-
-    public String getCubeDescData() {
-        return cubeDescData;
-    }
-
-    public void setCubeDescData(String cubeDescData) {
-        this.cubeDescData = cubeDescData;
-    }
-
-    /**
-     * @return the cubeDescName
-     */
-    public String getCubeName() {
-        return cubeName;
-    }
-
-    /**
-     * @param cubeName
-     *            the cubeDescName to set
-     */
-    public void setCubeName(String cubeName) {
-        this.cubeName = cubeName;
-    }
-
-    public String getProject() {
-        return project;
-    }
-
-    public void setProject(String project) {
-        this.project = project;
-    }
-
-    public String getStreamingCube() {
-        return streamingCube;
-    }
-
-    public void setStreamingCube(String streamingCube) {
-        this.streamingCube = streamingCube;
-    }
-
-    public String getStreamingData() {
-        return streamingData;
-    }
-
-    public void setStreamingData(String streamingData) {
-        this.streamingData = streamingData;
-    }
-
-    public String getKafkaData() {
-        return kafkaData;
-    }
-
-    public void setKafkaData(String kafkaData) {
-        this.kafkaData = kafkaData;
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/CubeSegmentRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/CubeSegmentRequest.java b/server/src/main/java/org/apache/kylin/rest/request/CubeSegmentRequest.java
deleted file mode 100644
index 17122ad..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/CubeSegmentRequest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.request;
-
-public class CubeSegmentRequest {
-
-    private String uuid;
-    private String cubeName;
-    private String cubeSegmentData;
-    private boolean successful;
-    private String message;
-    private String project;
-
-    public String getUuid() {
-        return uuid;
-    }
-
-    public void setUuid(String uuid) {
-        this.uuid = uuid;
-    }
-
-    /**
-     * @return the message
-     */
-    public String getMessage() {
-        return message;
-    }
-
-    /**
-     * @param message
-     *            the message to set
-     */
-    public void setMessage(String message) {
-        this.message = message;
-    }
-
-    /**
-     * @return the status
-     */
-    public boolean getSuccessful() {
-        return successful;
-    }
-
-    /**
-     * @param status
-     *            the status to set
-     */
-    public void setSuccessful(boolean status) {
-        this.successful = status;
-    }
-
-    public CubeSegmentRequest() {
-    }
-
-    public CubeSegmentRequest(String cubeName, String cubeDescData) {
-        this.cubeName = cubeName;
-        this.cubeSegmentData = cubeDescData;
-    }
-
-    public String getCubeSegmentData() {
-        return cubeSegmentData;
-    }
-
-    public void setCubeSegmentData(String cubeSegmentData) {
-        this.cubeSegmentData = cubeSegmentData;
-    }
-
-    /**
-     * @return the cubeDescName
-     */
-    public String getCubeName() {
-        return cubeName;
-    }
-
-    /**
-     * @param cubeName
-     *            the cubeDescName to set
-     */
-    public void setCubeName(String cubeName) {
-        this.cubeName = cubeName;
-    }
-
-    public String getProject() {
-        return project;
-    }
-
-    public void setProject(String project) {
-        this.project = project;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/ExternalFilterRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/ExternalFilterRequest.java b/server/src/main/java/org/apache/kylin/rest/request/ExternalFilterRequest.java
deleted file mode 100644
index 887e9ef..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/ExternalFilterRequest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.request;
-
-public class ExternalFilterRequest {
-
-    private String project;
-
-    private String extFilter;
-
-    private boolean successful;
-
-    private String message;
-
-    public String getProject() {
-        return project;
-    }
-
-    public void setProject(String project) {
-        this.project = project;
-    }
-
-    public boolean isSuccessful() {
-        return successful;
-    }
-
-    public String getExtFilter() {
-        return extFilter;
-    }
-
-    public void setExtFilter(String extFilter) {
-        this.extFilter = extFilter;
-    }
-
-    public void setSuccessful(boolean successful) {
-        this.successful = successful;
-    }
-
-    public String getMessage() {
-        return message;
-    }
-
-    public void setMessage(String message) {
-        this.message = message;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/HiveTableRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/HiveTableRequest.java b/server/src/main/java/org/apache/kylin/rest/request/HiveTableRequest.java
deleted file mode 100644
index c529360..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/HiveTableRequest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.apache.kylin.rest.request;
-
-/**
- * Created by kangkaisen on 16/5/21.
- */
-public class HiveTableRequest {
-
-    public HiveTableRequest() {
-
-    }
-
-    private boolean calculate = true;
-
-    public boolean isCalculate() {
-        return calculate;
-    }
-
-    public void setCalculate(boolean calculate) {
-        this.calculate = calculate;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/JobBuildRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/JobBuildRequest.java b/server/src/main/java/org/apache/kylin/rest/request/JobBuildRequest.java
deleted file mode 100644
index a8ffe5f..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/JobBuildRequest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.request;
-
-public class JobBuildRequest {
-
-    private long startTime;
-
-    private long endTime;
-
-    private String buildType;
-
-    private boolean force;
-
-    @Deprecated
-    private boolean forceMergeEmptySegment = false;
-
-    public long getStartTime() {
-        return startTime;
-    }
-
-    public void setStartTime(long startTime) {
-        this.startTime = startTime;
-    }
-
-    public long getEndTime() {
-        return endTime;
-    }
-
-    public void setEndTime(long endTime) {
-        this.endTime = endTime;
-    }
-
-    public String getBuildType() {
-        return buildType;
-    }
-
-    public void setBuildType(String buildType) {
-        this.buildType = buildType;
-    }
-
-    public boolean isForce() {
-        return force;
-    }
-
-    public void setForce(boolean force) {
-        this.force = force;
-    }
-
-    @Deprecated
-    public boolean isForceMergeEmptySegment() {
-        return forceMergeEmptySegment;
-    }
-
-    @Deprecated
-    public void setForceMergeEmptySegment(boolean forceMergeEmptySegment) {
-        this.forceMergeEmptySegment = forceMergeEmptySegment;
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/JobBuildRequest2.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/JobBuildRequest2.java b/server/src/main/java/org/apache/kylin/rest/request/JobBuildRequest2.java
deleted file mode 100644
index dc3b433..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/JobBuildRequest2.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.request;
-
-public class JobBuildRequest2 {
-
-    private long startSourceOffset;
-
-    private long endSourceOffset;
-
-    private String buildType;
-
-    private boolean force;
-
-    public long getStartSourceOffset() {
-        return startSourceOffset;
-    }
-
-    public void setStartSourceOffset(long startSourceOffset) {
-        this.startSourceOffset = startSourceOffset;
-    }
-
-    public long getEndSourceOffset() {
-        return endSourceOffset;
-    }
-
-    public void setEndSourceOffset(long endSourceOffset) {
-        this.endSourceOffset = endSourceOffset;
-    }
-
-    public String getBuildType() {
-        return buildType;
-    }
-
-    public void setBuildType(String buildType) {
-        this.buildType = buildType;
-    }
-
-    public boolean isForce() {
-        return force;
-    }
-
-    public void setForce(boolean force) {
-        this.force = force;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/JobListRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/JobListRequest.java b/server/src/main/java/org/apache/kylin/rest/request/JobListRequest.java
deleted file mode 100644
index 51160d2..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/JobListRequest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.request;
-
-import java.util.List;
-
-/**
- * @author xduo
- * 
- */
-public class JobListRequest {
-
-    private List<Integer> status;
-    private String cubeName;
-    private String projectName;
-    private Integer offset;
-    private Integer limit;
-    private Integer timeFilter;
-
-    public JobListRequest() {
-    }
-
-    public List<Integer> getStatus() {
-        return status;
-    }
-
-    public void setStatus(List<Integer> status) {
-        this.status = status;
-    }
-
-    public String getCubeName() {
-        return cubeName;
-    }
-
-    public void setCubeName(String cubeName) {
-        this.cubeName = cubeName;
-    }
-
-    public String getProjectName() {
-        return projectName;
-    }
-
-    public void setProjectName(String projectName) {
-        this.projectName = projectName;
-    }
-
-    public Integer getOffset() {
-        return offset;
-    }
-
-    public void setOffset(Integer offset) {
-        this.offset = offset;
-    }
-
-    public Integer getLimit() {
-        return limit;
-    }
-
-    public void setLimit(Integer limit) {
-        this.limit = limit;
-    }
-
-    public Integer getTimeFilter() {
-        return timeFilter;
-    }
-
-    public void setTimeFilter(Integer timeFilter) {
-        this.timeFilter = timeFilter;
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/MetaRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/MetaRequest.java b/server/src/main/java/org/apache/kylin/rest/request/MetaRequest.java
deleted file mode 100644
index 66e8ec0..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/MetaRequest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.request;
-
-/**
- */
-public class MetaRequest {
-
-    private String project;
-
-    public MetaRequest() {
-    }
-
-    public MetaRequest(String project) {
-        this.project = project;
-    }
-
-    public String getProject() {
-        return project;
-    }
-
-    public void setProject(String project) {
-        this.project = project;
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/MetricsRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/MetricsRequest.java b/server/src/main/java/org/apache/kylin/rest/request/MetricsRequest.java
deleted file mode 100644
index daee8f0..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/MetricsRequest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.request;
-
-import java.util.Date;
-
-/**
- * @author xduo
- * 
- */
-public class MetricsRequest {
-
-    private Date startTime;
-
-    private Date endTime;
-
-    private String account;
-
-    public Date getStartTime() {
-        return startTime;
-    }
-
-    public void setStartTime(Date startTime) {
-        this.startTime = startTime;
-    }
-
-    public Date getEndTime() {
-        return endTime;
-    }
-
-    public void setEndTime(Date endTime) {
-        this.endTime = endTime;
-    }
-
-    public String getAccount() {
-        return account;
-    }
-
-    public void setAccount(String account) {
-        this.account = account;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/ModelRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/ModelRequest.java b/server/src/main/java/org/apache/kylin/rest/request/ModelRequest.java
deleted file mode 100644
index dc8e06e..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/ModelRequest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.request;
-
-public class ModelRequest {
-
-    private String uuid;
-    private String modelName;
-    private String modelDescData;
-    private boolean successful;
-    private String message;
-    private String project;
-
-    public String getUuid() {
-        return uuid;
-    }
-
-    public void setUuid(String uuid) {
-        this.uuid = uuid;
-    }
-
-    /**
-     * @return the message
-     */
-    public String getMessage() {
-        return message;
-    }
-
-    /**
-     * @param message
-     *            the message to set
-     */
-    public void setMessage(String message) {
-        this.message = message;
-    }
-
-    /**
-     * @return the status
-     */
-    public boolean getSuccessful() {
-        return successful;
-    }
-
-    /**
-     * @param status
-     *            the status to set
-     */
-    public void setSuccessful(boolean status) {
-        this.successful = status;
-    }
-
-    public ModelRequest() {
-    }
-
-    public ModelRequest(String modelName, String modelDescData) {
-        this.modelName = modelName;
-        this.modelDescData = modelDescData;
-    }
-
-    public String getModelDescData() {
-        return modelDescData;
-    }
-
-    public void setModelDescData(String modelDescData) {
-        this.modelDescData = modelDescData;
-    }
-
-    /**
-     * @return the modelName
-     */
-    public String getModelName() {
-        return modelName;
-    }
-
-    /**
-     * @param modelName
-     *            the cubeName to set
-     */
-    public void setModelName(String modelName) {
-        this.modelName = modelName;
-    }
-
-    public String getProject() {
-        return project;
-    }
-
-    public void setProject(String project) {
-        this.project = project;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/PrepareSqlRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/PrepareSqlRequest.java b/server/src/main/java/org/apache/kylin/rest/request/PrepareSqlRequest.java
deleted file mode 100644
index 95bc2f5..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/PrepareSqlRequest.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.request;
-
-import java.util.Arrays;
-
-/**
- * @author xduo
- * 
- */
-public class PrepareSqlRequest extends SQLRequest {
-
-    public PrepareSqlRequest() {
-        super();
-    }
-
-    private StateParam[] params;
-
-    public StateParam[] getParams() {
-        return params;
-    }
-
-    public void setParams(StateParam[] params) {
-        this.params = params;
-    }
-
-    public static class StateParam {
-        private String className;
-        private String value;
-
-        public StateParam() {
-        }
-
-        public String getClassName() {
-            return className;
-        }
-
-        public void setClassName(String className) {
-            this.className = className;
-        }
-
-        public String getValue() {
-            return value;
-        }
-
-        public void setValue(String value) {
-            this.value = value;
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + ((className == null) ? 0 : className.hashCode());
-            result = prime * result + ((value == null) ? 0 : value.hashCode());
-            return result;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj)
-                return true;
-            if (obj == null)
-                return false;
-            if (getClass() != obj.getClass())
-                return false;
-            StateParam other = (StateParam) obj;
-            if (className == null) {
-                if (other.className != null)
-                    return false;
-            } else if (!className.equals(other.className))
-                return false;
-            if (value == null) {
-                if (other.value != null)
-                    return false;
-            } else if (!value.equals(other.value))
-                return false;
-            return true;
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = super.hashCode();
-        result = prime * result + ((params == null) ? 0 : Arrays.hashCode(params));
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        if (!super.equals(obj))
-            return false;
-        PrepareSqlRequest other = (PrepareSqlRequest) obj;
-        if (!Arrays.equals(params, other.params))
-            return false;
-        return true;
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/SQLRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/SQLRequest.java b/server/src/main/java/org/apache/kylin/rest/request/SQLRequest.java
deleted file mode 100644
index 96f5faa..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/SQLRequest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.request;
-
-import java.io.Serializable;
-import java.util.Map;
-
-public class SQLRequest implements Serializable {
-    protected static final long serialVersionUID = 1L;
-
-    private String sql;
-    private String project;
-    private Integer offset = 0;
-    private Integer limit = 0;
-    private boolean acceptPartial = false;
-
-    private Map<String, String> backdoorToggles;
-
-    public SQLRequest() {
-    }
-
-    public Map<String, String> getBackdoorToggles() {
-        return backdoorToggles;
-    }
-
-    public void setBackdoorToggles(Map<String, String> backdoorToggles) {
-        this.backdoorToggles = backdoorToggles;
-    }
-
-    public String getProject() {
-        return project;
-    }
-
-    public void setProject(String project) {
-        this.project = project;
-    }
-
-    public String getSql() {
-        return sql;
-    }
-
-    public void setSql(String sql) {
-        this.sql = sql;
-    }
-
-    public Integer getOffset() {
-        return offset;
-    }
-
-    public void setOffset(Integer offset) {
-        this.offset = offset;
-    }
-
-    public Integer getLimit() {
-        return limit;
-    }
-
-    public void setLimit(Integer limit) {
-        this.limit = limit;
-    }
-
-    public boolean isAcceptPartial() {
-        return acceptPartial;
-    }
-
-    public void setAcceptPartial(boolean acceptPartial) {
-        this.acceptPartial = acceptPartial;
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + (acceptPartial ? 1231 : 1237);
-        result = prime * result + ((offset == null) ? 0 : offset.hashCode());
-        result = prime * result + ((limit == null) ? 0 : limit.hashCode());
-        result = prime * result + ((project == null) ? 0 : project.hashCode());
-        result = prime * result + ((sql == null) ? 0 : sql.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        SQLRequest other = (SQLRequest) obj;
-        if (acceptPartial != other.acceptPartial)
-            return false;
-        if (offset == null) {
-            if (other.offset != null)
-                return false;
-        } else if (!offset.equals(other.offset))
-            return false;
-        if (limit == null) {
-            if (other.limit != null)
-                return false;
-        } else if (!limit.equals(other.limit))
-            return false;
-        if (project == null) {
-            if (other.project != null)
-                return false;
-        } else if (!project.equals(other.project))
-            return false;
-        if (sql == null) {
-            if (other.sql != null)
-                return false;
-        } else if (!sql.equals(other.sql))
-            return false;
-        return true;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/SaveSqlRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/SaveSqlRequest.java b/server/src/main/java/org/apache/kylin/rest/request/SaveSqlRequest.java
deleted file mode 100644
index affab1c..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/SaveSqlRequest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.request;
-
-/**
- * @author xduo
- * 
- */
-public class SaveSqlRequest {
-    private long id;
-    private String name;
-    private String sql;
-    private String project;
-    private String description;
-
-    public long getId() {
-        return id;
-    }
-
-    public void setId(long id) {
-        this.id = id;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getSql() {
-        return sql;
-    }
-
-    public void setSql(String sql) {
-        this.sql = sql;
-    }
-
-    public String getProject() {
-        return project;
-    }
-
-    public void setProject(String project) {
-        this.project = project;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/StreamingRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/StreamingRequest.java b/server/src/main/java/org/apache/kylin/rest/request/StreamingRequest.java
deleted file mode 100644
index 96db4da..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/StreamingRequest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.request;
-
-public class StreamingRequest {
-
-    private String project;
-
-    private String tableData;
-
-    private String streamingConfig;
-
-    private String kafkaConfig;
-
-    private boolean successful;
-
-    private String message;
-
-    public String getProject() {
-        return project;
-    }
-
-    public void setProject(String project) {
-        this.project = project;
-    }
-
-    public String getTableData() {
-        return tableData;
-    }
-
-    public void setTableData(String tableData) {
-        this.tableData = tableData;
-    }
-
-    public boolean isSuccessful() {
-        return successful;
-    }
-
-    public void setSuccessful(boolean successful) {
-        this.successful = successful;
-    }
-
-    public String getMessage() {
-        return message;
-    }
-
-    public void setMessage(String message) {
-        this.message = message;
-    }
-
-    public String getStreamingConfig() {
-        return streamingConfig;
-    }
-
-    public void setStreamingConfig(String streamingConfig) {
-        this.streamingConfig = streamingConfig;
-    }
-
-    public String getKafkaConfig() {
-        return kafkaConfig;
-    }
-
-    public void setKafkaConfig(String kafkaConfig) {
-        this.kafkaConfig = kafkaConfig;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/UpdateConfigRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/UpdateConfigRequest.java b/server/src/main/java/org/apache/kylin/rest/request/UpdateConfigRequest.java
deleted file mode 100644
index 50f7f9b..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/UpdateConfigRequest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.request;
-
-/**
- * @author xduo
- * 
- */
-public class UpdateConfigRequest {
-    private String key;
-
-    private String value;
-
-    public String getKey() {
-        return key;
-    }
-
-    public void setKey(String key) {
-        this.key = key;
-    }
-
-    public String getValue() {
-        return value;
-    }
-
-    public void setValue(String value) {
-        this.value = value;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java b/server/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java
deleted file mode 100644
index 29ba162..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.request;
-
-/**
- */
-public class UpdateProjectRequest {
-    private String formerProjectName;
-    private String newProjectName;
-    private String newDescription;
-
-    public UpdateProjectRequest() {
-    }
-
-    public String getFormerProjectName() {
-        return formerProjectName;
-    }
-
-    public void setFormerProjectName(String formerProjectName) {
-
-        this.formerProjectName = formerProjectName;
-    }
-
-    public String getNewDescription() {
-        return newDescription;
-    }
-
-    public void setNewDescription(String newDescription) {
-        this.newDescription = newDescription;
-    }
-
-    public String getNewProjectName() {
-        return newProjectName;
-    }
-
-    public void setNewProjectName(String newProjectName) {
-        this.newProjectName = newProjectName;
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/response/AccessEntryResponse.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/response/AccessEntryResponse.java b/server/src/main/java/org/apache/kylin/rest/response/AccessEntryResponse.java
deleted file mode 100644
index 5c55d58..0000000
--- a/server/src/main/java/org/apache/kylin/rest/response/AccessEntryResponse.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.response;
-
-import java.io.Serializable;
-
-import org.springframework.security.acls.model.Permission;
-import org.springframework.security.acls.model.Sid;
-import org.springframework.util.Assert;
-
-/**
- * @author xduo
- * 
- */
-public class AccessEntryResponse {
-
-    private Permission permission;
-    private Serializable id;
-    private Sid sid;
-    private boolean granting;
-
-    public AccessEntryResponse() {
-    }
-
-    public AccessEntryResponse(Serializable id, Sid sid, Permission permission, boolean granting) {
-        Assert.notNull(sid, "Sid required");
-        Assert.notNull(permission, "Permission required");
-        this.id = id;
-        this.sid = sid;
-        this.permission = permission;
-        this.granting = granting;
-    }
-
-    public Permission getPermission() {
-        return permission;
-    }
-
-    public void setPermission(Permission permission) {
-        this.permission = permission;
-    }
-
-    public Serializable getId() {
-        return id;
-    }
-
-    public Sid getSid() {
-        return sid;
-    }
-
-    public boolean isGranting() {
-        return granting;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/response/ErrorResponse.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/response/ErrorResponse.java b/server/src/main/java/org/apache/kylin/rest/response/ErrorResponse.java
deleted file mode 100644
index 3327cc0..0000000
--- a/server/src/main/java/org/apache/kylin/rest/response/ErrorResponse.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.response;
-
-/**
- * @author xduo
- * 
- */
-public class ErrorResponse {
-
-    public String url;
-    public String exception;
-
-    /**
-     * @param exception
-     */
-    public ErrorResponse(String url, Exception exception) {
-        this.url = url;
-        this.exception = exception.getLocalizedMessage();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/response/GeneralResponse.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/response/GeneralResponse.java b/server/src/main/java/org/apache/kylin/rest/response/GeneralResponse.java
deleted file mode 100644
index bc7c081..0000000
--- a/server/src/main/java/org/apache/kylin/rest/response/GeneralResponse.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.response;
-
-import java.util.Properties;
-
-/**
- * @author xduo
- * 
- */
-public class GeneralResponse extends Properties {
-
-    private static final long serialVersionUID = -6540990247122312493L;
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/response/HBaseResponse.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/response/HBaseResponse.java b/server/src/main/java/org/apache/kylin/rest/response/HBaseResponse.java
deleted file mode 100644
index 607d61a..0000000
--- a/server/src/main/java/org/apache/kylin/rest/response/HBaseResponse.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.response;
-
-import java.io.Serializable;
-
-public class HBaseResponse implements Serializable {
-    private static final long serialVersionUID = 7263557115683263492L;
-    private String tableName;
-    private long tableSize;
-    private int regionCount;
-    private long dateRangeStart;
-    private long dateRangeEnd;
-
-    public HBaseResponse() {
-    }
-
-    /**
-     * @return The hbase table name.
-     */
-    public String getTableName() {
-        return tableName;
-    }
-
-    /**
-     * @param tableName
-     *            The hbase table name.
-     */
-    public void setTableName(String tableName) {
-        this.tableName = tableName;
-    }
-
-    /**
-     * @return the tableSize
-     */
-    public long getTableSize() {
-        return tableSize;
-    }
-
-    /**
-     * @param tableSize
-     *            the tableSize to set
-     */
-    public void setTableSize(long tableSize) {
-        this.tableSize = tableSize;
-    }
-
-    /**
-     * @return the regionCount
-     */
-    public int getRegionCount() {
-        return regionCount;
-    }
-
-    /**
-     * @param regionCount
-     *            the regionCount to set
-     */
-    public void setRegionCount(int regionCount) {
-        this.regionCount = regionCount;
-    }
-
-    /**
-     * @return the segmentStartTime
-     */
-    public long getDateRangeStart() {
-        return dateRangeStart;
-    }
-
-    /**
-     * @param segmentStartTime
-     *            the segmentStartTime to set
-     */
-    public void setDateRangeStart(long dateRangeStart) {
-        this.dateRangeStart = dateRangeStart;
-    }
-
-    /**
-     * @return the segmentEndTime
-     */
-    public long getDateRangeEnd() {
-        return dateRangeEnd;
-    }
-
-    /**
-     * @param segmentEndTime
-     *            the segmentEndTime to set
-     */
-    public void setDateRangeEnd(long dateRangeEnd) {
-        this.dateRangeEnd = dateRangeEnd;
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/response/MetricsResponse.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/response/MetricsResponse.java b/server/src/main/java/org/apache/kylin/rest/response/MetricsResponse.java
deleted file mode 100644
index 34cdfcb..0000000
--- a/server/src/main/java/org/apache/kylin/rest/response/MetricsResponse.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.response;
-
-import java.util.HashMap;
-
-/**
- * @author xduo
- * 
- */
-public class MetricsResponse extends HashMap<String, Float> {
-
-    private static final long serialVersionUID = 1L;
-
-    public void increase(String key) {
-        increase(key, (float) 1);
-    }
-
-    public void increase(String key, Float increased) {
-        if (this.containsKey(key)) {
-            this.put(key, (this.get(key) + increased));
-        } else {
-            this.put(key, increased);
-        }
-    }
-
-    public void decrease(String key) {
-        decrease(key, (float) 1);
-    }
-
-    public void decrease(String key, Float decreased) {
-        if (this.containsKey(key)) {
-            this.put(key, (this.get(key) - decreased));
-        } else {
-            this.put(key, decreased);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/response/SQLResponse.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/response/SQLResponse.java b/server/src/main/java/org/apache/kylin/rest/response/SQLResponse.java
deleted file mode 100644
index 9c4e9da..0000000
--- a/server/src/main/java/org/apache/kylin/rest/response/SQLResponse.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.response;
-
-import java.io.Serializable;
-import java.util.List;
-
-import org.apache.kylin.rest.model.SelectedColumnMeta;
-
-public class SQLResponse implements Serializable {
-    protected static final long serialVersionUID = 1L;
-
-    // private static final Logger logger =
-    // LoggerFactory.getLogger(SQLResponse.class);
-
-    // the data type for each column
-    protected List<SelectedColumnMeta> columnMetas;
-
-    // the results rows, each row contains several columns
-    protected List<List<String>> results;
-
-    /**
-     * for historical reasons it is named "cube", however it might also refer to any realizations like hybrid, II or etc.
-     */
-    protected String cube;
-
-    // if not select query, only return affected row count
-    protected int affectedRowCount;
-
-    // flag indicating whether an exception occurred
-    protected boolean isException;
-
-    // if isException, the detailed exception message
-    protected String exceptionMessage;
-
-    protected long duration;
-
-    protected boolean isPartial = false;
-
-    protected long totalScanCount;
-
-    protected boolean hitExceptionCache = false;
-
-    protected boolean storageCacheUsed = false;
-
-    public SQLResponse() {
-    }
-
-    public SQLResponse(List<SelectedColumnMeta> columnMetas, List<List<String>> results, int affectedRowCount, boolean isException, String exceptionMessage) {
-        this.columnMetas = columnMetas;
-        this.results = results;
-        this.affectedRowCount = affectedRowCount;
-        this.isException = isException;
-        this.exceptionMessage = exceptionMessage;
-    }
-
-    public SQLResponse(List<SelectedColumnMeta> columnMetas, List<List<String>> results, String cube, int affectedRowCount, boolean isException, String exceptionMessage) {
-        this.columnMetas = columnMetas;
-        this.results = results;
-        this.cube = cube;
-        this.affectedRowCount = affectedRowCount;
-        this.isException = isException;
-        this.exceptionMessage = exceptionMessage;
-    }
-
-    public SQLResponse(List<SelectedColumnMeta> columnMetas, List<List<String>> results, String cube, int affectedRowCount, boolean isException, String exceptionMessage, boolean isPartial) {
-        this.columnMetas = columnMetas;
-        this.results = results;
-        this.cube = cube;
-        this.affectedRowCount = affectedRowCount;
-        this.isException = isException;
-        this.exceptionMessage = exceptionMessage;
-        this.isPartial = isPartial;
-    }
-
-    public List<SelectedColumnMeta> getColumnMetas() {
-        return columnMetas;
-    }
-
-    public List<List<String>> getResults() {
-        return results;
-    }
-
-    public void setResults(List<List<String>> results) {
-        this.results = results;
-    }
-
-    public String getCube() {
-        return cube;
-    }
-
-    public void setCube(String cube) {
-        this.cube = cube;
-    }
-
-    public int getAffectedRowCount() {
-        return affectedRowCount;
-    }
-
-    public boolean getIsException() {
-        return isException;
-    }
-
-    public void setIsException(boolean v) {
-        isException = v;
-    }
-
-    public String getExceptionMessage() {
-        return exceptionMessage;
-    }
-
-    public void setExceptionMessage(String msg) {
-        exceptionMessage = msg;
-    }
-
-    public long getDuration() {
-        return duration;
-    }
-
-    public void setDuration(long duration) {
-        this.duration = duration;
-    }
-
-    public boolean isPartial() {
-
-        return isPartial;
-    }
-
-    public long getTotalScanCount() {
-        return totalScanCount;
-    }
-
-    public void setTotalScanCount(long totalScanCount) {
-        this.totalScanCount = totalScanCount;
-    }
-
-    public boolean isHitExceptionCache() {
-        return hitExceptionCache;
-    }
-
-    public void setHitExceptionCache(boolean hitExceptionCache) {
-        this.hitExceptionCache = hitExceptionCache;
-    }
-
-    public boolean isStorageCacheUsed() {
-        return storageCacheUsed;
-    }
-
-    public void setStorageCacheUsed(boolean storageCacheUsed) {
-        this.storageCacheUsed = storageCacheUsed;
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/response/TableDescResponse.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/response/TableDescResponse.java b/server/src/main/java/org/apache/kylin/rest/response/TableDescResponse.java
deleted file mode 100644
index 5dede2a..0000000
--- a/server/src/main/java/org/apache/kylin/rest/response/TableDescResponse.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.response;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.kylin.metadata.model.TableDesc;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-/**
- * A response class to wrap TableDesc
- * 
- * @author jianliu
- * 
- */
-public class TableDescResponse extends TableDesc {
-    @JsonProperty("exd")
-    Map<String, String> descExd = new HashMap<String, String>();
-    @JsonProperty("cardinality")
-    Map<String, Long> cardinality = new HashMap<String, Long>();
-
-    /**
-     * @return the cardinality
-     */
-    public Map<String, Long> getCardinality() {
-        return cardinality;
-    }
-
-    /**
-     * @param cardinality
-     *            the cardinality to set
-     */
-    public void setCardinality(Map<String, Long> cardinality) {
-        this.cardinality = cardinality;
-    }
-
-    /**
-     * @return the descExd
-     */
-    public Map<String, String> getDescExd() {
-        return descExd;
-    }
-
-    /**
-     * @param descExd
-     *            the descExd to set
-     */
-    public void setDescExd(Map<String, String> descExd) {
-        this.descExd = descExd;
-    }
-
-    /**
-     * @param table
-     */
-    public TableDescResponse(TableDesc table) {
-        this.setColumns(table.getColumns());
-        this.setDatabase(table.getDatabase());
-        this.setName(table.getName());
-        this.setSourceType(table.getSourceType());
-        this.setUuid(table.getUuid());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/security/AclEntityFactory.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/AclEntityFactory.java b/server/src/main/java/org/apache/kylin/rest/security/AclEntityFactory.java
deleted file mode 100644
index 621fbe4..0000000
--- a/server/src/main/java/org/apache/kylin/rest/security/AclEntityFactory.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.security;
-
-import org.apache.kylin.common.persistence.RootPersistentEntity;
-import org.apache.kylin.cube.CubeInstance;
-import org.apache.kylin.job.JobInstance;
-import org.apache.kylin.metadata.model.DataModelDesc;
-import org.apache.kylin.metadata.project.ProjectInstance;
-
-/**
- * @author xduo
- * 
- */
-public class AclEntityFactory {
-
-    public static RootPersistentEntity createAclEntity(String entityType, String uuid) {
-        if ("CubeInstance".equals(entityType)) {
-            CubeInstance cubeInstance = new CubeInstance();
-            cubeInstance.setUuid(uuid);
-
-            return cubeInstance;
-        }
-
-        if ("DataModelDesc".equals(entityType)) {
-            DataModelDesc modelInstance = new DataModelDesc();
-            modelInstance.setUuid(uuid);
-
-            return modelInstance;
-        }
-
-        if ("JobInstance".equals(entityType)) {
-            JobInstance jobInstance = new JobInstance();
-            jobInstance.setUuid(uuid);
-
-            return jobInstance;
-        }
-
-        if ("ProjectInstance".equals(entityType)) {
-            ProjectInstance projectInstance = new ProjectInstance();
-            projectInstance.setUuid(uuid);
-
-            return projectInstance;
-        }
-
-        throw new RuntimeException("Unsupported entity type!");
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/security/AclHBaseStorage.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/AclHBaseStorage.java b/server/src/main/java/org/apache/kylin/rest/security/AclHBaseStorage.java
deleted file mode 100644
index 38f299e..0000000
--- a/server/src/main/java/org/apache/kylin/rest/security/AclHBaseStorage.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.security;
-
-import java.io.IOException;
-
-import org.apache.hadoop.hbase.client.HTableInterface;
-
-/**
- */
-public interface AclHBaseStorage {
-    String DEFAULT_TABLE_PREFIX = "kylin_metadata";
-
-    String ACL_INFO_FAMILY = "i";
-    String ACL_ACES_FAMILY = "a";
-    String ACL_TABLE_NAME = "_acl";
-
-    String USER_AUTHORITY_FAMILY = "a";
-    String USER_TABLE_NAME = "_user";
-    String USER_AUTHORITY_COLUMN = "c";
-
-    String prepareHBaseTable(Class<?> clazz) throws IOException;
-
-    HTableInterface getTable(String tableName) throws IOException;
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/security/AclPermission.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/AclPermission.java b/server/src/main/java/org/apache/kylin/rest/security/AclPermission.java
deleted file mode 100644
index 4e2e182..0000000
--- a/server/src/main/java/org/apache/kylin/rest/security/AclPermission.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.security;
-
-import org.springframework.security.acls.domain.BasePermission;
-import org.springframework.security.acls.model.Permission;
-
-/**
- * @author xduo
- * 
- */
-public class AclPermission extends BasePermission {
-
-    private static final long serialVersionUID = 6121785617686149123L;
-
-    public static final Permission MANAGEMENT = new AclPermission(1 << 5, 'M'); // 32
-    public static final Permission OPERATION = new AclPermission(1 << 6, 'O'); // 64
-
-    protected AclPermission(int mask) {
-        super(mask);
-    }
-
-    protected AclPermission(int mask, char code) {
-        super(mask, code);
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/security/AclPermissionFactory.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/AclPermissionFactory.java b/server/src/main/java/org/apache/kylin/rest/security/AclPermissionFactory.java
deleted file mode 100644
index d662403..0000000
--- a/server/src/main/java/org/apache/kylin/rest/security/AclPermissionFactory.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.security;
-
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.springframework.security.acls.domain.DefaultPermissionFactory;
-import org.springframework.security.acls.model.Permission;
-
-/**
- * @author xduo
- * 
- */
-public class AclPermissionFactory extends DefaultPermissionFactory {
-
-    public AclPermissionFactory() {
-        super();
-        registerPublicPermissions(AclPermission.class);
-    }
-
-    public static List<Permission> getPermissions() {
-        List<Permission> permissions = new ArrayList<Permission>();
-        Field[] fields = AclPermission.class.getFields();
-
-        for (Field field : fields) {
-            try {
-                Object fieldValue = field.get(null);
-
-                if (Permission.class.isAssignableFrom(fieldValue.getClass())) {
-                    // Found a Permission static field
-                    permissions.add((Permission) fieldValue);
-                }
-            } catch (Exception ignore) {
-                //ignore on purpose
-            }
-        }
-
-        return permissions;
-    }
-
-    public static Permission getPermission(String perName) {
-        Field[] fields = AclPermission.class.getFields();
-
-        for (Field field : fields) {
-            try {
-                Object fieldValue = field.get(null);
-
-                if (Permission.class.isAssignableFrom(fieldValue.getClass())) {
-                    // Found a Permission static field
-                    if (perName.equals(field.getName())) {
-                        return (Permission) fieldValue;
-                    }
-                }
-            } catch (Exception ignore) {
-                //ignore on purpose
-            }
-        }
-
-        return null;
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/security/AuthoritiesPopulator.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/AuthoritiesPopulator.java b/server/src/main/java/org/apache/kylin/rest/security/AuthoritiesPopulator.java
deleted file mode 100644
index 7983fc0..0000000
--- a/server/src/main/java/org/apache/kylin/rest/security/AuthoritiesPopulator.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.security;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import org.apache.kylin.rest.constant.Constant;
-import org.springframework.ldap.core.ContextSource;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.SimpleGrantedAuthority;
-import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
-
-/**
- * @author xduo
- * 
- */
-public class AuthoritiesPopulator extends DefaultLdapAuthoritiesPopulator {
-
-    String adminRole;
-    SimpleGrantedAuthority adminRoleAsAuthority;
-
-    SimpleGrantedAuthority adminAuthority = new SimpleGrantedAuthority(Constant.ROLE_ADMIN);
-    SimpleGrantedAuthority modelerAuthority = new SimpleGrantedAuthority(Constant.ROLE_MODELER);
-    SimpleGrantedAuthority analystAuthority = new SimpleGrantedAuthority(Constant.ROLE_ANALYST);
-
-    Set<GrantedAuthority> defaultAuthorities = new HashSet<GrantedAuthority>();
-
-    /**
-     * @param contextSource
-     * @param groupSearchBase
-     */
-    public AuthoritiesPopulator(ContextSource contextSource, String groupSearchBase, String adminRole, String defaultRole) {
-        super(contextSource, groupSearchBase);
-        this.adminRole = adminRole;
-        this.adminRoleAsAuthority = new SimpleGrantedAuthority(adminRole);
-
-        if (defaultRole.contains(Constant.ROLE_MODELER))
-            this.defaultAuthorities.add(modelerAuthority);
-        if (defaultRole.contains(Constant.ROLE_ANALYST))
-            this.defaultAuthorities.add(analystAuthority);
-    }
-
-    @Override
-    public Set<GrantedAuthority> getGroupMembershipRoles(String userDn, String username) {
-        Set<GrantedAuthority> authorities = super.getGroupMembershipRoles(userDn, username);
-
-        if (authorities.contains(adminRoleAsAuthority)) {
-            authorities.add(adminAuthority);
-            authorities.add(modelerAuthority);
-            authorities.add(analystAuthority);
-        }
-
-        authorities.addAll(defaultAuthorities);
-
-        return authorities;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/security/CrossDomainFilter.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/CrossDomainFilter.java b/server/src/main/java/org/apache/kylin/rest/security/CrossDomainFilter.java
deleted file mode 100644
index 7d9d9ac..0000000
--- a/server/src/main/java/org/apache/kylin/rest/security/CrossDomainFilter.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.security;
-
-import java.io.IOException;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.kylin.common.KylinConfig;
-
-/**
- * @author xduo
- * 
- */
-public class CrossDomainFilter implements Filter {
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
-     */
-    @Override
-    public void init(FilterConfig filterConfig) throws ServletException {
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
-     * javax.servlet.ServletResponse, javax.servlet.FilterChain)
-     */
-    @Override
-    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
-        if (KylinConfig.getInstanceFromEnv().isWebCrossDomainEnabled()) {
-            ((HttpServletResponse) response).addHeader("Access-Control-Allow-Origin", "*");
-            ((HttpServletResponse) response).addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
-            ((HttpServletResponse) response).addHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With, Accept, Authorization");
-        }
-
-        chain.doFilter(request, response);
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see javax.servlet.Filter#destroy()
-     */
-    @Override
-    public void destroy() {
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/security/KylinAuthenticationProvider.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/KylinAuthenticationProvider.java b/server/src/main/java/org/apache/kylin/rest/security/KylinAuthenticationProvider.java
deleted file mode 100644
index d0dd06a..0000000
--- a/server/src/main/java/org/apache/kylin/rest/security/KylinAuthenticationProvider.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.security;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Arrays;
-
-import org.apache.kylin.rest.service.UserService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.authentication.AuthenticationProvider;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.userdetails.User;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.util.Assert;
-
-import net.sf.ehcache.Cache;
-import net.sf.ehcache.CacheManager;
-import net.sf.ehcache.Element;
-
-/**
- * A wrapper class for the authentication provider; Will do something more for Kylin.
- */
-public class KylinAuthenticationProvider implements AuthenticationProvider {
-
-    private static final Logger logger = LoggerFactory.getLogger(KylinAuthenticationProvider.class);
-
-    @Autowired
-    UserService userService;
-
-    @Autowired
-    private CacheManager cacheManager;
-
-    //Embedded authentication provider
-    private AuthenticationProvider authenticationProvider;
-
-    MessageDigest md = null;
-
-    public KylinAuthenticationProvider(AuthenticationProvider authenticationProvider) {
-        super();
-        Assert.notNull(authenticationProvider, "The embedded authenticationProvider should not be null.");
-        this.authenticationProvider = authenticationProvider;
-        try {
-            md = MessageDigest.getInstance("MD5");
-        } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException("Failed to init Message Digest ", e);
-        }
-    }
-
-    @Override
-    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
-        Authentication authed = null;
-        Cache userCache = cacheManager.getCache("UserCache");
-        md.reset();
-        byte[] hashKey = md.digest((authentication.getName() + authentication.getCredentials()).getBytes());
-        String userKey = Arrays.toString(hashKey);
-
-        Element authedUser = userCache.get(userKey);
-        if (null != authedUser) {
-            authed = (Authentication) authedUser.getObjectValue();
-            SecurityContextHolder.getContext().setAuthentication(authed);
-        } else {
-            try {
-                authed = authenticationProvider.authenticate(authentication);
-                userCache.put(new Element(userKey, authed));
-            } catch (AuthenticationException e) {
-                logger.error("Failed to auth user: " + authentication.getName(), e);
-                throw e;
-            }
-
-            logger.debug("Authenticated user " + authed.toString());
-
-            UserDetails user;
-
-            if (authed.getDetails() == null) {
-                //authed.setAuthenticated(false);
-                throw new UsernameNotFoundException("User not found in LDAP, check whether he/she has been added to the groups.");
-            }
-
-            if (authed.getDetails() instanceof UserDetails) {
-                user = (UserDetails) authed.getDetails();
-            } else {
-                user = new User(authentication.getName(), "skippped-ldap", authed.getAuthorities());
-            }
-            Assert.notNull(user, "The UserDetail is null.");
-
-            logger.debug("User authorities :" + user.getAuthorities());
-            if (!userService.userExists(user.getUsername())) {
-                userService.createUser(user);
-            } else {
-                userService.updateUser(user);
-            }
-        }
-
-        return authed;
-    }
-
-    @Override
-    public boolean supports(Class<?> authentication) {
-        return authenticationProvider.supports(authentication);
-    }
-
-    public AuthenticationProvider getAuthenticationProvider() {
-        return authenticationProvider;
-    }
-
-    public void setAuthenticationProvider(AuthenticationProvider authenticationProvider) {
-        this.authenticationProvider = authenticationProvider;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/security/LdapProvider.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/LdapProvider.java b/server/src/main/java/org/apache/kylin/rest/security/LdapProvider.java
deleted file mode 100644
index 2c5fe50..0000000
--- a/server/src/main/java/org/apache/kylin/rest/security/LdapProvider.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.security;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Arrays;
-
-import org.apache.kylin.rest.service.UserService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.userdetails.User;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
-import org.springframework.security.ldap.authentication.LdapAuthenticator;
-import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
-
-import net.sf.ehcache.Cache;
-import net.sf.ehcache.CacheManager;
-import net.sf.ehcache.Element;
-
-/**
- * @author xduo
- * @deprecated replaced by KylinAuthenticationProvider
- * 
- */
-public class LdapProvider extends LdapAuthenticationProvider {
-
-    private static final Logger logger = LoggerFactory.getLogger(LdapProvider.class);
-
-    @Autowired
-    UserService userService;
-
-    @Autowired
-    private CacheManager cacheManager;
-
-    MessageDigest md = null;
-
-    /**
-     * @param authenticator
-     * @param authoritiesPopulator
-     */
-    public LdapProvider(LdapAuthenticator authenticator, LdapAuthoritiesPopulator authoritiesPopulator) {
-        super(authenticator, authoritiesPopulator);
-
-        try {
-            md = MessageDigest.getInstance("MD5");
-        } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException("Failed to init Message Digest ", e);
-        }
-    }
-
-    @Override
-    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
-        Authentication authed = null;
-        Cache userCache = cacheManager.getCache("UserCache");
-        md.reset();
-        byte[] hashKey = md.digest((authentication.getName() + authentication.getCredentials()).getBytes());
-        String userKey = Arrays.toString(hashKey);
-
-        Element authedUser = userCache.get(userKey);
-        if (null != authedUser) {
-            authed = (Authentication) authedUser.getObjectValue();
-            SecurityContextHolder.getContext().setAuthentication(authed);
-        } else {
-            try {
-                authed = super.authenticate(authentication);
-                userCache.put(new Element(userKey, authed));
-            } catch (AuthenticationException e) {
-                logger.error("Failed to auth user: " + authentication.getName(), e);
-                throw e;
-            }
-
-            UserDetails user = new User(authentication.getName(), "skippped-ldap", authed.getAuthorities());
-
-            if (!userService.userExists(authentication.getName())) {
-                userService.createUser(user);
-            } else {
-                userService.updateUser(user);
-            }
-        }
-
-        return authed;
-    }
-}


[06/13] kylin git commit: KYLIN-1823 split code from kylin-server into kylin-server-base

Posted by li...@apache.org.
http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/controller/AdminController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/AdminController.java b/server/src/main/java/org/apache/kylin/rest/controller/AdminController.java
deleted file mode 100644
index de3c4b4..0000000
--- a/server/src/main/java/org/apache/kylin/rest/controller/AdminController.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.controller;
-
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.rest.request.MetricsRequest;
-import org.apache.kylin.rest.request.UpdateConfigRequest;
-import org.apache.kylin.rest.response.GeneralResponse;
-import org.apache.kylin.rest.response.MetricsResponse;
-import org.apache.kylin.rest.service.AdminService;
-import org.apache.kylin.rest.service.CubeService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-/**
- * Admin Controller is defined as Restful API entrance for UI.
- * 
- * @author jianliu
- * 
- */
-@Controller
-@RequestMapping(value = "/admin")
-public class AdminController extends BasicController {
-
-    @Autowired
-    private AdminService adminService;
-    @Autowired
-    private CubeService cubeMgmtService;
-
-    @RequestMapping(value = "/env", method = { RequestMethod.GET })
-    @ResponseBody
-    public GeneralResponse getEnv() {
-        String env = adminService.getEnv();
-
-        GeneralResponse envRes = new GeneralResponse();
-        envRes.put("env", env);
-
-        return envRes;
-    }
-
-    @RequestMapping(value = "/config", method = { RequestMethod.GET })
-    @ResponseBody
-    public GeneralResponse getConfig() {
-        String config = adminService.getConfigAsString();
-
-        GeneralResponse configRes = new GeneralResponse();
-        configRes.put("config", config);
-
-        return configRes;
-    }
-
-    @RequestMapping(value = "/metrics/cubes", method = { RequestMethod.GET })
-    @ResponseBody
-    public MetricsResponse cubeMetrics(MetricsRequest request) {
-        return cubeMgmtService.calculateMetrics(request);
-    }
-
-    @RequestMapping(value = "/storage", method = { RequestMethod.DELETE })
-    @ResponseBody
-    public void cleanupStorage() {
-        adminService.cleanupStorage();
-    }
-
-    @RequestMapping(value = "/config", method = { RequestMethod.PUT })
-    public void updateKylinConfig(@RequestBody UpdateConfigRequest updateConfigRequest) {
-        KylinConfig.getInstanceFromEnv().setProperty(updateConfigRequest.getKey(), updateConfigRequest.getValue());
-    }
-
-    public void setAdminService(AdminService adminService) {
-        this.adminService = adminService;
-    }
-
-    public void setCubeMgmtService(CubeService cubeMgmtService) {
-        this.cubeMgmtService = cubeMgmtService;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/controller/BasicController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/BasicController.java b/server/src/main/java/org/apache/kylin/rest/controller/BasicController.java
deleted file mode 100644
index 0e4a70c..0000000
--- a/server/src/main/java/org/apache/kylin/rest/controller/BasicController.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.controller;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.kylin.rest.exception.BadRequestException;
-import org.apache.kylin.rest.exception.ForbiddenException;
-import org.apache.kylin.rest.exception.NotFoundException;
-import org.apache.kylin.rest.response.ErrorResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.bind.annotation.ResponseStatus;
-
-/**
- */
-public class BasicController {
-
-    private static final Logger logger = LoggerFactory.getLogger(BasicController.class);
-
-    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
-    @ExceptionHandler(Exception.class)
-    @ResponseBody
-    ErrorResponse handleError(HttpServletRequest req, Exception ex) {
-        logger.error("", ex);
-        return new ErrorResponse(req.getRequestURL().toString(), ex);
-    }
-
-    @ResponseStatus(HttpStatus.FORBIDDEN)
-    @ExceptionHandler(ForbiddenException.class)
-    @ResponseBody
-    ErrorResponse handleForbidden(HttpServletRequest req, Exception ex) {
-        return new ErrorResponse(req.getRequestURL().toString(), ex);
-    }
-
-    @ResponseStatus(HttpStatus.NOT_FOUND)
-    @ExceptionHandler(NotFoundException.class)
-    @ResponseBody
-    ErrorResponse handleNotFound(HttpServletRequest req, Exception ex) {
-        return new ErrorResponse(req.getRequestURL().toString(), ex);
-    }
-
-    @ResponseStatus(HttpStatus.BAD_REQUEST)
-    @ExceptionHandler(BadRequestException.class)
-    @ResponseBody
-    ErrorResponse handleBadRequest(HttpServletRequest req, Exception ex) {
-        logger.error("", ex);
-        return new ErrorResponse(req.getRequestURL().toString(), ex);
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/controller/CacheController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/CacheController.java b/server/src/main/java/org/apache/kylin/rest/controller/CacheController.java
deleted file mode 100644
index 845ffe0..0000000
--- a/server/src/main/java/org/apache/kylin/rest/controller/CacheController.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.controller;
-
-import java.io.IOException;
-
-import org.apache.kylin.common.restclient.Broadcaster;
-import org.apache.kylin.common.restclient.Broadcaster.EVENT;
-import org.apache.kylin.rest.service.CacheService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-/**
- * CubeController is defined as Restful API entrance for UI.
- *
- * @author jianliu
- */
-@Controller
-@RequestMapping(value = "/cache")
-public class CacheController extends BasicController {
-    private static final Logger logger = LoggerFactory.getLogger(CacheController.class);
-
-    @Autowired
-    private CacheService cacheService;
-
-    /**
-     * Wipe system cache
-     *
-     * @param type  {@link Broadcaster.TYPE}
-     * @param event {@link Broadcaster.EVENT}
-     * @param name
-     * @return if the action success
-     * @throws IOException
-     */
-    @RequestMapping(value = "/{type}/{name}/{event}", method = { RequestMethod.PUT })
-    @ResponseBody
-    public void wipeCache(@PathVariable String type, @PathVariable String event, @PathVariable String name) throws IOException {
-
-        Broadcaster.TYPE wipeType = Broadcaster.TYPE.getType(type);
-        EVENT wipeEvent = Broadcaster.EVENT.getEvent(event);
-
-        logger.info("wipe cache type: " + wipeType + " event:" + wipeEvent + " name:" + name);
-
-        switch (wipeEvent) {
-        case CREATE:
-        case UPDATE:
-            cacheService.rebuildCache(wipeType, name);
-            break;
-        case DROP:
-            cacheService.removeCache(wipeType, name);
-            break;
-        default:
-            throw new RuntimeException("invalid type:" + wipeEvent);
-        }
-    }
-
-    public void setCacheService(CacheService cacheService) {
-        this.cacheService = cacheService;
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java b/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
deleted file mode 100644
index 9315a20..0000000
--- a/server/src/main/java/org/apache/kylin/rest/controller/CubeController.java
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.controller;
-
-import java.io.IOException;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.kylin.common.util.JsonUtil;
-import org.apache.kylin.cube.CubeInstance;
-import org.apache.kylin.cube.CubeSegment;
-import org.apache.kylin.cube.model.CubeBuildTypeEnum;
-import org.apache.kylin.cube.model.CubeDesc;
-import org.apache.kylin.cube.model.CubeJoinedFlatTableDesc;
-import org.apache.kylin.dimension.DimensionEncodingFactory;
-import org.apache.kylin.engine.streaming.StreamingConfig;
-import org.apache.kylin.job.JobInstance;
-import org.apache.kylin.job.JoinedFlatTable;
-import org.apache.kylin.metadata.model.SegmentStatusEnum;
-import org.apache.kylin.metadata.project.ProjectInstance;
-import org.apache.kylin.rest.exception.BadRequestException;
-import org.apache.kylin.rest.exception.ForbiddenException;
-import org.apache.kylin.rest.exception.InternalErrorException;
-import org.apache.kylin.rest.exception.NotFoundException;
-import org.apache.kylin.rest.request.CubeRequest;
-import org.apache.kylin.rest.request.JobBuildRequest;
-import org.apache.kylin.rest.request.JobBuildRequest2;
-import org.apache.kylin.rest.response.GeneralResponse;
-import org.apache.kylin.rest.response.HBaseResponse;
-import org.apache.kylin.rest.service.CubeService;
-import org.apache.kylin.rest.service.JobService;
-import org.apache.kylin.rest.service.KafkaConfigService;
-import org.apache.kylin.rest.service.StreamingService;
-import org.apache.kylin.source.kafka.config.KafkaConfig;
-import org.apache.kylin.storage.hbase.cube.v1.coprocessor.observer.ObserverEnabler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.AccessDeniedException;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-
-import com.google.common.collect.Sets;
-
-/**
- * CubeController is defined as Restful API entrance for UI.
- */
-@Controller
-@RequestMapping(value = "/cubes")
-public class CubeController extends BasicController {
-    private static final Logger logger = LoggerFactory.getLogger(CubeController.class);
-
-    @Autowired
-    private StreamingService streamingService;
-
-    @Autowired
-    private KafkaConfigService kafkaConfigService;
-
-    @Autowired
-    private CubeService cubeService;
-
-    @Autowired
-    private JobService jobService;
-
-    @RequestMapping(value = "", method = { RequestMethod.GET })
-    @ResponseBody
-    public List<CubeInstance> getCubes(@RequestParam(value = "cubeName", required = false) String cubeName, @RequestParam(value = "modelName", required = false) String modelName, @RequestParam(value = "projectName", required = false) String projectName, @RequestParam(value = "limit", required = false) Integer limit, @RequestParam(value = "offset", required = false) Integer offset) {
-        return cubeService.getCubes(cubeName, projectName, modelName, limit, offset);
-    }
-
-    @RequestMapping(value = "validEncodings", method = { RequestMethod.GET })
-    @ResponseBody
-    public Set<String> getValidEncodings() {
-        Set<String> encodings;
-        try {
-            encodings = DimensionEncodingFactory.getValidEncodings();
-        } catch (Exception e) {
-            return Sets.newTreeSet();
-        }
-        return encodings;
-    }
-
-    @RequestMapping(value = "/{cubeName}", method = { RequestMethod.GET })
-    @ResponseBody
-    public CubeInstance getCube(@PathVariable String cubeName) {
-        CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
-        if (cube == null) {
-            throw new InternalErrorException("Cannot find cube " + cubeName);
-        }
-        return cube;
-    }
-
-    /**
-     * Get hive SQL of the cube
-     *
-     * @param cubeName Cube Name
-     * @return
-     * @throws UnknownHostException
-     * @throws IOException
-     */
-    @RequestMapping(value = "/{cubeName}/segs/{segmentName}/sql", method = { RequestMethod.GET })
-    @ResponseBody
-    public GeneralResponse getSql(@PathVariable String cubeName, @PathVariable String segmentName) {
-        CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
-        CubeDesc cubeDesc = cube.getDescriptor();
-        CubeSegment cubeSegment = cube.getSegment(segmentName, SegmentStatusEnum.READY);
-        CubeJoinedFlatTableDesc flatTableDesc = new CubeJoinedFlatTableDesc(cubeDesc, cubeSegment);
-        String sql = JoinedFlatTable.generateSelectDataStatement(flatTableDesc);
-
-        GeneralResponse repsonse = new GeneralResponse();
-        repsonse.setProperty("sql", sql);
-
-        return repsonse;
-    }
-
-    /**
-     * Update cube notify list
-     *
-     * @param cubeName
-     * @param notifyList
-     * @throws IOException
-     */
-    @RequestMapping(value = "/{cubeName}/notify_list", method = { RequestMethod.PUT })
-    @ResponseBody
-    public void updateNotifyList(@PathVariable String cubeName, @RequestBody List<String> notifyList) {
-        CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
-
-        if (cube == null) {
-            throw new InternalErrorException("Cannot find cube " + cubeName);
-        }
-
-        try {
-            cubeService.updateCubeNotifyList(cube, notifyList);
-        } catch (Exception e) {
-            logger.error(e.getLocalizedMessage(), e);
-            throw new InternalErrorException(e.getLocalizedMessage());
-        }
-
-    }
-
-    @RequestMapping(value = "/{cubeName}/cost", method = { RequestMethod.PUT })
-    @ResponseBody
-    public CubeInstance updateCubeCost(@PathVariable String cubeName, @RequestParam(value = "cost") int cost) {
-        try {
-            return cubeService.updateCubeCost(cubeName, cost);
-        } catch (Exception e) {
-            String message = "Failed to update cube cost: " + cubeName + " : " + cost;
-            logger.error(message, e);
-            throw new InternalErrorException(message + " Caused by: " + e.getMessage(), e);
-        }
-    }
-
-    @RequestMapping(value = "/{cubeName}/coprocessor", method = { RequestMethod.PUT })
-    @ResponseBody
-    public Map<String, Boolean> updateCubeCoprocessor(@PathVariable String cubeName, @RequestParam(value = "force") String force) {
-        try {
-            ObserverEnabler.updateCubeOverride(cubeName, force);
-            return ObserverEnabler.getCubeOverrides();
-        } catch (Exception e) {
-            String message = "Failed to update cube coprocessor: " + cubeName + " : " + force;
-            logger.error(message, e);
-            throw new InternalErrorException(message + " Caused by: " + e.getMessage(), e);
-        }
-    }
-
-    /**
-     * Force rebuild a cube's lookup table snapshot
-     *
-     * @throws IOException
-     */
-    @RequestMapping(value = "/{cubeName}/segs/{segmentName}/refresh_lookup", method = { RequestMethod.PUT })
-    @ResponseBody
-    public CubeInstance rebuildLookupSnapshot(@PathVariable String cubeName, @PathVariable String segmentName, @RequestParam(value = "lookupTable") String lookupTable) {
-        try {
-            return cubeService.rebuildLookupSnapshot(cubeName, segmentName, lookupTable);
-        } catch (IOException e) {
-            logger.error(e.getLocalizedMessage(), e);
-            throw new InternalErrorException(e.getLocalizedMessage());
-        }
-    }
-
-    /**
-     * Delete a cube segment
-     *
-     * @throws IOException
-     */
-    @RequestMapping(value = "/{cubeName}/segs/{segmentName}", method = { RequestMethod.DELETE })
-    @ResponseBody
-    public CubeInstance deleteSegment(@PathVariable String cubeName, @PathVariable String segmentName) {
-        CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
-
-        if (cube == null) {
-            throw new InternalErrorException("Cannot find cube " + cubeName);
-        }
-
-        CubeSegment segment = cube.getSegment(segmentName, null);
-        if (segment == null) {
-            throw new InternalErrorException("Cannot find segment '" + segmentName + "'");
-        }
-
-        try {
-            return cubeService.deleteSegment(cube, segmentName);
-        } catch (Exception e) {
-            logger.error(e.getLocalizedMessage(), e);
-            throw new InternalErrorException(e.getLocalizedMessage());
-        }
-    }
-
-    /** Build/Rebuild a cube segment */
-    @RequestMapping(value = "/{cubeName}/build", method = { RequestMethod.PUT })
-    @ResponseBody
-    public JobInstance build(@PathVariable String cubeName, @RequestBody JobBuildRequest req) {
-        return rebuild(cubeName, req);
-    }
-
-    /** Build/Rebuild a cube segment */
-    @RequestMapping(value = "/{cubeName}/rebuild", method = { RequestMethod.PUT })
-    @ResponseBody
-    public JobInstance rebuild(@PathVariable String cubeName, @RequestBody JobBuildRequest req) {
-        return buildInternal(cubeName, req.getStartTime(), req.getEndTime(), 0, 0, req.getBuildType(), req.isForce() || req.isForceMergeEmptySegment());
-    }
-
-    /** Build/Rebuild a cube segment by source offset */
-    @RequestMapping(value = "/{cubeName}/build2", method = { RequestMethod.PUT })
-    @ResponseBody
-    public JobInstance build(@PathVariable String cubeName, @RequestBody JobBuildRequest2 req) {
-        return rebuild(cubeName, req);
-    }
-
-    /** Build/Rebuild a cube segment by source offset */
-    @RequestMapping(value = "/{cubeName}/rebuild2", method = { RequestMethod.PUT })
-    @ResponseBody
-    public JobInstance rebuild(@PathVariable String cubeName, @RequestBody JobBuildRequest2 req) {
-        return buildInternal(cubeName, 0, 0, req.getStartSourceOffset(), req.getEndSourceOffset(), req.getBuildType(), req.isForce());
-    }
-
-    private JobInstance buildInternal(String cubeName, long startTime, long endTime, //
-            long startOffset, long endOffset, String buildType, boolean force) {
-        try {
-            String submitter = SecurityContextHolder.getContext().getAuthentication().getName();
-            CubeInstance cube = jobService.getCubeManager().getCube(cubeName);
-            return jobService.submitJob(cube, startTime, endTime, startOffset, endOffset, //
-                    CubeBuildTypeEnum.valueOf(buildType), force, submitter);
-        } catch (Exception e) {
-            logger.error(e.getLocalizedMessage(), e);
-            throw new InternalErrorException(e.getLocalizedMessage());
-        }
-    }
-
-    @RequestMapping(value = "/{cubeName}/disable", method = { RequestMethod.PUT })
-    @ResponseBody
-    public CubeInstance disableCube(@PathVariable String cubeName) {
-        try {
-            CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
-
-            if (cube == null) {
-                throw new InternalErrorException("Cannot find cube " + cubeName);
-            }
-
-            return cubeService.disableCube(cube);
-        } catch (Exception e) {
-            String message = "Failed to disable cube: " + cubeName;
-            logger.error(message, e);
-            throw new InternalErrorException(message + " Caused by: " + e.getMessage(), e);
-        }
-    }
-
-    @RequestMapping(value = "/{cubeName}/purge", method = { RequestMethod.PUT })
-    @ResponseBody
-    public CubeInstance purgeCube(@PathVariable String cubeName) {
-        try {
-            CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
-
-            if (cube == null) {
-                throw new InternalErrorException("Cannot find cube " + cubeName);
-            }
-
-            return cubeService.purgeCube(cube);
-        } catch (Exception e) {
-            String message = "Failed to purge cube: " + cubeName;
-            logger.error(message, e);
-            throw new InternalErrorException(message + " Caused by: " + e.getMessage(), e);
-        }
-    }
-
-    @RequestMapping(value = "/{cubeName}/clone", method = { RequestMethod.PUT })
-    @ResponseBody
-    public CubeInstance cloneCube(@PathVariable String cubeName, @RequestBody CubeRequest cubeRequest) {
-        String newCubeName = cubeRequest.getCubeName();
-        String project = cubeRequest.getProject();
-
-        CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
-        if (cube == null) {
-            throw new InternalErrorException("Cannot find cube " + cubeName);
-        }
-        CubeDesc cubeDesc = cube.getDescriptor();
-        CubeDesc newCubeDesc = CubeDesc.getCopyOf(cubeDesc);
-        newCubeDesc.setName(newCubeName);
-
-        CubeInstance newCube;
-        try {
-            newCube = cubeService.createCubeAndDesc(newCubeName, project, newCubeDesc);
-
-            //reload to avoid shallow clone
-            cubeService.getCubeDescManager().reloadCubeDescLocal(newCubeName);
-        } catch (IOException e) {
-            throw new InternalErrorException("Failed to clone cube ", e);
-        }
-
-        return newCube;
-
-    }
-
-    @RequestMapping(value = "/{cubeName}/enable", method = { RequestMethod.PUT })
-    @ResponseBody
-    public CubeInstance enableCube(@PathVariable String cubeName) {
-        try {
-            CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
-            if (null == cube) {
-                throw new InternalErrorException("Cannot find cube " + cubeName);
-            }
-
-            return cubeService.enableCube(cube);
-        } catch (Exception e) {
-            String message = "Failed to enable cube: " + cubeName;
-            logger.error(message, e);
-            throw new InternalErrorException(message + " Caused by: " + e.getMessage(), e);
-        }
-    }
-
-    @RequestMapping(value = "/{cubeName}", method = { RequestMethod.DELETE })
-    @ResponseBody
-    public void deleteCube(@PathVariable String cubeName) {
-        CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
-        if (null == cube) {
-            throw new NotFoundException("Cube with name " + cubeName + " not found..");
-        }
-
-        //drop Cube
-        try {
-            cubeService.deleteCube(cube);
-        } catch (Exception e) {
-            logger.error(e.getLocalizedMessage(), e);
-            throw new InternalErrorException("Failed to delete cube. " + " Caused by: " + e.getMessage(), e);
-        }
-
-    }
-
-    /**
-     * save cubeDesc
-     *
-     * @return Table metadata array
-     * @throws IOException
-     */
-    @RequestMapping(value = "", method = { RequestMethod.POST })
-    @ResponseBody
-    public CubeRequest saveCubeDesc(@RequestBody CubeRequest cubeRequest) {
-
-        CubeDesc desc = deserializeCubeDesc(cubeRequest);
-        if (desc == null) {
-            cubeRequest.setMessage("CubeDesc is null.");
-            return cubeRequest;
-        }
-        String name = CubeService.getCubeNameFromDesc(desc.getName());
-        if (StringUtils.isEmpty(name)) {
-            logger.info("Cube name should not be empty.");
-            throw new BadRequestException("Cube name should not be empty.");
-        }
-
-        try {
-            desc.setUuid(UUID.randomUUID().toString());
-            String projectName = (null == cubeRequest.getProject()) ? ProjectInstance.DEFAULT_PROJECT_NAME : cubeRequest.getProject();
-            cubeService.createCubeAndDesc(name, projectName, desc);
-        } catch (Exception e) {
-            logger.error("Failed to deal with the request.", e);
-            throw new InternalErrorException(e.getLocalizedMessage(), e);
-        }
-
-        cubeRequest.setUuid(desc.getUuid());
-        cubeRequest.setSuccessful(true);
-        return cubeRequest;
-    }
-
-    /**
-     * update CubDesc
-     *
-     * @return Table metadata array
-     * @throws JsonProcessingException
-     * @throws IOException
-     */
-    @RequestMapping(value = "", method = { RequestMethod.PUT })
-    @ResponseBody
-    public CubeRequest updateCubeDesc(@RequestBody CubeRequest cubeRequest) throws JsonProcessingException {
-
-        //update cube
-        CubeDesc desc = deserializeCubeDesc(cubeRequest);
-        CubeDesc oldCubeDesc;
-        boolean isCubeDescFreeEditable;
-
-        if (desc == null) {
-            return cubeRequest;
-        }
-
-        // Check if the cube is editable
-        isCubeDescFreeEditable = cubeService.isCubeDescFreeEditable(desc);
-
-        String projectName = (null == cubeRequest.getProject()) ? ProjectInstance.DEFAULT_PROJECT_NAME : cubeRequest.getProject();
-        try {
-            CubeInstance cube = cubeService.getCubeManager().getCube(cubeRequest.getCubeName());
-
-            if (cube == null) {
-                String error = "The cube named " + cubeRequest.getCubeName() + " does not exist ";
-                updateRequest(cubeRequest, false, error);
-                return cubeRequest;
-            }
-
-            //cube renaming is not allowed
-            if (!cube.getDescriptor().getName().equalsIgnoreCase(desc.getName())) {
-                String error = "Cube Desc renaming is not allowed: desc.getName(): " + desc.getName() + ", cubeRequest.getCubeName(): " + cubeRequest.getCubeName();
-                updateRequest(cubeRequest, false, error);
-                return cubeRequest;
-            }
-
-            oldCubeDesc = cube.getDescriptor();
-            if (isCubeDescFreeEditable || oldCubeDesc.consistentWith(desc)) {
-                desc = cubeService.updateCubeAndDesc(cube, desc, projectName, true);
-            } else {
-                logger.warn("Won't update the cube desc due to inconsistency");
-                updateRequest(cubeRequest, false, "CubeDesc " + desc.getName() + " is inconsistent with existing. Try purge that cube first or avoid updating key cube desc fields.");
-                return cubeRequest;
-            }
-        } catch (AccessDeniedException accessDeniedException) {
-            throw new ForbiddenException("You don't have right to update this cube.");
-        } catch (Exception e) {
-            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
-            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
-        }
-
-        if (!desc.getError().isEmpty()) {
-            logger.warn("Cube " + desc.getName() + " fail to update because " + desc.getError());
-            updateRequest(cubeRequest, false, omitMessage(desc.getError()));
-            return cubeRequest;
-        }
-
-        String descData = JsonUtil.writeValueAsIndentString(desc);
-        cubeRequest.setCubeDescData(descData);
-        cubeRequest.setSuccessful(true);
-        return cubeRequest;
-    }
-
-    /**
-     * get Hbase Info
-     *
-     * @return true
-     * @throws IOException
-     */
-    @RequestMapping(value = "/{cubeName}/hbase", method = { RequestMethod.GET })
-    @ResponseBody
-    public List<HBaseResponse> getHBaseInfo(@PathVariable String cubeName) {
-        List<HBaseResponse> hbase = new ArrayList<HBaseResponse>();
-
-        CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
-        if (null == cube) {
-            throw new InternalErrorException("Cannot find cube " + cubeName);
-        }
-
-        List<CubeSegment> segments = cube.getSegments();
-
-        for (CubeSegment segment : segments) {
-            String tableName = segment.getStorageLocationIdentifier();
-            HBaseResponse hr = null;
-
-            // Get info of given table.
-            try {
-                hr = cubeService.getHTableInfo(tableName);
-            } catch (IOException e) {
-                logger.error("Failed to calcuate size of HTable \"" + tableName + "\".", e);
-            }
-
-            if (null == hr) {
-                logger.info("Failed to calcuate size of HTable \"" + tableName + "\".");
-                hr = new HBaseResponse();
-            }
-
-            hr.setTableName(tableName);
-            hr.setDateRangeStart(segment.getDateRangeStart());
-            hr.setDateRangeEnd(segment.getDateRangeEnd());
-            hbase.add(hr);
-        }
-
-        return hbase;
-    }
-
-    private CubeDesc deserializeCubeDesc(CubeRequest cubeRequest) {
-        CubeDesc desc = null;
-        try {
-            logger.debug("Saving cube " + cubeRequest.getCubeDescData());
-            desc = JsonUtil.readValue(cubeRequest.getCubeDescData(), CubeDesc.class);
-        } catch (JsonParseException e) {
-            logger.error("The cube definition is not valid.", e);
-            updateRequest(cubeRequest, false, e.getMessage());
-        } catch (JsonMappingException e) {
-            logger.error("The cube definition is not valid.", e);
-            updateRequest(cubeRequest, false, e.getMessage());
-        } catch (IOException e) {
-            logger.error("Failed to deal with the request.", e);
-            throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
-        }
-        return desc;
-    }
-
-    private StreamingConfig deserializeStreamingDesc(CubeRequest cubeRequest) {
-        StreamingConfig desc = null;
-        try {
-            logger.debug("Saving StreamingConfig " + cubeRequest.getStreamingData());
-            desc = JsonUtil.readValue(cubeRequest.getStreamingData(), StreamingConfig.class);
-        } catch (JsonParseException e) {
-            logger.error("The StreamingConfig definition is not valid.", e);
-            updateRequest(cubeRequest, false, e.getMessage());
-        } catch (JsonMappingException e) {
-            logger.error("The data StreamingConfig definition is not valid.", e);
-            updateRequest(cubeRequest, false, e.getMessage());
-        } catch (IOException e) {
-            logger.error("Failed to deal with the request.", e);
-            throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
-        }
-        return desc;
-    }
-
-    private KafkaConfig deserializeKafkaDesc(CubeRequest cubeRequest) {
-        KafkaConfig desc = null;
-        try {
-            logger.debug("Saving KafkaConfig " + cubeRequest.getKafkaData());
-            desc = JsonUtil.readValue(cubeRequest.getKafkaData(), KafkaConfig.class);
-        } catch (JsonParseException e) {
-            logger.error("The KafkaConfig definition is not valid.", e);
-            updateRequest(cubeRequest, false, e.getMessage());
-        } catch (JsonMappingException e) {
-            logger.error("The data KafkaConfig definition is not valid.", e);
-            updateRequest(cubeRequest, false, e.getMessage());
-        } catch (IOException e) {
-            logger.error("Failed to deal with the request.", e);
-            throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
-        }
-        return desc;
-    }
-
-    /**
-     * @return
-     */
-    private String omitMessage(List<String> errors) {
-        StringBuffer buffer = new StringBuffer();
-        for (Iterator<String> iterator = errors.iterator(); iterator.hasNext();) {
-            String string = (String) iterator.next();
-            buffer.append(string);
-            buffer.append("\n");
-        }
-        return buffer.toString();
-    }
-
-    private void updateRequest(CubeRequest request, boolean success, String message) {
-        request.setCubeDescData("");
-        request.setSuccessful(success);
-        request.setMessage(message);
-    }
-
-    public void setCubeService(CubeService cubeService) {
-        this.cubeService = cubeService;
-    }
-
-    public void setJobService(JobService jobService) {
-        this.jobService = jobService;
-    }
-
-    public void setStreamingService(StreamingService streamingService) {
-        this.streamingService = streamingService;
-    }
-
-    public void setKafkaConfigService(KafkaConfigService kafkaConfigService) {
-        this.kafkaConfigService = kafkaConfigService;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/controller/CubeDescController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/CubeDescController.java b/server/src/main/java/org/apache/kylin/rest/controller/CubeDescController.java
deleted file mode 100644
index 61584a3..0000000
--- a/server/src/main/java/org/apache/kylin/rest/controller/CubeDescController.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.controller;
-
-import java.io.IOException;
-
-import org.apache.kylin.cube.CubeInstance;
-import org.apache.kylin.cube.model.CubeDesc;
-import org.apache.kylin.rest.service.CubeService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-/**
- * @author xduo
- * 
- */
-@Controller
-@RequestMapping(value = "/cube_desc")
-public class CubeDescController {
-
-    @Autowired
-    private CubeService cubeService;
-
-    /**
-     * Get detail information of the "Cube ID"
-     * 
-     * @param cubeDescName
-     *            Cube ID
-     * @return
-     * @throws IOException
-     */
-    @RequestMapping(value = "/{cubeName}", method = { RequestMethod.GET })
-    @ResponseBody
-    public CubeDesc[] getCube(@PathVariable String cubeName) {
-        CubeInstance cubeInstance = cubeService.getCubeManager().getCube(cubeName);
-        if (cubeInstance == null) {
-            return null;
-        }
-        CubeDesc cSchema = cubeInstance.getDescriptor();
-        if (cSchema != null) {
-            return new CubeDesc[] { cSchema };
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Get detail information of the "Cube ID"
-     * return CubeDesc instead of CubeDesc[]
-     *
-     * @param cubeDescName
-     *            Cube ID
-     * @return
-     * @throws IOException
-     */
-    @RequestMapping(value = "/{cubeName}/desc", method = { RequestMethod.GET })
-    @ResponseBody
-    public CubeDesc getDesc(@PathVariable String cubeName) {
-        CubeInstance cubeInstance = cubeService.getCubeManager().getCube(cubeName);
-        if (cubeInstance == null) {
-            return null;
-        }
-        CubeDesc cSchema = cubeInstance.getDescriptor();
-        if (cSchema != null) {
-            return cSchema;
-        } else {
-            return null;
-        }
-    }
-
-    public void setCubeService(CubeService cubeService) {
-        this.cubeService = cubeService;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/controller/DiagnosisController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/DiagnosisController.java b/server/src/main/java/org/apache/kylin/rest/controller/DiagnosisController.java
deleted file mode 100644
index b9da9b2..0000000
--- a/server/src/main/java/org/apache/kylin/rest/controller/DiagnosisController.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.controller;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.kylin.metadata.badquery.BadQueryEntry;
-import org.apache.kylin.metadata.badquery.BadQueryHistory;
-import org.apache.kylin.rest.exception.InternalErrorException;
-import org.apache.kylin.rest.service.DiagnosisService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-import com.google.common.collect.Lists;
-
-@Controller
-@RequestMapping(value = "/diag")
-public class DiagnosisController {
-
-    private static final Logger logger = LoggerFactory.getLogger(DiagnosisController.class);
-
-    @Autowired
-    private DiagnosisService dgService;
-
-    /**
-     * Get bad query history
-     */
-    @RequestMapping(value = "/{project}/sql", method = { RequestMethod.GET })
-    @ResponseBody
-    public List<BadQueryEntry> getBadQuerySql(@PathVariable String project) {
-
-        List<BadQueryEntry> badEntry = Lists.newArrayList();
-        try {
-            BadQueryHistory badQueryHistory = dgService.getProjectBadQueryHistory(project);
-            badEntry.addAll(badQueryHistory.getEntries());
-        } catch (IOException e) {
-            throw new InternalErrorException(e + " Caused by: " + e.getMessage(), e);
-        }
-
-        return badEntry;
-    }
-
-    /**
-     * Get diagnosis information for project
-     */
-    @RequestMapping(value = "/project/{project}/download", method = { RequestMethod.GET })
-    @ResponseBody
-    public void dumpProjectDiagnosisInfo(@PathVariable String project, final HttpServletRequest request, final HttpServletResponse response) {
-        String filePath;
-        try {
-            filePath = dgService.dumpProjectDiagnosisInfo(project);
-        } catch (IOException e) {
-            throw new InternalErrorException(e + " Caused by: " + e.getMessage(), e);
-        }
-
-        setDownloadResponse(filePath, response);
-    }
-
-    /**
-     * Get diagnosis information for job
-     */
-    @RequestMapping(value = "/job/{jobId}/download", method = { RequestMethod.GET })
-    @ResponseBody
-    public void dumpJobDiagnosisInfo(@PathVariable String jobId, final HttpServletRequest request, final HttpServletResponse response) {
-        String filePath;
-        try {
-            filePath = dgService.dumpJobDiagnosisInfo(jobId);
-        } catch (IOException e) {
-            throw new InternalErrorException(e + " Caused by: " + e.getMessage(), e);
-        }
-
-        setDownloadResponse(filePath, response);
-    }
-
-    private void setDownloadResponse(String downloadFile, final HttpServletResponse response) {
-        File file = new File(downloadFile);
-        try (InputStream fileInputStream = new FileInputStream(file); OutputStream output = response.getOutputStream();) {
-            response.reset();
-            response.setContentType("application/octet-stream");
-            response.setContentLength((int) (file.length()));
-            response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
-            IOUtils.copyLarge(fileInputStream, output);
-            output.flush();
-        } catch (IOException e) {
-            throw new InternalErrorException(e + " Caused by: " + e.getMessage(), e);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/controller/ExternalFilterController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/ExternalFilterController.java b/server/src/main/java/org/apache/kylin/rest/controller/ExternalFilterController.java
deleted file mode 100644
index 7baa639..0000000
--- a/server/src/main/java/org/apache/kylin/rest/controller/ExternalFilterController.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.controller;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import org.apache.kylin.common.util.JsonUtil;
-import org.apache.kylin.metadata.model.ExternalFilterDesc;
-import org.apache.kylin.rest.request.ExternalFilterRequest;
-import org.apache.kylin.rest.service.ExtFilterService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-import com.google.common.collect.Lists;
-
-/**
- * @author jiazhong
- */
-@Controller
-@RequestMapping(value = "/extFilter")
-public class ExternalFilterController extends BasicController {
-    private static final Logger logger = LoggerFactory.getLogger(ExternalFilterController.class);
-
-    @Autowired
-    private ExtFilterService extFilterService;
-
-    @RequestMapping(value = "/saveExtFilter", method = { RequestMethod.POST })
-    @ResponseBody
-    public Map<String, String> saveExternalFilter(@RequestBody ExternalFilterRequest request) throws IOException {
-        Map<String, String> result = new HashMap();
-        String filterProject = request.getProject();
-        ExternalFilterDesc desc = JsonUtil.readValue(request.getExtFilter(), ExternalFilterDesc.class);
-        desc.setUuid(UUID.randomUUID().toString());
-        extFilterService.saveExternalFilter(desc);
-        extFilterService.syncExtFilterToProject(new String[] { desc.getName() }, filterProject);
-        result.put("success", "true");
-        return result;
-    }
-
-    @RequestMapping(value = "/updateExtFilter", method = { RequestMethod.PUT })
-    @ResponseBody
-    public Map<String, String> updateExternalFilter(@RequestBody ExternalFilterRequest request) throws IOException {
-        Map<String, String> result = new HashMap();
-        ExternalFilterDesc desc = JsonUtil.readValue(request.getExtFilter(), ExternalFilterDesc.class);
-        extFilterService.updateExternalFilter(desc);
-        extFilterService.syncExtFilterToProject(new String[] { desc.getName() }, request.getProject());
-        result.put("success", "true");
-        return result;
-    }
-
-    @RequestMapping(value = "/{filter}/{project}", method = { RequestMethod.DELETE })
-    @ResponseBody
-    public Map<String, String> removeFilter(@PathVariable String filter, @PathVariable String project) throws IOException {
-        Map<String, String> result = new HashMap<String, String>();
-        extFilterService.removeExtFilterFromProject(filter, project);
-        extFilterService.removeExternalFilter(filter);
-        result.put("success", "true");
-        return result;
-    }
-
-    @RequestMapping(value = "", method = { RequestMethod.GET })
-    @ResponseBody
-    public List<ExternalFilterDesc> getExternalFilters(@RequestParam(value = "project", required = true) String project) throws IOException {
-        List<ExternalFilterDesc> filterDescs = Lists.newArrayList();
-        filterDescs.addAll(extFilterService.getProjectManager().listExternalFilterDescs(project).values());
-        return filterDescs;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/controller/JobController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/JobController.java b/server/src/main/java/org/apache/kylin/rest/controller/JobController.java
deleted file mode 100644
index dce3847..0000000
--- a/server/src/main/java/org/apache/kylin/rest/controller/JobController.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.controller;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.TimeZone;
-
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.common.util.ClassUtil;
-import org.apache.kylin.job.JobInstance;
-import org.apache.kylin.job.Scheduler;
-import org.apache.kylin.job.SchedulerFactory;
-import org.apache.kylin.job.constant.JobStatusEnum;
-import org.apache.kylin.job.constant.JobTimeFilterEnum;
-import org.apache.kylin.job.engine.JobEngineConfig;
-import org.apache.kylin.job.exception.SchedulerException;
-import org.apache.kylin.job.execution.AbstractExecutable;
-import org.apache.kylin.job.lock.JobLock;
-import org.apache.kylin.rest.exception.InternalErrorException;
-import org.apache.kylin.rest.request.JobListRequest;
-import org.apache.kylin.rest.service.JobService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-/**
- *
- */
-@Controller
-@RequestMapping(value = "jobs")
-public class JobController extends BasicController implements InitializingBean {
-    private static final Logger logger = LoggerFactory.getLogger(JobController.class);
-
-    @Autowired
-    private JobService jobService;
-
-    private JobLock jobLock;
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
-     */
-    @SuppressWarnings("unchecked")
-    @Override
-    public void afterPropertiesSet() throws Exception {
-
-        String timeZone = jobService.getConfig().getTimeZone();
-        TimeZone tzone = TimeZone.getTimeZone(timeZone);
-        TimeZone.setDefault(tzone);
-
-        final KylinConfig kylinConfig = KylinConfig.getInstanceFromEnv();
-        final Scheduler<AbstractExecutable> scheduler = (Scheduler<AbstractExecutable>) SchedulerFactory.scheduler(kylinConfig.getSchedulerType());
-
-        jobLock = (JobLock) ClassUtil.newInstance(kylinConfig.getJobControllerLock());
-
-        new Thread(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    scheduler.init(new JobEngineConfig(kylinConfig), jobLock);
-                    while (!scheduler.hasStarted()) {
-                        logger.error("scheduler has not been started");
-                        Thread.sleep(1000);
-                    }
-                } catch (Exception e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        }).start();
-
-        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    scheduler.shutdown();
-                } catch (SchedulerException e) {
-                    logger.error("error occurred to shutdown scheduler", e);
-                }
-            }
-        }));
-    }
-
-    /**
-     * get all cube jobs
-     * 
-     * @return
-     * @throws IOException
-     */
-    @RequestMapping(value = "", method = { RequestMethod.GET })
-    @ResponseBody
-    public List<JobInstance> list(JobListRequest jobRequest) {
-
-        List<JobInstance> jobInstanceList = Collections.emptyList();
-        List<JobStatusEnum> statusList = new ArrayList<JobStatusEnum>();
-
-        if (null != jobRequest.getStatus()) {
-            for (int status : jobRequest.getStatus()) {
-                statusList.add(JobStatusEnum.getByCode(status));
-            }
-        }
-
-        JobTimeFilterEnum timeFilter = JobTimeFilterEnum.getByCode(jobRequest.getTimeFilter());
-
-        try {
-            jobInstanceList = jobService.listAllJobs(jobRequest.getCubeName(), jobRequest.getProjectName(), statusList, jobRequest.getLimit(), jobRequest.getOffset(), timeFilter);
-        } catch (Exception e) {
-            logger.error(e.getLocalizedMessage(), e);
-            throw new InternalErrorException(e);
-        }
-        return jobInstanceList;
-    }
-
-    /**
-     * Get a cube job
-     * 
-     * @return
-     * @throws IOException
-     */
-    @RequestMapping(value = "/{jobId}", method = { RequestMethod.GET })
-    @ResponseBody
-    public JobInstance get(@PathVariable String jobId) {
-        JobInstance jobInstance = null;
-        try {
-            jobInstance = jobService.getJobInstance(jobId);
-        } catch (Exception e) {
-            logger.error(e.getLocalizedMessage(), e);
-            throw new InternalErrorException(e);
-        }
-
-        return jobInstance;
-    }
-
-    /**
-     * Get a job step output
-     * 
-     * @return
-     * @throws IOException
-     */
-    @RequestMapping(value = "/{jobId}/steps/{stepId}/output", method = { RequestMethod.GET })
-    @ResponseBody
-    public Map<String, String> getStepOutput(@PathVariable String jobId, @PathVariable String stepId) {
-        Map<String, String> result = new HashMap<String, String>();
-        result.put("jobId", jobId);
-        result.put("stepId", String.valueOf(stepId));
-        result.put("cmd_output", jobService.getExecutableManager().getOutput(stepId).getVerboseMsg());
-        return result;
-    }
-
-    /**
-     * Resume a cube job
-     * 
-     * @return
-     * @throws IOException
-     */
-    @RequestMapping(value = "/{jobId}/resume", method = { RequestMethod.PUT })
-    @ResponseBody
-    public JobInstance resume(@PathVariable String jobId) {
-        try {
-            final JobInstance jobInstance = jobService.getJobInstance(jobId);
-            jobService.resumeJob(jobInstance);
-            return jobService.getJobInstance(jobId);
-        } catch (Exception e) {
-            logger.error(e.getLocalizedMessage(), e);
-            throw new InternalErrorException(e);
-        }
-    }
-
-    /**
-     * Cancel a job
-     * 
-     * @return
-     * @throws IOException
-     */
-    @RequestMapping(value = "/{jobId}/cancel", method = { RequestMethod.PUT })
-    @ResponseBody
-    public JobInstance cancel(@PathVariable String jobId) {
-
-        try {
-            final JobInstance jobInstance = jobService.getJobInstance(jobId);
-            return jobService.cancelJob(jobInstance);
-        } catch (Exception e) {
-            logger.error(e.getLocalizedMessage(), e);
-            throw new InternalErrorException(e);
-        }
-
-    }
-
-    public void setJobService(JobService jobService) {
-        this.jobService = jobService;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
deleted file mode 100644
index 5f6a91b..0000000
--- a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.controller;
-
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.List;
-import java.util.UUID;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.common.util.JsonUtil;
-import org.apache.kylin.metadata.MetadataManager;
-import org.apache.kylin.metadata.model.DataModelDesc;
-import org.apache.kylin.metadata.project.ProjectInstance;
-import org.apache.kylin.rest.exception.BadRequestException;
-import org.apache.kylin.rest.exception.ForbiddenException;
-import org.apache.kylin.rest.exception.InternalErrorException;
-import org.apache.kylin.rest.exception.NotFoundException;
-import org.apache.kylin.rest.request.ModelRequest;
-import org.apache.kylin.rest.service.ModelService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.AccessDeniedException;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-
-/**
- * ModelController is defined as Restful API entrance for UI.
- *
- * @author jiazhong
- */
-@Controller
-@RequestMapping(value = "/models")
-public class ModelController extends BasicController {
-    private static final Logger logger = LoggerFactory.getLogger(ModelController.class);
-
-    @Autowired
-    private ModelService modelService;
-
-    @RequestMapping(value = "", method = { RequestMethod.GET })
-    @ResponseBody
-    public List<DataModelDesc> getModels(@RequestParam(value = "modelName", required = false) String modelName, @RequestParam(value = "projectName", required = false) String projectName, @RequestParam(value = "limit", required = false) Integer limit, @RequestParam(value = "offset", required = false) Integer offset) {
-        try {
-            return modelService.getModels(modelName, projectName, limit, offset);
-        } catch (IOException e) {
-            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
-            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
-        }
-    }
-
-    /**
-     *
-     * create model
-     * @throws java.io.IOException
-     */
-    @RequestMapping(value = "", method = { RequestMethod.POST })
-    @ResponseBody
-    public ModelRequest saveModelDesc(@RequestBody ModelRequest modelRequest) {
-        //Update Model
-        DataModelDesc modelDesc = deserializeDataModelDesc(modelRequest);
-        if (modelDesc == null || StringUtils.isEmpty(modelDesc.getName())) {
-            return modelRequest;
-        }
-
-        if (StringUtils.isEmpty(modelDesc.getName())) {
-            logger.info("Model name should not be empty.");
-            throw new BadRequestException("Model name should not be empty.");
-        }
-
-        try {
-            modelDesc.setUuid(UUID.randomUUID().toString());
-            String projectName = (null == modelRequest.getProject()) ? ProjectInstance.DEFAULT_PROJECT_NAME : modelRequest.getProject();
-
-            modelService.createModelDesc(projectName, modelDesc);
-        } catch (IOException e) {
-            // TODO Auto-generated catch block
-            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
-            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
-        }
-
-        modelRequest.setUuid(modelDesc.getUuid());
-        modelRequest.setSuccessful(true);
-        return modelRequest;
-    }
-
-    @RequestMapping(value = "", method = { RequestMethod.PUT })
-    @ResponseBody
-    public ModelRequest updateModelDesc(@RequestBody ModelRequest modelRequest) throws JsonProcessingException {
-        DataModelDesc modelDesc = deserializeDataModelDesc(modelRequest);
-        if (modelDesc == null) {
-            return modelRequest;
-        }
-        try {
-            modelDesc = modelService.updateModelAndDesc(modelDesc);
-        } catch (AccessDeniedException accessDeniedException) {
-            throw new ForbiddenException("You don't have right to update this model.");
-        } catch (Exception e) {
-            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
-            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
-        }
-
-        if (modelDesc.getError().isEmpty()) {
-            modelRequest.setSuccessful(true);
-        } else {
-            logger.warn("Model " + modelDesc.getName() + " fail to update because " + modelDesc.getError());
-            updateRequest(modelRequest, false, omitMessage(modelDesc.getError()));
-        }
-        String descData = JsonUtil.writeValueAsIndentString(modelDesc);
-        modelRequest.setModelDescData(descData);
-        return modelRequest;
-    }
-
-    @RequestMapping(value = "/{modelName}", method = { RequestMethod.DELETE })
-    @ResponseBody
-    public void deleteModel(@PathVariable String modelName) {
-        DataModelDesc desc = modelService.getMetadataManager().getDataModelDesc(modelName);
-        if (null == desc) {
-            throw new NotFoundException("Data Model with name " + modelName + " not found..");
-        }
-        try {
-            modelService.dropModel(desc);
-        } catch (Exception e) {
-            logger.error(e.getLocalizedMessage(), e);
-            throw new InternalErrorException("Failed to delete model. " + " Caused by: " + e.getMessage(), e);
-        }
-    }
-
-    @RequestMapping(value = "/{modelName}/clone", method = { RequestMethod.PUT })
-    @ResponseBody
-    public ModelRequest cloneModel(@PathVariable String modelName, @RequestBody ModelRequest modelRequest) {
-        String project = modelRequest.getProject();
-        MetadataManager metaManager = MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
-        DataModelDesc modelDesc = metaManager.getDataModelDesc(modelName);
-        String newModelName = modelRequest.getModelName();
-
-        if (StringUtils.isEmpty(project)) {
-            logger.info("Project name should not be empty.");
-            throw new BadRequestException("Project name should not be empty.");
-        }
-
-        if (modelDesc == null || StringUtils.isEmpty(modelName)) {
-            logger.info("Model does not exist.");
-            throw new BadRequestException("Model does not exist.");
-        }
-
-        if (StringUtils.isEmpty(newModelName)) {
-            logger.info("New model name is empty.");
-            throw new BadRequestException("New model name is empty.");
-        }
-
-        DataModelDesc newModelDesc = DataModelDesc.getCopyOf(modelDesc);
-        newModelDesc.setName(newModelName);
-        try {
-            newModelDesc = modelService.createModelDesc(project, newModelDesc);
-
-            //reload avoid shallow
-            metaManager.reloadDataModelDesc(newModelName);
-        } catch (IOException e) {
-            throw new InternalErrorException("failed to clone DataModelDesc", e);
-        }
-
-        modelRequest.setUuid(newModelDesc.getUuid());
-        modelRequest.setSuccessful(true);
-        return modelRequest;
-    }
-
-    private DataModelDesc deserializeDataModelDesc(ModelRequest modelRequest) {
-        DataModelDesc desc = null;
-        try {
-            logger.debug("Saving MODEL " + modelRequest.getModelDescData());
-            desc = JsonUtil.readValue(modelRequest.getModelDescData(), DataModelDesc.class);
-        } catch (JsonParseException e) {
-            logger.error("The data model definition is not valid.", e);
-            updateRequest(modelRequest, false, e.getMessage());
-        } catch (JsonMappingException e) {
-            logger.error("The data model definition is not valid.", e);
-            updateRequest(modelRequest, false, e.getMessage());
-        } catch (IOException e) {
-            logger.error("Failed to deal with the request.", e);
-            throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
-        }
-        return desc;
-    }
-
-    private void updateRequest(ModelRequest request, boolean success, String message) {
-        request.setModelDescData("");
-        request.setSuccessful(success);
-        request.setMessage(message);
-    }
-
-    public void setModelService(ModelService modelService) {
-        this.modelService = modelService;
-    }
-
-    /**
-     * @param errors
-     * @return
-     */
-    private String omitMessage(List<String> errors) {
-        StringBuffer buffer = new StringBuffer();
-        for (Iterator<String> iterator = errors.iterator(); iterator.hasNext();) {
-            String string = (String) iterator.next();
-            buffer.append(string);
-            buffer.append("\n");
-        }
-        return buffer.toString();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/controller/ModelDescController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/ModelDescController.java b/server/src/main/java/org/apache/kylin/rest/controller/ModelDescController.java
deleted file mode 100644
index 4171afd..0000000
--- a/server/src/main/java/org/apache/kylin/rest/controller/ModelDescController.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.controller;
-
-import java.io.IOException;
-
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.metadata.MetadataManager;
-import org.apache.kylin.metadata.model.DataModelDesc;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-/**
- * @author jiazhong
- * 
- */
-@Controller
-@RequestMapping(value = "/model")
-public class ModelDescController extends BasicController {
-
-    /**
-     * Get detail information of the "Model ID"
-     * 
-     * @param modelDescName
-     *            Model ID
-     * @return
-     * @throws IOException
-     */
-    @RequestMapping(value = "/{model_name}", method = { RequestMethod.GET })
-    @ResponseBody
-    public DataModelDesc getModel(@PathVariable String model_name) {
-        MetadataManager metaManager = MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
-        DataModelDesc modeDesc = metaManager.getDataModelDesc(model_name);
-        return modeDesc;
-
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/ProjectController.java b/server/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
deleted file mode 100644
index f829fff..0000000
--- a/server/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.controller;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.kylin.common.persistence.AclEntity;
-import org.apache.kylin.cube.CubeInstance;
-import org.apache.kylin.metadata.project.ProjectInstance;
-import org.apache.kylin.rest.constant.Constant;
-import org.apache.kylin.rest.exception.InternalErrorException;
-import org.apache.kylin.rest.request.CreateProjectRequest;
-import org.apache.kylin.rest.request.UpdateProjectRequest;
-import org.apache.kylin.rest.service.AccessService;
-import org.apache.kylin.rest.service.CubeService;
-import org.apache.kylin.rest.service.ProjectService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.acls.domain.GrantedAuthoritySid;
-import org.springframework.security.acls.domain.PrincipalSid;
-import org.springframework.security.acls.model.AccessControlEntry;
-import org.springframework.security.acls.model.Acl;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-/**
- * @author xduo
- */
-@Controller
-@RequestMapping(value = "/projects")
-public class ProjectController extends BasicController {
-    private static final Logger logger = LoggerFactory.getLogger(ProjectController.class);
-
-    @Autowired
-    private ProjectService projectService;
-    @Autowired
-    private AccessService accessService;
-    @Autowired
-    private CubeService cubeService;
-
-    /**
-     * Get available project list
-     *
-     * @return Table metadata array
-     * @throws IOException
-     */
-    @RequestMapping(value = "", method = { RequestMethod.GET })
-    @ResponseBody
-    public List<ProjectInstance> getProjects(@RequestParam(value = "limit", required = false) Integer limit, @RequestParam(value = "offset", required = false) Integer offset) {
-        return projectService.listAllProjects(limit, offset);
-    }
-
-    @RequestMapping(value = "/readable", method = { RequestMethod.GET })
-    @ResponseBody
-    public List<ProjectInstance> getReadableProjects(@RequestParam(value = "limit", required = false) Integer limit, @RequestParam(value = "offset", required = false) Integer offset) {
-        List<ProjectInstance> readableProjects = new ArrayList<ProjectInstance>();
-        //list all projects first
-        List<ProjectInstance> projectInstances = projectService.listAllProjects(limit, offset);
-
-        //get user infomation
-        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
-        UserDetails userDetails = null;
-        if (authentication == null) {
-            logger.debug("authentication is null.");
-            throw new InternalErrorException("Can not find authentication infomation.");
-        }
-        if (authentication.getPrincipal() instanceof UserDetails) {
-            logger.debug("authentication.getPrincipal() is " + authentication.getPrincipal());
-            userDetails = (UserDetails) authentication.getPrincipal();
-        }
-        if (authentication.getDetails() instanceof UserDetails) {
-            logger.debug("authentication.getDetails() is " + authentication.getDetails());
-            userDetails = (UserDetails) authentication.getDetails();
-        }
-
-        //check if ROLE_ADMIN return all,also get user role list
-        List<String> userAuthority = new ArrayList<>();
-        for (GrantedAuthority auth : authentication.getAuthorities()) {
-            userAuthority.add(auth.getAuthority());
-            if (auth.getAuthority().equals(Constant.ROLE_ADMIN))
-                return projectInstances;
-        }
-        String userName = userDetails.getUsername();
-        for (ProjectInstance projectInstance : projectInstances) {
-            if (projectInstance == null) {
-                continue;
-            }
-
-            boolean hasProjectPermission = false;
-            AclEntity ae = accessService.getAclEntity("ProjectInstance", projectInstance.getId());
-            Acl projectAcl = accessService.getAcl(ae);
-            //project no Acl info will be skipped
-            if (projectAcl != null) {
-
-                //project owner has permission
-                if (((PrincipalSid) projectAcl.getOwner()).getPrincipal().equals(userName)) {
-                    readableProjects.add(projectInstance);
-                    continue;
-                }
-
-                //check project permission and role
-                for (AccessControlEntry ace : projectAcl.getEntries()) {
-                    if (ace.getSid() instanceof PrincipalSid && ((PrincipalSid) ace.getSid()).getPrincipal().equals(userName)) {
-                        hasProjectPermission = true;
-                        readableProjects.add(projectInstance);
-                        break;
-
-                    } else if (ace.getSid() instanceof GrantedAuthoritySid) {
-                        String projectAuthority = ((GrantedAuthoritySid) ace.getSid()).getGrantedAuthority();
-                        if (userAuthority.contains(projectAuthority)) {
-                            hasProjectPermission = true;
-                            readableProjects.add(projectInstance);
-                            break;
-                        }
-
-                    }
-
-                }
-            }
-
-            if (!hasProjectPermission) {
-                List<CubeInstance> cubeInstances = cubeService.listAllCubes(projectInstance.getName());
-
-                for (CubeInstance cubeInstance : cubeInstances) {
-                    if (cubeInstance == null) {
-                        continue;
-                    }
-                    boolean hasCubePermission = false;
-                    AclEntity cubeAe = accessService.getAclEntity("CubeInstance", cubeInstance.getId());
-                    Acl cubeAcl = accessService.getAcl(cubeAe);
-                    //cube no Acl info will not be used to filter project
-                    if (cubeAcl != null) {
-                        //cube owner will have permission to read project
-                        if (((PrincipalSid) cubeAcl.getOwner()).getPrincipal().equals(userName)) {
-                            hasProjectPermission = true;
-                            break;
-                        }
-                        for (AccessControlEntry cubeAce : cubeAcl.getEntries()) {
-
-                            if (cubeAce.getSid() instanceof PrincipalSid && ((PrincipalSid) cubeAce.getSid()).getPrincipal().equals(userName)) {
-                                hasCubePermission = true;
-                                break;
-                            } else if (cubeAce.getSid() instanceof GrantedAuthoritySid) {
-                                String cubeAuthority = ((GrantedAuthoritySid) cubeAce.getSid()).getGrantedAuthority();
-                                if (userAuthority.contains(cubeAuthority)) {
-                                    hasCubePermission = true;
-                                    break;
-                                }
-
-                            }
-                        }
-                    }
-                    if (hasCubePermission) {
-                        hasProjectPermission = true;
-                        break;
-                    }
-                }
-                if (hasProjectPermission) {
-                    readableProjects.add(projectInstance);
-                }
-            }
-
-        }
-        return readableProjects;
-    }
-
-    @RequestMapping(value = "", method = { RequestMethod.POST })
-    @ResponseBody
-    public ProjectInstance saveProject(@RequestBody CreateProjectRequest projectRequest) {
-        if (StringUtils.isEmpty(projectRequest.getName())) {
-            throw new InternalErrorException("A project name must be given to create a project");
-        }
-
-        ProjectInstance createdProj = null;
-        try {
-            createdProj = projectService.createProject(projectRequest);
-        } catch (Exception e) {
-            logger.error("Failed to deal with the request.", e);
-            throw new InternalErrorException(e.getLocalizedMessage());
-        }
-
-        return createdProj;
-    }
-
-    @RequestMapping(value = "", method = { RequestMethod.PUT })
-    @ResponseBody
-    public ProjectInstance updateProject(@RequestBody UpdateProjectRequest projectRequest) {
-        if (StringUtils.isEmpty(projectRequest.getFormerProjectName())) {
-            throw new InternalErrorException("A project name must be given to update a project");
-        }
-
-        ProjectInstance updatedProj = null;
-        try {
-            ProjectInstance currentProject = projectService.getProjectManager().getProject(projectRequest.getFormerProjectName());
-            updatedProj = projectService.updateProject(projectRequest, currentProject);
-        } catch (Exception e) {
-            logger.error("Failed to deal with the request.", e);
-            throw new InternalErrorException(e.getLocalizedMessage());
-        }
-
-        return updatedProj;
-    }
-
-    @RequestMapping(value = "/{projectName}", method = { RequestMethod.DELETE })
-    @ResponseBody
-    public void deleteProject(@PathVariable String projectName) {
-        try {
-
-            ProjectInstance project = projectService.getProjectManager().getProject(projectName);
-            projectService.deleteProject(projectName, project);
-        } catch (Exception e) {
-            logger.error(e.getLocalizedMessage(), e);
-            throw new InternalErrorException("Failed to delete project. " + " Caused by: " + e.getMessage(), e);
-        }
-    }
-
-    public void setProjectService(ProjectService projectService) {
-        this.projectService = projectService;
-    }
-
-    public void setAccessService(AccessService accessService) {
-        this.accessService = accessService;
-    }
-
-    public void setCubeService(CubeService cubeService) {
-        this.cubeService = cubeService;
-    }
-}


[08/13] kylin git commit: KYLIN-1823 split code from kylin-server into kylin-server-base

Posted by li...@apache.org.
http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/service/BasicService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/BasicService.java b/server-base/src/main/java/org/apache/kylin/rest/service/BasicService.java
new file mode 100644
index 0000000..7197f03
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/BasicService.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.service;
+
+import java.io.IOException;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.cube.CubeDescManager;
+import org.apache.kylin.cube.CubeManager;
+import org.apache.kylin.engine.mr.CubingJob;
+import org.apache.kylin.engine.mr.steps.CubingExecutableUtil;
+import org.apache.kylin.engine.streaming.StreamingManager;
+import org.apache.kylin.invertedindex.IIDescManager;
+import org.apache.kylin.invertedindex.IIManager;
+import org.apache.kylin.job.execution.AbstractExecutable;
+import org.apache.kylin.job.execution.ExecutableState;
+import org.apache.kylin.job.execution.Output;
+import org.apache.kylin.job.manager.ExecutableManager;
+import org.apache.kylin.metadata.MetadataManager;
+import org.apache.kylin.metadata.badquery.BadQueryHistoryManager;
+import org.apache.kylin.metadata.project.ProjectInstance;
+import org.apache.kylin.metadata.project.ProjectManager;
+import org.apache.kylin.metadata.realization.RealizationType;
+import org.apache.kylin.source.kafka.KafkaConfigManager;
+import org.apache.kylin.storage.hybrid.HybridManager;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Lists;
+
+public abstract class BasicService {
+
+    public KylinConfig getConfig() {
+        KylinConfig kylinConfig = KylinConfig.getInstanceFromEnv();
+
+        if (kylinConfig == null) {
+            throw new IllegalArgumentException("Failed to load kylin config instance");
+        }
+
+        return kylinConfig;
+    }
+
+    public MetadataManager getMetadataManager() {
+        return MetadataManager.getInstance(getConfig());
+    }
+
+    public CubeManager getCubeManager() {
+        return CubeManager.getInstance(getConfig());
+    }
+
+    public StreamingManager getStreamingManager() {
+        return StreamingManager.getInstance(getConfig());
+    }
+
+    public KafkaConfigManager getKafkaManager() throws IOException {
+        return KafkaConfigManager.getInstance(getConfig());
+    }
+
+    public CubeDescManager getCubeDescManager() {
+        return CubeDescManager.getInstance(getConfig());
+    }
+
+    public ProjectManager getProjectManager() {
+        return ProjectManager.getInstance(getConfig());
+    }
+
+    public HybridManager getHybridManager() {
+        return HybridManager.getInstance(getConfig());
+    }
+
+    public ExecutableManager getExecutableManager() {
+        return ExecutableManager.getInstance(getConfig());
+    }
+
+    public IIDescManager getIIDescManager() {
+        return IIDescManager.getInstance(getConfig());
+    }
+
+    public IIManager getIIManager() {
+        return IIManager.getInstance(getConfig());
+    }
+
+    public BadQueryHistoryManager getBadQueryHistoryManager() {
+        return BadQueryHistoryManager.getInstance(getConfig());
+    }
+
+    protected List<CubingJob> listAllCubingJobs(final String cubeName, final String projectName, final Set<ExecutableState> statusList, final Map<String, Output> allOutputs) {
+        return listAllCubingJobs(cubeName, projectName, statusList, -1L, -1L, allOutputs);
+    }
+
+    protected List<CubingJob> listAllCubingJobs(final String cubeName, final String projectName, final Set<ExecutableState> statusList, long timeStartInMillis, long timeEndInMillis, final Map<String, Output> allOutputs) {
+        List<CubingJob> results = Lists.newArrayList(FluentIterable.from(getExecutableManager().getAllExecutables(timeStartInMillis, timeEndInMillis)).filter(new Predicate<AbstractExecutable>() {
+            @Override
+            public boolean apply(AbstractExecutable executable) {
+                if (executable instanceof CubingJob) {
+                    if (cubeName == null) {
+                        return true;
+                    }
+                    return CubingExecutableUtil.getCubeName(executable.getParams()).equalsIgnoreCase(cubeName);
+                } else {
+                    return false;
+                }
+            }
+        }).transform(new Function<AbstractExecutable, CubingJob>() {
+            @Override
+            public CubingJob apply(AbstractExecutable executable) {
+                return (CubingJob) executable;
+            }
+        }).filter(Predicates.and(new Predicate<CubingJob>() {
+            @Override
+            public boolean apply(CubingJob executable) {
+                if (null == projectName || null == getProjectManager().getProject(projectName)) {
+                    return true;
+                } else {
+                    ProjectInstance project = getProjectManager().getProject(projectName);
+                    return project.containsRealization(RealizationType.CUBE, CubingExecutableUtil.getCubeName(executable.getParams()));
+                }
+            }
+        }, new Predicate<CubingJob>() {
+            @Override
+            public boolean apply(CubingJob executable) {
+                return statusList.contains(allOutputs.get(executable.getId()).getState());
+            }
+        })));
+        return results;
+    }
+
+    protected List<CubingJob> listAllCubingJobs(final String cubeName, final String projectName, final Set<ExecutableState> statusList) {
+        return listAllCubingJobs(cubeName, projectName, statusList, getExecutableManager().getAllOutputs());
+    }
+
+    protected List<CubingJob> listAllCubingJobs(final String cubeName, final String projectName) {
+        return listAllCubingJobs(cubeName, projectName, EnumSet.allOf(ExecutableState.class), getExecutableManager().getAllOutputs());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/service/CacheService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/CacheService.java b/server-base/src/main/java/org/apache/kylin/rest/service/CacheService.java
new file mode 100644
index 0000000..9185544
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/CacheService.java
@@ -0,0 +1,313 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.service;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.annotation.PostConstruct;
+import javax.sql.DataSource;
+
+import org.apache.calcite.jdbc.Driver;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.restclient.Broadcaster;
+import org.apache.kylin.cube.CubeDescManager;
+import org.apache.kylin.cube.CubeInstance;
+import org.apache.kylin.cube.CubeManager;
+import org.apache.kylin.dict.DictionaryManager;
+import org.apache.kylin.engine.streaming.StreamingManager;
+import org.apache.kylin.invertedindex.IIDescManager;
+import org.apache.kylin.invertedindex.IIManager;
+import org.apache.kylin.metadata.MetadataManager;
+import org.apache.kylin.metadata.project.ProjectInstance;
+import org.apache.kylin.metadata.project.ProjectManager;
+import org.apache.kylin.metadata.realization.RealizationRegistry;
+import org.apache.kylin.metadata.realization.RealizationType;
+import org.apache.kylin.query.enumerator.OLAPQuery;
+import org.apache.kylin.query.schema.OLAPSchemaFactory;
+import org.apache.kylin.rest.controller.QueryController;
+import org.apache.kylin.source.kafka.KafkaConfigManager;
+import org.apache.kylin.storage.hbase.HBaseConnection;
+import org.apache.kylin.storage.hybrid.HybridManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+import org.springframework.stereotype.Component;
+
+import net.sf.ehcache.CacheManager;
+
+/**
+ */
+@Component("cacheService")
+public class CacheService extends BasicService {
+
+    private static final Logger logger = LoggerFactory.getLogger(CacheService.class);
+
+    private static ConcurrentMap<String, DataSource> olapDataSources = new ConcurrentHashMap<String, DataSource>();
+
+    @Autowired
+    private CubeService cubeService;
+
+    @Autowired
+    private CacheManager cacheManager;
+
+    @PostConstruct
+    public void initCubeChangeListener() throws IOException {
+        CubeManager cubeMgr = CubeManager.getInstance(getConfig());
+        cubeMgr.setCubeChangeListener(new CubeManager.CubeChangeListener() {
+
+            @Override
+            public void afterCubeCreate(CubeInstance cube) {
+                // no cache need change
+            }
+
+            @Override
+            public void afterCubeUpdate(CubeInstance cube) {
+                rebuildCubeCache(cube.getName());
+            }
+
+            @Override
+            public void afterCubeDelete(CubeInstance cube) {
+                removeCubeCache(cube.getName(), cube);
+            }
+        });
+    }
+
+    // for test
+    public void setCubeService(CubeService cubeService) {
+        this.cubeService = cubeService;
+    }
+
+    protected void cleanDataCache(String storageUUID) {
+        if (cacheManager != null) {
+            logger.info("cleaning cache for " + storageUUID + " (currently remove all entries)");
+            cacheManager.getCache(QueryController.SUCCESS_QUERY_CACHE).removeAll();
+            cacheManager.getCache(QueryController.EXCEPTION_QUERY_CACHE).removeAll();
+        } else {
+            logger.warn("skip cleaning cache for " + storageUUID);
+        }
+    }
+
+    protected void cleanAllDataCache() {
+        if (cacheManager != null) {
+            logger.warn("cleaning all storage cache");
+            cacheManager.clearAll();
+        } else {
+            logger.warn("skip cleaning all storage cache");
+        }
+    }
+
+    private static void removeOLAPDataSource(String project) {
+        logger.info("removeOLAPDataSource is called for project " + project);
+        if (StringUtils.isEmpty(project))
+            throw new IllegalArgumentException("removeOLAPDataSource: project name not given");
+
+        project = ProjectInstance.getNormalizedProjectName(project);
+        olapDataSources.remove(project);
+    }
+
+    public static void removeAllOLAPDataSources() {
+        // brutal, yet simplest way
+        logger.info("removeAllOLAPDataSources is called.");
+        olapDataSources.clear();
+    }
+
+    public DataSource getOLAPDataSource(String project) {
+
+        project = ProjectInstance.getNormalizedProjectName(project);
+
+        DataSource ret = olapDataSources.get(project);
+        if (ret == null) {
+            logger.debug("Creating a new data source, OLAP data source pointing to " + getConfig());
+            File modelJson = OLAPSchemaFactory.createTempOLAPJson(project, getConfig());
+
+            try {
+                String text = FileUtils.readFileToString(modelJson);
+                logger.debug("The new temp olap json is :" + text);
+            } catch (IOException e) {
+                e.printStackTrace(); // logging failure is not critical
+            }
+
+            DriverManagerDataSource ds = new DriverManagerDataSource();
+            Properties props = new Properties();
+            props.setProperty(OLAPQuery.PROP_SCAN_THRESHOLD, String.valueOf(KylinConfig.getInstanceFromEnv().getScanThreshold()));
+            ds.setConnectionProperties(props);
+            ds.setDriverClassName(Driver.class.getName());
+            ds.setUrl("jdbc:calcite:model=" + modelJson.getAbsolutePath());
+
+            ret = olapDataSources.putIfAbsent(project, ds);
+            if (ret == null) {
+                ret = ds;
+            }
+        }
+        return ret;
+    }
+
+    public void rebuildCache(Broadcaster.TYPE cacheType, String cacheKey) {
+        final String log = "rebuild cache type: " + cacheType + " name:" + cacheKey;
+        logger.info(log);
+        try {
+            switch (cacheType) {
+            case CUBE:
+                rebuildCubeCache(cacheKey);
+                break;
+            case STREAMING:
+                getStreamingManager().reloadStreamingConfigLocal(cacheKey);
+                break;
+            case KAFKA:
+                getKafkaManager().reloadKafkaConfigLocal(cacheKey);
+                break;
+            case CUBE_DESC:
+                getCubeDescManager().reloadCubeDescLocal(cacheKey);
+                break;
+            case PROJECT:
+                reloadProjectCache(cacheKey);
+                break;
+            case INVERTED_INDEX:
+                //II update does not need to update storage cache because it is dynamic already
+                getIIManager().reloadIILocal(cacheKey);
+                getHybridManager().reloadHybridInstanceByChild(RealizationType.INVERTED_INDEX, cacheKey);
+                getProjectManager().clearL2Cache();
+                break;
+            case INVERTED_INDEX_DESC:
+                getIIDescManager().reloadIIDescLocal(cacheKey);
+                break;
+            case TABLE:
+                getMetadataManager().reloadTableCache(cacheKey);
+                IIDescManager.clearCache();
+                CubeDescManager.clearCache();
+                break;
+            case EXTERNAL_FILTER:
+                getMetadataManager().reloadExtFilter(cacheKey);
+                IIDescManager.clearCache();
+                CubeDescManager.clearCache();
+                break;
+            case DATA_MODEL:
+                getMetadataManager().reloadDataModelDesc(cacheKey);
+                IIDescManager.clearCache();
+                CubeDescManager.clearCache();
+                break;
+            case ALL:
+                DictionaryManager.clearCache();
+                MetadataManager.clearCache();
+                CubeDescManager.clearCache();
+                CubeManager.clearCache();
+                IIDescManager.clearCache();
+                IIManager.clearCache();
+                HybridManager.clearCache();
+                RealizationRegistry.clearCache();
+                ProjectManager.clearCache();
+                KafkaConfigManager.clearCache();
+                StreamingManager.clearCache();
+                HBaseConnection.clearConnCache();
+
+                cleanAllDataCache();
+                removeAllOLAPDataSources();
+                break;
+            default:
+                throw new RuntimeException("invalid cacheType:" + cacheType);
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("error " + log, e);
+        }
+    }
+
+    private void rebuildCubeCache(String cubeName) {
+        CubeInstance cube = getCubeManager().reloadCubeLocal(cubeName);
+        getHybridManager().reloadHybridInstanceByChild(RealizationType.CUBE, cubeName);
+        reloadProjectCache(getProjectManager().findProjects(RealizationType.CUBE, cubeName));
+        //clean query related cache first
+        if (cube != null) {
+            cleanDataCache(cube.getUuid());
+        }
+        cubeService.updateOnNewSegmentReady(cubeName);
+    }
+
+    public void removeCache(Broadcaster.TYPE cacheType, String cacheKey) {
+        final String log = "remove cache type: " + cacheType + " name:" + cacheKey;
+        try {
+            switch (cacheType) {
+            case CUBE:
+                removeCubeCache(cacheKey, null);
+                break;
+            case CUBE_DESC:
+                getCubeDescManager().removeLocalCubeDesc(cacheKey);
+                break;
+            case PROJECT:
+                ProjectManager.clearCache();
+                break;
+            case INVERTED_INDEX:
+                getIIManager().removeIILocal(cacheKey);
+                break;
+            case INVERTED_INDEX_DESC:
+                getIIDescManager().removeIIDescLocal(cacheKey);
+                break;
+            case TABLE:
+                throw new UnsupportedOperationException(log);
+            case EXTERNAL_FILTER:
+                throw new UnsupportedOperationException(log);
+            case DATA_MODEL:
+                getMetadataManager().removeModelCache(cacheKey);
+                break;
+            default:
+                throw new RuntimeException("invalid cacheType:" + cacheType);
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("error " + log, e);
+        }
+    }
+
+    private void removeCubeCache(String cubeName, CubeInstance cube) {
+        // you may not get the cube instance if it's already removed from metadata
+        if (cube == null) {
+            cube = getCubeManager().getCube(cubeName);
+        }
+
+        getCubeManager().removeCubeLocal(cubeName);
+        getHybridManager().reloadHybridInstanceByChild(RealizationType.CUBE, cubeName);
+        reloadProjectCache(getProjectManager().findProjects(RealizationType.CUBE, cubeName));
+
+        if (cube != null) {
+            cleanDataCache(cube.getUuid());
+        }
+    }
+
+    private void reloadProjectCache(List<ProjectInstance> projects) {
+        for (ProjectInstance prj : projects) {
+            reloadProjectCache(prj.getName());
+        }
+    }
+
+    private void reloadProjectCache(String projectName) {
+        try {
+            getProjectManager().reloadProjectLocal(projectName);
+        } catch (IOException ex) {
+            logger.warn("Failed to reset project cache", ex);
+        }
+        removeOLAPDataSource(projectName);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java b/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java
new file mode 100644
index 0000000..a9d4bfc
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/CubeService.java
@@ -0,0 +1,676 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.service;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.util.Pair;
+import org.apache.kylin.cube.CubeInstance;
+import org.apache.kylin.cube.CubeManager;
+import org.apache.kylin.cube.CubeSegment;
+import org.apache.kylin.cube.CubeUpdate;
+import org.apache.kylin.cube.cuboid.CuboidCLI;
+import org.apache.kylin.cube.model.CubeDesc;
+import org.apache.kylin.engine.EngineFactory;
+import org.apache.kylin.engine.mr.CubingJob;
+import org.apache.kylin.engine.mr.HadoopUtil;
+import org.apache.kylin.engine.mr.common.HadoopShellExecutable;
+import org.apache.kylin.engine.mr.common.MapReduceExecutable;
+import org.apache.kylin.job.exception.JobException;
+import org.apache.kylin.job.execution.DefaultChainedExecutable;
+import org.apache.kylin.job.execution.ExecutableState;
+import org.apache.kylin.metadata.MetadataConstants;
+import org.apache.kylin.metadata.MetadataManager;
+import org.apache.kylin.metadata.model.SegmentStatusEnum;
+import org.apache.kylin.metadata.model.TableDesc;
+import org.apache.kylin.metadata.project.ProjectInstance;
+import org.apache.kylin.metadata.project.ProjectManager;
+import org.apache.kylin.metadata.project.RealizationEntry;
+import org.apache.kylin.metadata.realization.RealizationStatusEnum;
+import org.apache.kylin.metadata.realization.RealizationType;
+import org.apache.kylin.rest.constant.Constant;
+import org.apache.kylin.rest.exception.InternalErrorException;
+import org.apache.kylin.rest.request.MetricsRequest;
+import org.apache.kylin.rest.response.HBaseResponse;
+import org.apache.kylin.rest.response.MetricsResponse;
+import org.apache.kylin.rest.security.AclPermission;
+import org.apache.kylin.source.hive.HiveSourceTableLoader;
+import org.apache.kylin.source.hive.cardinality.HiveColumnCardinalityJob;
+import org.apache.kylin.source.hive.cardinality.HiveColumnCardinalityUpdateJob;
+import org.apache.kylin.storage.hbase.HBaseConnection;
+import org.apache.kylin.storage.hbase.util.HBaseRegionSizeCalculator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PostFilter;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Stateless & lightweight service facade of cube management functions.
+ *
+ * @author yangli9
+ */
+@Component("cubeMgmtService")
+public class CubeService extends BasicService {
+    private static final String DESC_SUFFIX = "_desc";
+
+    private static final Logger logger = LoggerFactory.getLogger(CubeService.class);
+
+    private WeakHashMap<String, HBaseResponse> htableInfoCache = new WeakHashMap<>();
+
+    @Autowired
+    private AccessService accessService;
+
+    @PostFilter(Constant.ACCESS_POST_FILTER_READ)
+    public List<CubeInstance> listAllCubes(final String cubeName, final String projectName, final String modelName) {
+        List<CubeInstance> cubeInstances = null;
+        ProjectInstance project = (null != projectName) ? getProjectManager().getProject(projectName) : null;
+
+        if (null == project) {
+            cubeInstances = getCubeManager().listAllCubes();
+        } else {
+            cubeInstances = listAllCubes(projectName);
+        }
+
+        List<CubeInstance> filterModelCubes = new ArrayList<CubeInstance>();
+
+        if (modelName != null) {
+            for (CubeInstance cubeInstance : cubeInstances) {
+                boolean isCubeMatch = cubeInstance.getDescriptor().getModelName().toLowerCase().equals(modelName.toLowerCase());
+                if (isCubeMatch) {
+                    filterModelCubes.add(cubeInstance);
+                }
+            }
+        } else {
+            filterModelCubes = cubeInstances;
+        }
+
+        List<CubeInstance> filterCubes = new ArrayList<CubeInstance>();
+        for (CubeInstance cubeInstance : filterModelCubes) {
+            boolean isCubeMatch = (null == cubeName) || cubeInstance.getName().toLowerCase().contains(cubeName.toLowerCase());
+
+            if (isCubeMatch) {
+                filterCubes.add(cubeInstance);
+            }
+        }
+
+        return filterCubes;
+    }
+
+    public List<CubeInstance> getCubes(final String cubeName, final String projectName, final String modelName, final Integer limit, final Integer offset) {
+
+        List<CubeInstance> cubes;
+        cubes = listAllCubes(cubeName, projectName, modelName);
+
+        int climit = (null == limit) ? cubes.size() : limit;
+        int coffset = (null == offset) ? 0 : offset;
+
+        if (cubes.size() <= coffset) {
+            return Collections.emptyList();
+        }
+
+        if ((cubes.size() - coffset) < climit) {
+            return cubes.subList(coffset, cubes.size());
+        }
+
+        return cubes.subList(coffset, coffset + climit);
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
+    public CubeInstance updateCubeCost(String cubeName, int cost) throws IOException {
+        CubeInstance cube = getCubeManager().getCube(cubeName);
+        if (cube == null) {
+            throw new IOException("Cannot find cube " + cubeName);
+        }
+        if (cube.getCost() == cost) {
+            // Do nothing
+            return cube;
+        }
+        cube.setCost(cost);
+
+        String owner = SecurityContextHolder.getContext().getAuthentication().getName();
+        cube.setOwner(owner);
+
+        CubeUpdate cubeBuilder = new CubeUpdate(cube).setOwner(owner).setCost(cost);
+
+        return getCubeManager().updateCube(cubeBuilder);
+    }
+
+    public CubeInstance createCubeAndDesc(String cubeName, String projectName, CubeDesc desc) throws IOException {
+        if (getCubeManager().getCube(cubeName) != null) {
+            throw new InternalErrorException("The cube named " + cubeName + " already exists");
+        }
+
+        if (getCubeDescManager().getCubeDesc(desc.getName()) != null) {
+            throw new InternalErrorException("The cube desc named " + desc.getName() + " already exists");
+        }
+
+        String owner = SecurityContextHolder.getContext().getAuthentication().getName();
+        CubeDesc createdDesc;
+        CubeInstance createdCube;
+
+        createdDesc = getCubeDescManager().createCubeDesc(desc);
+
+        if (!createdDesc.getError().isEmpty()) {
+            getCubeDescManager().removeCubeDesc(createdDesc);
+            throw new InternalErrorException(createdDesc.getError().get(0));
+        }
+
+        try {
+            int cuboidCount = CuboidCLI.simulateCuboidGeneration(createdDesc, false);
+            logger.info("New cube " + cubeName + " has " + cuboidCount + " cuboids");
+        } catch (Exception e) {
+            getCubeDescManager().removeCubeDesc(createdDesc);
+            throw new InternalErrorException("Failed to deal with the request.", e);
+        }
+
+        createdCube = getCubeManager().createCube(cubeName, projectName, createdDesc, owner);
+        accessService.init(createdCube, AclPermission.ADMINISTRATION);
+
+        ProjectInstance project = getProjectManager().getProject(projectName);
+        accessService.inherit(createdCube, project);
+
+        return createdCube;
+    }
+
+    public List<CubeInstance> listAllCubes(String projectName) {
+        ProjectManager projectManager = getProjectManager();
+        ProjectInstance project = projectManager.getProject(projectName);
+        if (project == null) {
+            return Collections.emptyList();
+        }
+        ArrayList<CubeInstance> result = new ArrayList<CubeInstance>();
+        for (RealizationEntry projectDataModel : project.getRealizationEntries()) {
+            if (projectDataModel.getType() == RealizationType.CUBE) {
+                CubeInstance cube = getCubeManager().getCube(projectDataModel.getRealization());
+                if (cube != null)
+                    result.add(cube);
+                else
+                    logger.error("Cube instance " + projectDataModel.getRealization() + " is failed to load");
+            }
+        }
+        return result;
+    }
+
+    private boolean isCubeInProject(String projectName, CubeInstance target) {
+        ProjectManager projectManager = getProjectManager();
+        ProjectInstance project = projectManager.getProject(projectName);
+        if (project == null) {
+            return false;
+        }
+        for (RealizationEntry projectDataModel : project.getRealizationEntries()) {
+            if (projectDataModel.getType() == RealizationType.CUBE) {
+                CubeInstance cube = getCubeManager().getCube(projectDataModel.getRealization());
+                if (cube == null) {
+                    logger.error("Project " + projectName + " contains realization " + projectDataModel.getRealization() + " which is not found by CubeManager");
+                    continue;
+                }
+                if (cube.equals(target)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'MANAGEMENT')")
+    public CubeDesc updateCubeAndDesc(CubeInstance cube, CubeDesc desc, String newProjectName, boolean forceUpdate) throws IOException, JobException {
+
+        final List<CubingJob> cubingJobs = listAllCubingJobs(cube.getName(), null, EnumSet.of(ExecutableState.READY, ExecutableState.RUNNING));
+        if (!cubingJobs.isEmpty()) {
+            throw new JobException("Cube schema shouldn't be changed with running job.");
+        }
+
+        try {
+            //double check again
+            if (!forceUpdate && !cube.getDescriptor().consistentWith(desc)) {
+                throw new IllegalStateException("cube's desc is not consistent with the new desc");
+            }
+
+            CubeDesc updatedCubeDesc = getCubeDescManager().updateCubeDesc(desc);
+            int cuboidCount = CuboidCLI.simulateCuboidGeneration(updatedCubeDesc, false);
+            logger.info("Updated cube " + cube.getName() + " has " + cuboidCount + " cuboids");
+
+            ProjectManager projectManager = getProjectManager();
+            if (!isCubeInProject(newProjectName, cube)) {
+                String owner = SecurityContextHolder.getContext().getAuthentication().getName();
+                ProjectInstance newProject = projectManager.moveRealizationToProject(RealizationType.CUBE, cube.getName(), newProjectName, owner);
+                accessService.inherit(cube, newProject);
+            }
+
+            return updatedCubeDesc;
+        } catch (IOException e) {
+            throw new InternalErrorException("Failed to deal with the request.", e);
+        }
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'MANAGEMENT')")
+    public void deleteCube(CubeInstance cube) throws IOException, JobException {
+        final List<CubingJob> cubingJobs = listAllCubingJobs(cube.getName(), null, EnumSet.of(ExecutableState.READY, ExecutableState.RUNNING));
+        if (!cubingJobs.isEmpty()) {
+            throw new JobException("The cube " + cube.getName() + " has running job, please discard it and try again.");
+        }
+
+        this.releaseAllSegments(cube);
+        getCubeManager().dropCube(cube.getName(), true);
+        accessService.clean(cube, true);
+    }
+
+    public boolean isCubeDescFreeEditable(CubeDesc cd) {
+        List<CubeInstance> cubes = getCubeManager().getCubesByDesc(cd.getName());
+        for (CubeInstance cube : cubes) {
+            if (cube.getSegments().size() != 0) {
+                logger.debug("cube '" + cube.getName() + " has " + cube.getSegments().size() + " segments, couldn't edit cube desc.");
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public static String getCubeDescNameFromCube(String cubeName) {
+        return cubeName + DESC_SUFFIX;
+    }
+
+    public static String getCubeNameFromDesc(String descName) {
+        if (descName.toLowerCase().endsWith(DESC_SUFFIX)) {
+            return descName.substring(0, descName.toLowerCase().indexOf(DESC_SUFFIX));
+        } else {
+            return descName;
+        }
+    }
+
+    /**
+     * Stop all jobs belonging to this cube and clean out all segments
+     *
+     * @param cube
+     * @return
+     * @throws IOException
+     * @throws JobException
+     */
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'OPERATION') or hasPermission(#cube, 'MANAGEMENT')")
+    public CubeInstance purgeCube(CubeInstance cube) throws IOException, JobException {
+
+        String cubeName = cube.getName();
+        RealizationStatusEnum ostatus = cube.getStatus();
+        if (null != ostatus && !RealizationStatusEnum.DISABLED.equals(ostatus)) {
+            throw new InternalErrorException("Only disabled cube can be purged, status of " + cubeName + " is " + ostatus);
+        }
+
+        try {
+            this.releaseAllSegments(cube);
+            return cube;
+        } catch (IOException e) {
+            throw e;
+        }
+
+    }
+
+    /**
+     * Update a cube status from ready to disabled.
+     *
+     * @return
+     * @throws IOException
+     * @throws JobException
+     */
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'OPERATION') or hasPermission(#cube, 'MANAGEMENT')")
+    public CubeInstance disableCube(CubeInstance cube) throws IOException, JobException {
+
+        String cubeName = cube.getName();
+
+        RealizationStatusEnum ostatus = cube.getStatus();
+        if (null != ostatus && !RealizationStatusEnum.READY.equals(ostatus)) {
+            throw new InternalErrorException("Only ready cube can be disabled, status of " + cubeName + " is " + ostatus);
+        }
+
+        cube.setStatus(RealizationStatusEnum.DISABLED);
+
+        try {
+            CubeUpdate cubeBuilder = new CubeUpdate(cube);
+            cubeBuilder.setStatus(RealizationStatusEnum.DISABLED);
+            return getCubeManager().updateCube(cubeBuilder);
+        } catch (IOException e) {
+            cube.setStatus(ostatus);
+            throw e;
+        }
+    }
+
+    /**
+     * Update a cube status from disable to ready.
+     *
+     * @return
+     * @throws IOException
+     * @throws JobException
+     */
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'OPERATION')  or hasPermission(#cube, 'MANAGEMENT')")
+    public CubeInstance enableCube(CubeInstance cube) throws IOException, JobException {
+        String cubeName = cube.getName();
+
+        RealizationStatusEnum ostatus = cube.getStatus();
+        if (!cube.getStatus().equals(RealizationStatusEnum.DISABLED)) {
+            throw new InternalErrorException("Only disabled cube can be enabled, status of " + cubeName + " is " + ostatus);
+        }
+
+        if (cube.getSegments(SegmentStatusEnum.READY).size() == 0) {
+            throw new InternalErrorException("Cube " + cubeName + " dosen't contain any READY segment");
+        }
+
+        final List<CubingJob> cubingJobs = listAllCubingJobs(cube.getName(), null, EnumSet.of(ExecutableState.READY, ExecutableState.RUNNING));
+        if (!cubingJobs.isEmpty()) {
+            throw new JobException("Enable is not allowed with a running job.");
+        }
+        if (!cube.getDescriptor().checkSignature()) {
+            throw new IllegalStateException("Inconsistent cube desc signature for " + cube.getDescriptor());
+        }
+
+        try {
+            CubeUpdate cubeBuilder = new CubeUpdate(cube);
+            cubeBuilder.setStatus(RealizationStatusEnum.READY);
+            return getCubeManager().updateCube(cubeBuilder);
+        } catch (IOException e) {
+            cube.setStatus(ostatus);
+            throw e;
+        }
+    }
+
+    public MetricsResponse calculateMetrics(MetricsRequest request) {
+        List<CubeInstance> cubes = this.getCubeManager().listAllCubes();
+        MetricsResponse metrics = new MetricsResponse();
+        Date startTime = (null == request.getStartTime()) ? new Date(-1) : request.getStartTime();
+        Date endTime = (null == request.getEndTime()) ? new Date() : request.getEndTime();
+        metrics.increase("totalCubes", (float) 0);
+        metrics.increase("totalStorage", (float) 0);
+
+        for (CubeInstance cube : cubes) {
+            Date createdDate = new Date(-1);
+            createdDate = (cube.getCreateTimeUTC() == 0) ? createdDate : new Date(cube.getCreateTimeUTC());
+
+            if (createdDate.getTime() > startTime.getTime() && createdDate.getTime() < endTime.getTime()) {
+                metrics.increase("totalCubes");
+            }
+        }
+
+        metrics.increase("aveStorage", (metrics.get("totalCubes") == 0) ? 0 : metrics.get("totalStorage") / metrics.get("totalCubes"));
+
+        return metrics;
+    }
+
+    /**
+     * Calculate size of each region for given table and other info of the
+     * table.
+     *
+     * @param tableName The table name.
+     * @return The HBaseResponse object contains table size, region count. null
+     * if error happens.
+     * @throws IOException Exception when HTable resource is not closed correctly.
+     */
+    public HBaseResponse getHTableInfo(String tableName) throws IOException {
+        if (htableInfoCache.containsKey(tableName)) {
+            return htableInfoCache.get(tableName);
+        }
+
+        Configuration hconf = HBaseConnection.getCurrentHBaseConfiguration();
+        HTable table = null;
+        HBaseResponse hr = null;
+        long tableSize = 0;
+        int regionCount = 0;
+
+        try {
+            table = new HTable(hconf, tableName);
+
+            HBaseRegionSizeCalculator cal = new HBaseRegionSizeCalculator(table);
+            Map<byte[], Long> sizeMap = cal.getRegionSizeMap();
+
+            for (long s : sizeMap.values()) {
+                tableSize += s;
+            }
+
+            regionCount = sizeMap.size();
+
+            // Set response.
+            hr = new HBaseResponse();
+            hr.setTableSize(tableSize);
+            hr.setRegionCount(regionCount);
+        } finally {
+            if (null != table) {
+                table.close();
+            }
+        }
+
+        htableInfoCache.put(tableName, hr);
+
+        return hr;
+    }
+
+    /**
+     * Generate cardinality for table This will trigger a hadoop job
+     * The result will be merged into table exd info
+     *
+     * @param tableName
+     */
+    public void calculateCardinality(String tableName, String submitter) {
+        String[] dbTableName = HadoopUtil.parseHiveTableName(tableName);
+        tableName = dbTableName[0] + "." + dbTableName[1];
+        TableDesc table = getMetadataManager().getTableDesc(tableName);
+        final Map<String, String> tableExd = getMetadataManager().getTableDescExd(tableName);
+        if (tableExd == null || table == null) {
+            IllegalArgumentException e = new IllegalArgumentException("Cannot find table descirptor " + tableName);
+            logger.error("Cannot find table descirptor " + tableName, e);
+            throw e;
+        }
+
+        DefaultChainedExecutable job = new DefaultChainedExecutable();
+        job.setName("Hive Column Cardinality calculation for table '" + tableName + "'");
+        job.setSubmitter(submitter);
+
+        String outPath = HiveColumnCardinalityJob.OUTPUT_PATH + "/" + tableName;
+        String param = "-table " + tableName + " -output " + outPath;
+
+        MapReduceExecutable step1 = new MapReduceExecutable();
+
+        step1.setMapReduceJobClass(HiveColumnCardinalityJob.class);
+        step1.setMapReduceParams(param);
+
+        job.addTask(step1);
+
+        HadoopShellExecutable step2 = new HadoopShellExecutable();
+
+        step2.setJobClass(HiveColumnCardinalityUpdateJob.class);
+        step2.setJobParams(param);
+        job.addTask(step2);
+
+        getExecutableManager().addJob(job);
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'OPERATION')  or hasPermission(#cube, 'MANAGEMENT')")
+    public void updateCubeNotifyList(CubeInstance cube, List<String> notifyList) throws IOException {
+        CubeDesc desc = cube.getDescriptor();
+        desc.setNotifyList(notifyList);
+        getCubeDescManager().updateCubeDesc(desc);
+    }
+
+    public CubeInstance rebuildLookupSnapshot(String cubeName, String segmentName, String lookupTable) throws IOException {
+        CubeManager cubeMgr = getCubeManager();
+        CubeInstance cube = cubeMgr.getCube(cubeName);
+        CubeSegment seg = cube.getSegment(segmentName, SegmentStatusEnum.READY);
+        cubeMgr.buildSnapshotTable(seg, lookupTable);
+
+        return cube;
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'OPERATION')  or hasPermission(#cube, 'MANAGEMENT')")
+    public CubeInstance deleteSegment(CubeInstance cube, String segmentName) throws IOException {
+
+        if (!segmentName.equals(cube.getSegments().get(0).getName()) && !segmentName.equals(cube.getSegments().get(cube.getSegments().size() - 1).getName())) {
+            throw new IllegalArgumentException("Cannot delete segment '" + segmentName + "' as it is neither the first nor the last segment.");
+        }
+        CubeSegment toDelete = null;
+        for (CubeSegment seg : cube.getSegments()) {
+            if (seg.getName().equals(segmentName)) {
+                toDelete = seg;
+            }
+        }
+
+        if (toDelete.getStatus() != SegmentStatusEnum.READY) {
+            throw new IllegalArgumentException("Cannot delete segment '" + segmentName + "' as its status is not READY. Discard the on-going job for it.");
+        }
+
+        CubeUpdate update = new CubeUpdate(cube);
+        update.setToRemoveSegs(new CubeSegment[] { toDelete });
+        return CubeManager.getInstance(getConfig()).updateCube(update);
+    }
+
+    /**
+     * purge the cube
+     *
+     * @throws IOException
+     * @throws JobException
+     */
+    private CubeInstance releaseAllSegments(CubeInstance cube) throws IOException, JobException {
+        final List<CubingJob> cubingJobs = listAllCubingJobs(cube.getName(), null);
+        for (CubingJob cubingJob : cubingJobs) {
+            final ExecutableState status = cubingJob.getStatus();
+            if (status != ExecutableState.SUCCEED && status != ExecutableState.STOPPED && status != ExecutableState.DISCARDED) {
+                getExecutableManager().discardJob(cubingJob.getId());
+            }
+        }
+        CubeUpdate update = new CubeUpdate(cube);
+        update.setToRemoveSegs(cube.getSegments().toArray(new CubeSegment[cube.getSegments().size()]));
+        return CubeManager.getInstance(getConfig()).updateCube(update);
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_MODELER + " or " + Constant.ACCESS_HAS_ROLE_ADMIN)
+    public String[] reloadHiveTable(String tables) throws IOException {
+        Set<String> loaded = HiveSourceTableLoader.reloadHiveTables(tables.split(","), getConfig());
+        return (String[]) loaded.toArray(new String[loaded.size()]);
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
+    public void unLoadHiveTable(String tableName) throws IOException {
+        String[] dbTableName = HadoopUtil.parseHiveTableName(tableName);
+        tableName = dbTableName[0] + "." + dbTableName[1];
+        HiveSourceTableLoader.unLoadHiveTable(tableName.toUpperCase());
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
+    public void syncTableToProject(String[] tables, String project) throws IOException {
+        getProjectManager().addTableDescToProject(tables, project);
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
+    public void removeTableFromProject(String tableName, String projectName) throws IOException {
+        String[] dbTableName = HadoopUtil.parseHiveTableName(tableName);
+        tableName = dbTableName[0] + "." + dbTableName[1];
+        getProjectManager().removeTableDescFromProject(tableName, projectName);
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_MODELER + " or " + Constant.ACCESS_HAS_ROLE_ADMIN)
+    public void calculateCardinalityIfNotPresent(String[] tables, String submitter) throws IOException {
+        MetadataManager metaMgr = getMetadataManager();
+        for (String table : tables) {
+            Map<String, String> exdMap = metaMgr.getTableDescExd(table);
+            if (exdMap == null || !exdMap.containsKey(MetadataConstants.TABLE_EXD_CARDINALITY)) {
+                calculateCardinality(table, submitter);
+            }
+        }
+    }
+
+    public void updateOnNewSegmentReady(String cubeName) {
+        logger.debug("on updateOnNewSegmentReady: " + cubeName);
+        final KylinConfig kylinConfig = KylinConfig.getInstanceFromEnv();
+        String serverMode = kylinConfig.getServerMode();
+        logger.debug("server mode: " + serverMode);
+        if (Constant.SERVER_MODE_JOB.equals(serverMode.toLowerCase()) || Constant.SERVER_MODE_ALL.equals(serverMode.toLowerCase())) {
+            keepCubeRetention(cubeName);
+            mergeCubeSegment(cubeName);
+        }
+
+    }
+
+    private void keepCubeRetention(String cubeName) {
+        logger.info("checking keepCubeRetention");
+        CubeInstance cube = getCubeManager().getCube(cubeName);
+        CubeDesc desc = cube.getDescriptor();
+        if (desc.getRetentionRange() <= 0)
+            return;
+
+        synchronized (CubeService.class) {
+            cube = getCubeManager().getCube(cubeName);
+            List<CubeSegment> readySegs = cube.getSegments(SegmentStatusEnum.READY);
+            if (readySegs.isEmpty())
+                return;
+
+            List<CubeSegment> toRemoveSegs = Lists.newArrayList();
+            long tail = readySegs.get(readySegs.size() - 1).getDateRangeEnd();
+            long head = tail - desc.getRetentionRange();
+            for (CubeSegment seg : readySegs) {
+                if (seg.getDateRangeEnd() <= head)
+                    toRemoveSegs.add(seg);
+            }
+
+            if (toRemoveSegs.size() > 0) {
+                CubeUpdate cubeBuilder = new CubeUpdate(cube);
+                cubeBuilder.setToRemoveSegs(toRemoveSegs.toArray(new CubeSegment[toRemoveSegs.size()]));
+                try {
+                    this.getCubeManager().updateCube(cubeBuilder);
+                } catch (IOException e) {
+                    logger.error("Failed to remove old segment from cube " + cubeName, e);
+                }
+            }
+        }
+    }
+
+    private void mergeCubeSegment(String cubeName) {
+        CubeInstance cube = getCubeManager().getCube(cubeName);
+        if (!cube.needAutoMerge())
+            return;
+
+        synchronized (CubeService.class) {
+            try {
+                cube = getCubeManager().getCube(cubeName);
+                Pair<Long, Long> offsets = getCubeManager().autoMergeCubeSegments(cube);
+                if (offsets != null) {
+                    CubeSegment newSeg = getCubeManager().mergeSegments(cube, 0, 0, offsets.getFirst(), offsets.getSecond(), true);
+                    logger.debug("Will submit merge job on " + newSeg);
+                    DefaultChainedExecutable job = EngineFactory.createBatchMergeJob(newSeg, "SYSTEM");
+                    getExecutableManager().addJob(job);
+                } else {
+                    logger.debug("Not ready for merge on cube " + cubeName);
+                }
+            } catch (IOException e) {
+                logger.error("Failed to auto merge cube " + cubeName, e);
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/service/DiagnosisService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/DiagnosisService.java b/server-base/src/main/java/org/apache/kylin/rest/service/DiagnosisService.java
new file mode 100644
index 0000000..ba51ea1
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/DiagnosisService.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.service;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.apache.kylin.metadata.badquery.BadQueryHistory;
+import org.apache.kylin.rest.constant.Constant;
+import org.apache.kylin.tool.DiagnosisInfoCLI;
+import org.apache.kylin.tool.JobDiagnosisInfoCLI;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+import com.google.common.io.Files;
+
+@Component("diagnosisService")
+public class DiagnosisService extends BasicService {
+
+    private static final Logger logger = LoggerFactory.getLogger(DiagnosisService.class);
+
+    private File getDumpDir() {
+        return Files.createTempDir();
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
+    public BadQueryHistory getProjectBadQueryHistory(String project) throws IOException {
+        return getBadQueryHistoryManager().getBadQueriesForProject(project);
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
+    public String dumpProjectDiagnosisInfo(String project) throws IOException {
+        String[] args = { "-project", "-all", "-destDir", getDumpDir().getAbsolutePath() };
+        logger.info("DiagnosisInfoCLI args: " + Arrays.toString(args));
+        DiagnosisInfoCLI diagnosisInfoCli = new DiagnosisInfoCLI();
+        diagnosisInfoCli.execute(args);
+        return diagnosisInfoCli.getExportDest();
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
+    public String dumpJobDiagnosisInfo(String jobId) throws IOException {
+        String[] args = { "-jobId", jobId, "-destDir", getDumpDir().getAbsolutePath() };
+        logger.info("JobDiagnosisInfoCLI args: " + Arrays.toString(args));
+        JobDiagnosisInfoCLI jobInfoExtractor = new JobDiagnosisInfoCLI();
+        jobInfoExtractor.execute(args);
+        return jobInfoExtractor.getExportDest();
+    }
+
+    public static void main(String[] args1) {
+        String[] args = { "-project", "-all", "-destDir", Files.createTempDir().getAbsolutePath() };
+        logger.info("DiagnosisInfoCLI args: " + Arrays.toString(args));
+        DiagnosisInfoCLI diagnosisInfoCli = new DiagnosisInfoCLI();
+        diagnosisInfoCli.execute(args);
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/service/ExtFilterService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/ExtFilterService.java b/server-base/src/main/java/org/apache/kylin/rest/service/ExtFilterService.java
new file mode 100644
index 0000000..0c98965
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/ExtFilterService.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.service;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.kylin.metadata.model.ExternalFilterDesc;
+import org.apache.kylin.rest.constant.Constant;
+import org.apache.kylin.rest.exception.InternalErrorException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component("extFilterService")
+public class ExtFilterService extends BasicService {
+    private static final Logger logger = LoggerFactory.getLogger(ExtFilterService.class);
+
+    @Autowired
+    private AccessService accessService;
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
+    public void saveExternalFilter(ExternalFilterDesc desc) throws IOException {
+        if (getMetadataManager().getExtFilterDesc(desc.getName()) != null) {
+            throw new InternalErrorException("The filter named " + desc.getName() + " already exists");
+        }
+        getMetadataManager().saveExternalFilter(desc);
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
+    public void updateExternalFilter(ExternalFilterDesc desc) throws IOException {
+        if (getMetadataManager().getExtFilterDesc(desc.getName()) == null) {
+            throw new InternalErrorException("The filter named " + desc.getName() + " does not exists");
+        }
+        getMetadataManager().saveExternalFilter(desc);
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
+    public void removeExternalFilter(String name) throws IOException {
+        getMetadataManager().removeExternalFilter(name);
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
+    public void syncExtFilterToProject(String[] filters, String project) throws IOException {
+        getProjectManager().addExtFilterToProject(filters, project);
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
+    public void removeExtFilterFromProject(String filterName, String projectName) throws IOException {
+        getProjectManager().removeExtFilterFromProject(filterName, projectName);
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
+    public List<ExternalFilterDesc> listAllExternalFilters() {
+        return getMetadataManager().listAllExternalFilters();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/service/JobService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/JobService.java b/server-base/src/main/java/org/apache/kylin/rest/service/JobService.java
new file mode 100644
index 0000000..c868264
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/JobService.java
@@ -0,0 +1,388 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.service;
+
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.kylin.cube.CubeInstance;
+import org.apache.kylin.cube.CubeSegment;
+import org.apache.kylin.cube.CubeUpdate;
+import org.apache.kylin.cube.model.CubeBuildTypeEnum;
+import org.apache.kylin.engine.EngineFactory;
+import org.apache.kylin.engine.mr.CubingJob;
+import org.apache.kylin.engine.mr.common.HadoopShellExecutable;
+import org.apache.kylin.engine.mr.common.MapReduceExecutable;
+import org.apache.kylin.engine.mr.steps.CubingExecutableUtil;
+import org.apache.kylin.job.JobInstance;
+import org.apache.kylin.job.common.ShellExecutable;
+import org.apache.kylin.job.constant.JobStatusEnum;
+import org.apache.kylin.job.constant.JobStepStatusEnum;
+import org.apache.kylin.job.constant.JobTimeFilterEnum;
+import org.apache.kylin.job.exception.JobException;
+import org.apache.kylin.job.execution.AbstractExecutable;
+import org.apache.kylin.job.execution.DefaultChainedExecutable;
+import org.apache.kylin.job.execution.ExecutableState;
+import org.apache.kylin.job.execution.Output;
+import org.apache.kylin.metadata.model.SegmentStatusEnum;
+import org.apache.kylin.rest.constant.Constant;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+/**
+ * @author ysong1
+ */
+@Component("jobService")
+public class JobService extends BasicService {
+
+    @SuppressWarnings("unused")
+    private static final Logger logger = LoggerFactory.getLogger(JobService.class);
+
+    @Autowired
+    private AccessService accessService;
+
+    public List<JobInstance> listAllJobs(final String cubeName, final String projectName, final List<JobStatusEnum> statusList, final Integer limitValue, final Integer offsetValue, final JobTimeFilterEnum timeFilter) throws IOException, JobException {
+        Integer limit = (null == limitValue) ? 30 : limitValue;
+        Integer offset = (null == offsetValue) ? 0 : offsetValue;
+        List<JobInstance> jobs = listAllJobs(cubeName, projectName, statusList, timeFilter);
+        Collections.sort(jobs);
+
+        if (jobs.size() <= offset) {
+            return Collections.emptyList();
+        }
+
+        if ((jobs.size() - offset) < limit) {
+            return jobs.subList(offset, jobs.size());
+        }
+
+        return jobs.subList(offset, offset + limit);
+    }
+
+    public List<JobInstance> listAllJobs(final String cubeName, final String projectName, final List<JobStatusEnum> statusList, final JobTimeFilterEnum timeFilter) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(new Date());
+        long currentTimeMillis = calendar.getTimeInMillis();
+        long timeStartInMillis = getTimeStartInMillis(calendar, timeFilter);
+        return listCubeJobInstance(cubeName, projectName, statusList, timeStartInMillis, currentTimeMillis);
+    }
+
+    @Deprecated
+    public List<JobInstance> listAllJobs(final String cubeName, final String projectName, final List<JobStatusEnum> statusList, final Integer limitValue, final Integer offsetValue) throws IOException, JobException {
+        Integer limit = (null == limitValue) ? 30 : limitValue;
+        Integer offset = (null == offsetValue) ? 0 : offsetValue;
+        List<JobInstance> jobs = listAllJobs(cubeName, projectName, statusList);
+        Collections.sort(jobs);
+
+        if (jobs.size() <= offset) {
+            return Collections.emptyList();
+        }
+
+        if ((jobs.size() - offset) < limit) {
+            return jobs.subList(offset, jobs.size());
+        }
+
+        return jobs.subList(offset, offset + limit);
+    }
+
+    public List<JobInstance> listAllJobs(final String cubeName, final String projectName, final List<JobStatusEnum> statusList) {
+        return listCubeJobInstance(cubeName, projectName, statusList);
+    }
+
+    private List<JobInstance> listCubeJobInstance(final String cubeName, final String projectName, List<JobStatusEnum> statusList, final long timeStartInMillis, final long timeEndInMillis) {
+        Set<ExecutableState> states = convertStatusEnumToStates(statusList);
+        final Map<String, Output> allOutputs = getExecutableManager().getAllOutputs(timeStartInMillis, timeEndInMillis);
+        return Lists.newArrayList(FluentIterable.from(listAllCubingJobs(cubeName, projectName, states, timeStartInMillis, timeEndInMillis, allOutputs)).transform(new Function<CubingJob, JobInstance>() {
+            @Override
+            public JobInstance apply(CubingJob cubingJob) {
+                return parseToJobInstance(cubingJob, allOutputs);
+            }
+        }));
+    }
+
+    private List<JobInstance> listCubeJobInstance(final String cubeName, final String projectName, List<JobStatusEnum> statusList) {
+        Set<ExecutableState> states = convertStatusEnumToStates(statusList);
+        final Map<String, Output> allOutputs = getExecutableManager().getAllOutputs();
+        return Lists.newArrayList(FluentIterable.from(listAllCubingJobs(cubeName, projectName, states, allOutputs)).transform(new Function<CubingJob, JobInstance>() {
+            @Override
+            public JobInstance apply(CubingJob cubingJob) {
+                return parseToJobInstance(cubingJob, allOutputs);
+            }
+        }));
+    }
+
+    private Set<ExecutableState> convertStatusEnumToStates(List<JobStatusEnum> statusList) {
+        Set<ExecutableState> states;
+        if (statusList == null || statusList.isEmpty()) {
+            states = EnumSet.allOf(ExecutableState.class);
+        } else {
+            states = Sets.newHashSet();
+            for (JobStatusEnum status : statusList) {
+                states.add(parseToExecutableState(status));
+            }
+        }
+        return states;
+    }
+
+    private long getTimeStartInMillis(Calendar calendar, JobTimeFilterEnum timeFilter) {
+        switch (timeFilter) {
+        case LAST_ONE_DAY:
+            calendar.add(Calendar.DAY_OF_MONTH, -1);
+            return calendar.getTimeInMillis();
+        case LAST_ONE_WEEK:
+            calendar.add(Calendar.WEEK_OF_MONTH, -1);
+            return calendar.getTimeInMillis();
+        case LAST_ONE_MONTH:
+            calendar.add(Calendar.MONTH, -1);
+            return calendar.getTimeInMillis();
+        case LAST_ONE_YEAR:
+            calendar.add(Calendar.YEAR, -1);
+            return calendar.getTimeInMillis();
+        case ALL:
+            return 0;
+        default:
+            throw new RuntimeException("illegal timeFilter for job history:" + timeFilter);
+        }
+    }
+
+    private ExecutableState parseToExecutableState(JobStatusEnum status) {
+        switch (status) {
+        case DISCARDED:
+            return ExecutableState.DISCARDED;
+        case ERROR:
+            return ExecutableState.ERROR;
+        case FINISHED:
+            return ExecutableState.SUCCEED;
+        case NEW:
+            return ExecutableState.READY;
+        case PENDING:
+            return ExecutableState.READY;
+        case RUNNING:
+            return ExecutableState.RUNNING;
+        default:
+            throw new RuntimeException("illegal status:" + status);
+        }
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'OPERATION') or hasPermission(#cube, 'MANAGEMENT')")
+    public JobInstance submitJob(CubeInstance cube, long startDate, long endDate, long startOffset, long endOffset, //
+            CubeBuildTypeEnum buildType, boolean force, String submitter) throws IOException, JobException {
+
+        checkCubeDescSignature(cube);
+        checkNoRunningJob(cube);
+
+        DefaultChainedExecutable job;
+
+        if (buildType == CubeBuildTypeEnum.BUILD) {
+            CubeSegment newSeg = getCubeManager().appendSegment(cube, startDate, endDate, startOffset, endOffset);
+            job = EngineFactory.createBatchCubingJob(newSeg, submitter);
+        } else if (buildType == CubeBuildTypeEnum.MERGE) {
+            CubeSegment newSeg = getCubeManager().mergeSegments(cube, startDate, endDate, startOffset, endOffset, force);
+            job = EngineFactory.createBatchMergeJob(newSeg, submitter);
+        } else if (buildType == CubeBuildTypeEnum.REFRESH) {
+            CubeSegment refreshSeg = getCubeManager().refreshSegment(cube, startDate, endDate, startOffset, endOffset);
+            job = EngineFactory.createBatchCubingJob(refreshSeg, submitter);
+        } else {
+            throw new JobException("invalid build type:" + buildType);
+        }
+        getExecutableManager().addJob(job);
+        JobInstance jobInstance = getSingleJobInstance(job);
+
+        accessService.init(jobInstance, null);
+        accessService.inherit(jobInstance, cube);
+
+        return jobInstance;
+    }
+
+    private void checkCubeDescSignature(CubeInstance cube) {
+        if (!cube.getDescriptor().checkSignature())
+            throw new IllegalStateException("Inconsistent cube desc signature for " + cube.getDescriptor());
+    }
+
+    private void checkNoRunningJob(CubeInstance cube) throws JobException {
+        final List<CubingJob> cubingJobs = listAllCubingJobs(cube.getName(), null, EnumSet.allOf(ExecutableState.class));
+        for (CubingJob job : cubingJobs) {
+            if (job.getStatus() == ExecutableState.READY || job.getStatus() == ExecutableState.RUNNING || job.getStatus() == ExecutableState.ERROR) {
+                throw new JobException("The cube " + cube.getName() + " has running job(" + job.getId() + ") please discard it and try again.");
+            }
+        }
+    }
+
+    public JobInstance getJobInstance(String uuid) throws IOException, JobException {
+        return getSingleJobInstance(getExecutableManager().getJob(uuid));
+    }
+
+    public Output getOutput(String id) {
+        return getExecutableManager().getOutput(id);
+    }
+
+    private JobInstance getSingleJobInstance(AbstractExecutable job) {
+        if (job == null) {
+            return null;
+        }
+        Preconditions.checkState(job instanceof CubingJob, "illegal job type, id:" + job.getId());
+        CubingJob cubeJob = (CubingJob) job;
+        final JobInstance result = new JobInstance();
+        result.setName(job.getName());
+        result.setRelatedCube(CubingExecutableUtil.getCubeName(cubeJob.getParams()));
+        result.setRelatedSegment(CubingExecutableUtil.getSegmentId(cubeJob.getParams()));
+        result.setLastModified(cubeJob.getLastModified());
+        result.setSubmitter(cubeJob.getSubmitter());
+        result.setUuid(cubeJob.getId());
+        result.setType(CubeBuildTypeEnum.BUILD);
+        result.setStatus(parseToJobStatus(job.getStatus()));
+        result.setMrWaiting(cubeJob.getMapReduceWaitTime() / 1000);
+        result.setDuration(cubeJob.getDuration() / 1000);
+        for (int i = 0; i < cubeJob.getTasks().size(); ++i) {
+            AbstractExecutable task = cubeJob.getTasks().get(i);
+            result.addStep(parseToJobStep(task, i, getExecutableManager().getOutput(task.getId())));
+        }
+        return result;
+    }
+
+    private JobInstance parseToJobInstance(AbstractExecutable job, Map<String, Output> outputs) {
+        if (job == null) {
+            return null;
+        }
+        Preconditions.checkState(job instanceof CubingJob, "illegal job type, id:" + job.getId());
+        CubingJob cubeJob = (CubingJob) job;
+        Output output = outputs.get(job.getId());
+        final JobInstance result = new JobInstance();
+        result.setName(job.getName());
+        result.setRelatedCube(CubingExecutableUtil.getCubeName(cubeJob.getParams()));
+        result.setRelatedSegment(CubingExecutableUtil.getSegmentId(cubeJob.getParams()));
+        result.setLastModified(output.getLastModified());
+        result.setSubmitter(cubeJob.getSubmitter());
+        result.setUuid(cubeJob.getId());
+        result.setType(CubeBuildTypeEnum.BUILD);
+        result.setStatus(parseToJobStatus(output.getState()));
+        result.setMrWaiting(AbstractExecutable.getExtraInfoAsLong(output, CubingJob.MAP_REDUCE_WAIT_TIME, 0L) / 1000);
+        result.setDuration(AbstractExecutable.getDuration(AbstractExecutable.getStartTime(output), AbstractExecutable.getEndTime(output)) / 1000);
+        for (int i = 0; i < cubeJob.getTasks().size(); ++i) {
+            AbstractExecutable task = cubeJob.getTasks().get(i);
+            result.addStep(parseToJobStep(task, i, outputs.get(task.getId())));
+        }
+        return result;
+    }
+
+    private JobInstance.JobStep parseToJobStep(AbstractExecutable task, int i, Output stepOutput) {
+        Preconditions.checkNotNull(stepOutput);
+        JobInstance.JobStep result = new JobInstance.JobStep();
+        result.setId(task.getId());
+        result.setName(task.getName());
+        result.setSequenceID(i);
+        result.setStatus(parseToJobStepStatus(stepOutput.getState()));
+        for (Map.Entry<String, String> entry : stepOutput.getExtra().entrySet()) {
+            if (entry.getKey() != null && entry.getValue() != null) {
+                result.putInfo(entry.getKey(), entry.getValue());
+            }
+        }
+        result.setExecStartTime(AbstractExecutable.getStartTime(stepOutput));
+        result.setExecEndTime(AbstractExecutable.getEndTime(stepOutput));
+        if (task instanceof ShellExecutable) {
+            result.setExecCmd(((ShellExecutable) task).getCmd());
+        }
+        if (task instanceof MapReduceExecutable) {
+            result.setExecCmd(((MapReduceExecutable) task).getMapReduceParams());
+            result.setExecWaitTime(AbstractExecutable.getExtraInfoAsLong(stepOutput, MapReduceExecutable.MAP_REDUCE_WAIT_TIME, 0L) / 1000);
+        }
+        if (task instanceof HadoopShellExecutable) {
+            result.setExecCmd(((HadoopShellExecutable) task).getJobParams());
+        }
+        return result;
+    }
+
+    private JobStatusEnum parseToJobStatus(ExecutableState state) {
+        switch (state) {
+        case READY:
+            return JobStatusEnum.PENDING;
+        case RUNNING:
+            return JobStatusEnum.RUNNING;
+        case ERROR:
+            return JobStatusEnum.ERROR;
+        case DISCARDED:
+            return JobStatusEnum.DISCARDED;
+        case SUCCEED:
+            return JobStatusEnum.FINISHED;
+        case STOPPED:
+        default:
+            throw new RuntimeException("invalid state:" + state);
+        }
+    }
+
+    private JobStepStatusEnum parseToJobStepStatus(ExecutableState state) {
+        switch (state) {
+        case READY:
+            return JobStepStatusEnum.PENDING;
+        case RUNNING:
+            return JobStepStatusEnum.RUNNING;
+        case ERROR:
+            return JobStepStatusEnum.ERROR;
+        case DISCARDED:
+            return JobStepStatusEnum.DISCARDED;
+        case SUCCEED:
+            return JobStepStatusEnum.FINISHED;
+        case STOPPED:
+        default:
+            throw new RuntimeException("invalid state:" + state);
+        }
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#job, 'ADMINISTRATION') or hasPermission(#job, 'OPERATION') or hasPermission(#job, 'MANAGEMENT')")
+    public void resumeJob(JobInstance job) throws IOException, JobException {
+        getExecutableManager().resumeJob(job.getId());
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#job, 'ADMINISTRATION') or hasPermission(#job, 'OPERATION') or hasPermission(#job, 'MANAGEMENT')")
+    public JobInstance cancelJob(JobInstance job) throws IOException, JobException {
+        //        CubeInstance cube = this.getCubeManager().getCube(job.getRelatedCube());
+        //        for (BuildCubeJob cubeJob: listAllCubingJobs(cube.getName(), null, EnumSet.of(ExecutableState.READY, ExecutableState.RUNNING))) {
+        //            getExecutableManager().stopJob(cubeJob.getId());
+        //        }
+        CubeInstance cubeInstance = getCubeManager().getCube(job.getRelatedCube());
+        final String segmentIds = job.getRelatedSegment();
+        for (String segmentId : StringUtils.split(segmentIds)) {
+            final CubeSegment segment = cubeInstance.getSegmentById(segmentId);
+            if (segment != null && segment.getStatus() == SegmentStatusEnum.NEW) {
+                // Remove this segments
+                CubeUpdate cubeBuilder = new CubeUpdate(cubeInstance);
+                cubeBuilder.setToRemoveSegs(segment);
+                getCubeManager().updateCube(cubeBuilder);
+            }
+        }
+        getExecutableManager().discardJob(job.getId());
+        return job;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/service/KafkaConfigService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/KafkaConfigService.java b/server-base/src/main/java/org/apache/kylin/rest/service/KafkaConfigService.java
new file mode 100644
index 0000000..1f286e3
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/KafkaConfigService.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.service;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.kylin.rest.constant.Constant;
+import org.apache.kylin.rest.exception.InternalErrorException;
+import org.apache.kylin.source.kafka.config.KafkaConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PostFilter;
+import org.springframework.stereotype.Component;
+
+@Component("kafkaMgmtService")
+public class KafkaConfigService extends BasicService {
+
+    @Autowired
+    private AccessService accessService;
+
+    @PostFilter(Constant.ACCESS_POST_FILTER_READ)
+    public List<KafkaConfig> listAllKafkaConfigs(final String kafkaConfigName) throws IOException {
+        List<KafkaConfig> kafkaConfigs = new ArrayList<KafkaConfig>();
+        //        CubeInstance cubeInstance = (null != cubeName) ? getCubeManager().getCube(cubeName) : null;
+        if (null == kafkaConfigName) {
+            kafkaConfigs = getKafkaManager().listAllKafkaConfigs();
+        } else {
+            List<KafkaConfig> configs = getKafkaManager().listAllKafkaConfigs();
+            for (KafkaConfig config : configs) {
+                if (kafkaConfigName.equals(config.getName())) {
+                    kafkaConfigs.add(config);
+                }
+            }
+        }
+
+        return kafkaConfigs;
+    }
+
+    public List<KafkaConfig> getKafkaConfigs(final String kafkaConfigName, final Integer limit, final Integer offset) throws IOException {
+
+        List<KafkaConfig> kafkaConfigs;
+        kafkaConfigs = listAllKafkaConfigs(kafkaConfigName);
+
+        if (limit == null || offset == null) {
+            return kafkaConfigs;
+        }
+
+        if ((kafkaConfigs.size() - offset) < limit) {
+            return kafkaConfigs.subList(offset, kafkaConfigs.size());
+        }
+
+        return kafkaConfigs.subList(offset, offset + limit);
+    }
+
+    public KafkaConfig createKafkaConfig(KafkaConfig config) throws IOException {
+        if (getKafkaManager().getKafkaConfig(config.getName()) != null) {
+            throw new InternalErrorException("The kafkaConfig named " + config.getName() + " already exists");
+        }
+        getKafkaManager().createKafkaConfig(config.getName(), config);
+        return config;
+    }
+
+    //    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
+    public KafkaConfig updateKafkaConfig(KafkaConfig config) throws IOException {
+        return getKafkaManager().updateKafkaConfig(config);
+    }
+
+    public KafkaConfig getKafkaConfig(String configName) throws IOException {
+        return getKafkaManager().getKafkaConfig(configName);
+    }
+
+    //    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
+    public void dropKafkaConfig(KafkaConfig config) throws IOException {
+        getKafkaManager().removeKafkaConfig(config);
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/service/ModelService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/ModelService.java b/server-base/src/main/java/org/apache/kylin/rest/service/ModelService.java
new file mode 100644
index 0000000..9d8ccfb
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/ModelService.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.service;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.kylin.cube.model.CubeDesc;
+import org.apache.kylin.engine.mr.HadoopUtil;
+import org.apache.kylin.invertedindex.model.IIDesc;
+import org.apache.kylin.metadata.model.DataModelDesc;
+import org.apache.kylin.metadata.project.ProjectInstance;
+import org.apache.kylin.rest.constant.Constant;
+import org.apache.kylin.rest.exception.InternalErrorException;
+import org.apache.kylin.rest.security.AclPermission;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PostFilter;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author jiazhong
+ */
+@Component("modelMgmtService")
+public class ModelService extends BasicService {
+
+    @Autowired
+    private AccessService accessService;
+
+    @PostFilter(Constant.ACCESS_POST_FILTER_READ)
+    public List<DataModelDesc> listAllModels(final String modelName, final String projectName) throws IOException {
+        List<DataModelDesc> models = null;
+        ProjectInstance project = (null != projectName) ? getProjectManager().getProject(projectName) : null;
+
+        if (null == project) {
+            models = getMetadataManager().getModels();
+        } else {
+            models = getMetadataManager().getModels(projectName);
+            project.getModels();
+        }
+
+        List<DataModelDesc> filterModels = new ArrayList<DataModelDesc>();
+        for (DataModelDesc modelDesc : models) {
+            boolean isModelMatch = (null == modelName) || modelDesc.getName().toLowerCase().contains(modelName.toLowerCase());
+
+            if (isModelMatch) {
+                filterModels.add(modelDesc);
+            }
+        }
+
+        return filterModels;
+    }
+
+    public List<DataModelDesc> getModels(final String modelName, final String projectName, final Integer limit, final Integer offset) throws IOException {
+
+        List<DataModelDesc> modelDescs;
+        modelDescs = listAllModels(modelName, projectName);
+
+        if (limit == null || offset == null) {
+            return modelDescs;
+        }
+
+        if ((modelDescs.size() - offset) < limit) {
+            return modelDescs.subList(offset, modelDescs.size());
+        }
+
+        return modelDescs.subList(offset, offset + limit);
+    }
+
+    public DataModelDesc createModelDesc(String projectName, DataModelDesc desc) throws IOException {
+        if (getMetadataManager().getDataModelDesc(desc.getName()) != null) {
+            throw new InternalErrorException("The model named " + desc.getName() + " already exists");
+        }
+        DataModelDesc createdDesc = null;
+        String owner = SecurityContextHolder.getContext().getAuthentication().getName();
+        createdDesc = getMetadataManager().createDataModelDesc(desc, projectName, owner);
+
+        accessService.init(createdDesc, AclPermission.ADMINISTRATION);
+        ProjectInstance project = getProjectManager().getProject(projectName);
+        accessService.inherit(createdDesc, project);
+        return createdDesc;
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
+    public DataModelDesc updateModelAndDesc(DataModelDesc desc) throws IOException {
+
+        getMetadataManager().updateDataModelDesc(desc);
+        return desc;
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
+    public void dropModel(DataModelDesc desc) throws IOException {
+
+        //check cube desc exist
+        List<CubeDesc> cubeDescs = getCubeDescManager().listAllDesc();
+        for (CubeDesc cubeDesc : cubeDescs) {
+            if (cubeDesc.getModelName().equals(desc.getName())) {
+                throw new InternalErrorException("Model referenced by cube,drop cubes under model and try again.");
+            }
+        }
+
+        //check II desc exist
+        List<IIDesc> iiDescs = getIIDescManager().listAllDesc();
+        for (IIDesc iidesc : iiDescs) {
+            if (iidesc.getModelName().equals(desc.getName())) {
+                throw new InternalErrorException("Model referenced by IIDesc.");
+            }
+        }
+
+        getMetadataManager().dropModel(desc);
+
+        accessService.clean(desc, true);
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
+    public boolean isTableInAnyModel(String tableName) {
+        String[] dbTableName = HadoopUtil.parseHiveTableName(tableName);
+        tableName = dbTableName[0] + "." + dbTableName[1];
+        return getMetadataManager().isTableInAnyModel(tableName);
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
+    public boolean isTableInModel(String tableName, String projectName) throws IOException {
+        String[] dbTableName = HadoopUtil.parseHiveTableName(tableName);
+        tableName = dbTableName[0] + "." + dbTableName[1];
+        return getMetadataManager().isTableInModel(tableName, projectName);
+    }
+}


[03/13] kylin git commit: KYLIN-1823 split code from kylin-server into kylin-server-base

Posted by li...@apache.org.
http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/security/MockAclHBaseStorage.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/MockAclHBaseStorage.java b/server/src/main/java/org/apache/kylin/rest/security/MockAclHBaseStorage.java
deleted file mode 100644
index 6c8081d..0000000
--- a/server/src/main/java/org/apache/kylin/rest/security/MockAclHBaseStorage.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.security;
-
-import java.io.IOException;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.hadoop.hbase.client.HTableInterface;
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.rest.service.AclService;
-import org.apache.kylin.rest.service.UserService;
-
-/**
- */
-public class MockAclHBaseStorage implements AclHBaseStorage {
-
-    private static final String aclTableName = "MOCK-ACL-TABLE";
-    private static final String userTableName = "MOCK-USER-TABLE";
-
-    private HTableInterface mockedAclTable;
-    private HTableInterface mockedUserTable;
-    private RealAclHBaseStorage realAcl;
-
-    public MockAclHBaseStorage() {
-        String metadataUrl = KylinConfig.getInstanceFromEnv().getMetadataUrl();
-        if (metadataUrl != null && metadataUrl.endsWith("hbase")) {
-            // hbase must be available since metadata is on it
-            // in this case, let us use a real ACL instead of mockup
-            realAcl = new RealAclHBaseStorage();
-        }
-    }
-
-    @Override
-    public String prepareHBaseTable(Class<?> clazz) throws IOException {
-        if (realAcl != null) {
-            return realAcl.prepareHBaseTable(clazz);
-        }
-
-        if (clazz == AclService.class) {
-            mockedAclTable = new MockHTable(aclTableName, ACL_INFO_FAMILY, ACL_ACES_FAMILY);
-            return aclTableName;
-        } else if (clazz == UserService.class) {
-            mockedUserTable = new MockHTable(userTableName, USER_AUTHORITY_FAMILY);
-            return userTableName;
-        } else {
-            throw new IllegalStateException("prepareHBaseTable for unknown class: " + clazz);
-        }
-    }
-
-    @Override
-    public HTableInterface getTable(String tableName) throws IOException {
-        if (realAcl != null) {
-            return realAcl.getTable(tableName);
-        }
-
-        if (StringUtils.equals(tableName, aclTableName)) {
-            return mockedAclTable;
-        } else if (StringUtils.equals(tableName, userTableName)) {
-            return mockedUserTable;
-        } else {
-            throw new IllegalStateException("getTable failed" + tableName);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/security/MockHTable.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/MockHTable.java b/server/src/main/java/org/apache/kylin/rest/security/MockHTable.java
deleted file mode 100644
index d0aa0ed..0000000
--- a/server/src/main/java/org/apache/kylin/rest/security/MockHTable.java
+++ /dev/null
@@ -1,729 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-/**
- * This file is licensed to you 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.
- */
-
-package org.apache.kylin.rest.security;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.NavigableMap;
-import java.util.NavigableSet;
-import java.util.NoSuchElementException;
-import java.util.TreeMap;
-
-import org.apache.commons.lang.NotImplementedException;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hbase.HColumnDescriptor;
-import org.apache.hadoop.hbase.HTableDescriptor;
-import org.apache.hadoop.hbase.KeyValue;
-import org.apache.hadoop.hbase.TableName;
-import org.apache.hadoop.hbase.client.Append;
-import org.apache.hadoop.hbase.client.Delete;
-import org.apache.hadoop.hbase.client.Durability;
-import org.apache.hadoop.hbase.client.Get;
-import org.apache.hadoop.hbase.client.HTableInterface;
-import org.apache.hadoop.hbase.client.Increment;
-import org.apache.hadoop.hbase.client.Mutation;
-import org.apache.hadoop.hbase.client.Put;
-import org.apache.hadoop.hbase.client.Result;
-import org.apache.hadoop.hbase.client.ResultScanner;
-import org.apache.hadoop.hbase.client.Row;
-import org.apache.hadoop.hbase.client.RowMutations;
-import org.apache.hadoop.hbase.client.Scan;
-import org.apache.hadoop.hbase.client.coprocessor.Batch;
-import org.apache.hadoop.hbase.filter.CompareFilter;
-import org.apache.hadoop.hbase.filter.Filter;
-import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
-import org.apache.hadoop.hbase.util.Bytes;
-
-import com.google.protobuf.Descriptors;
-import com.google.protobuf.Message;
-import com.google.protobuf.Service;
-import com.google.protobuf.ServiceException;
-
-/**
- * MockHTable.
- *
- * original MockHTable (by agaoglu) : https://gist.github.com/agaoglu/613217#file_mock_h_table.java
- *
- * Modifications
- *
- * <ul>
- *     <li>fix filter (by k-mack) : https://gist.github.com/k-mack/4600133</li>
- *     <li>fix batch() : implement all mutate operation and fix result[] count.</li>
- *     <li>fix exists()</li>
- *     <li>fix increment() : wrong return value</li>
- *     <li>check columnFamily</li>
- *     <li>implement mutateRow()</li>
- *     <li>implement getTableName()</li>
- *     <li>implement getTableDescriptor()</li>
- *     <li>throws RuntimeException when unimplemented method was called.</li>
- *     <li>remove some methods for loading data, checking values ...</li>
- * </ul>
- */
-public class MockHTable implements HTableInterface {
-    private final String tableName;
-    private final List<String> columnFamilies = new ArrayList<>();
-
-    private NavigableMap<byte[], NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>>> data = new TreeMap<>(Bytes.BYTES_COMPARATOR);
-
-    private static List<KeyValue> toKeyValue(byte[] row, NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> rowdata, int maxVersions) {
-        return toKeyValue(row, rowdata, 0, Long.MAX_VALUE, maxVersions);
-    }
-
-    public MockHTable(String tableName) {
-        this.tableName = tableName;
-    }
-
-    public MockHTable(String tableName, String... columnFamilies) {
-        this.tableName = tableName;
-        this.columnFamilies.addAll(Arrays.asList(columnFamilies));
-    }
-
-    public void addColumnFamily(String columnFamily) {
-        this.columnFamilies.add(columnFamily);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public byte[] getTableName() {
-        return tableName.getBytes();
-    }
-
-    @Override
-    public TableName getName() {
-        return null;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Configuration getConfiguration() {
-        throw new RuntimeException(this.getClass() + " does NOT implement this method.");
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public HTableDescriptor getTableDescriptor() throws IOException {
-        HTableDescriptor table = new HTableDescriptor(tableName);
-        for (String columnFamily : columnFamilies) {
-            table.addFamily(new HColumnDescriptor(columnFamily));
-        }
-        return table;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void mutateRow(RowMutations rm) throws IOException {
-        // currently only support Put and Delete
-        for (Mutation mutation : rm.getMutations()) {
-            if (mutation instanceof Put) {
-                put((Put) mutation);
-            } else if (mutation instanceof Delete) {
-                delete((Delete) mutation);
-            }
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Result append(Append append) throws IOException {
-        throw new RuntimeException(this.getClass() + " does NOT implement this method.");
-    }
-
-    private static List<KeyValue> toKeyValue(byte[] row, NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> rowdata, long timestampStart, long timestampEnd, int maxVersions) {
-        List<KeyValue> ret = new ArrayList<KeyValue>();
-        for (byte[] family : rowdata.keySet())
-            for (byte[] qualifier : rowdata.get(family).keySet()) {
-                int versionsAdded = 0;
-                for (Map.Entry<Long, byte[]> tsToVal : rowdata.get(family).get(qualifier).descendingMap().entrySet()) {
-                    if (versionsAdded++ == maxVersions)
-                        break;
-                    Long timestamp = tsToVal.getKey();
-                    if (timestamp < timestampStart)
-                        continue;
-                    if (timestamp > timestampEnd)
-                        continue;
-                    byte[] value = tsToVal.getValue();
-                    ret.add(new KeyValue(row, family, qualifier, timestamp, value));
-                }
-            }
-        return ret;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean exists(Get get) throws IOException {
-        Result result = get(get);
-        return result != null && result.isEmpty() == false;
-    }
-
-    @Override
-    public Boolean[] exists(List<Get> gets) throws IOException {
-        return new Boolean[0];
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void batch(List<? extends Row> actions, Object[] results) throws IOException, InterruptedException {
-        results = batch(actions);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Object[] batch(List<? extends Row> actions) throws IOException, InterruptedException {
-        Object[] results = new Object[actions.size()]; // same size.
-        for (int i = 0; i < actions.size(); i++) {
-            Row r = actions.get(i);
-            if (r instanceof Delete) {
-                delete((Delete) r);
-                results[i] = new Result();
-            }
-            if (r instanceof Put) {
-                put((Put) r);
-                results[i] = new Result();
-            }
-            if (r instanceof Get) {
-                Result result = get((Get) r);
-                results[i] = result;
-            }
-            if (r instanceof Increment) {
-                Result result = increment((Increment) r);
-                results[i] = result;
-            }
-            if (r instanceof Append) {
-                Result result = append((Append) r);
-                results[i] = result;
-            }
-        }
-        return results;
-    }
-
-    @Override
-    public <R> void batchCallback(List<? extends Row> actions, Object[] results, Batch.Callback<R> callback) throws IOException, InterruptedException {
-
-    }
-
-    @Override
-    public <R> Object[] batchCallback(List<? extends Row> actions, Batch.Callback<R> callback) throws IOException, InterruptedException {
-        return new Object[0];
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Result get(Get get) throws IOException {
-        if (!data.containsKey(get.getRow()))
-            return new Result();
-        byte[] row = get.getRow();
-        List<KeyValue> kvs = new ArrayList<KeyValue>();
-        if (!get.hasFamilies()) {
-            kvs = toKeyValue(row, data.get(row), get.getMaxVersions());
-        } else {
-            for (byte[] family : get.getFamilyMap().keySet()) {
-                if (data.get(row).get(family) == null)
-                    continue;
-                NavigableSet<byte[]> qualifiers = get.getFamilyMap().get(family);
-                if (qualifiers == null || qualifiers.isEmpty())
-                    qualifiers = data.get(row).get(family).navigableKeySet();
-                for (byte[] qualifier : qualifiers) {
-                    if (qualifier == null)
-                        qualifier = "".getBytes();
-                    if (!data.get(row).containsKey(family) || !data.get(row).get(family).containsKey(qualifier) || data.get(row).get(family).get(qualifier).isEmpty())
-                        continue;
-                    Map.Entry<Long, byte[]> timestampAndValue = data.get(row).get(family).get(qualifier).lastEntry();
-                    kvs.add(new KeyValue(row, family, qualifier, timestampAndValue.getKey(), timestampAndValue.getValue()));
-                }
-            }
-        }
-        Filter filter = get.getFilter();
-        if (filter != null) {
-            kvs = filter(filter, kvs);
-        }
-
-        return new Result(kvs);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Result[] get(List<Get> gets) throws IOException {
-        List<Result> results = new ArrayList<Result>();
-        for (Get g : gets) {
-            results.add(get(g));
-        }
-        return results.toArray(new Result[results.size()]);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Result getRowOrBefore(byte[] row, byte[] family) throws IOException {
-        // FIXME: implement
-        return null;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public ResultScanner getScanner(Scan scan) throws IOException {
-        final List<Result> ret = new ArrayList<Result>();
-        byte[] st = scan.getStartRow();
-        byte[] sp = scan.getStopRow();
-        Filter filter = scan.getFilter();
-
-        for (byte[] row : data.keySet()) {
-            // if row is equal to startRow emit it. When startRow (inclusive) and
-            // stopRow (exclusive) is the same, it should not be excluded which would
-            // happen w/o this control.
-            if (st != null && st.length > 0 && Bytes.BYTES_COMPARATOR.compare(st, row) != 0) {
-                // if row is before startRow do not emit, pass to next row
-                if (st != null && st.length > 0 && Bytes.BYTES_COMPARATOR.compare(st, row) > 0)
-                    continue;
-                // if row is equal to stopRow or after it do not emit, stop iteration
-                if (sp != null && sp.length > 0 && Bytes.BYTES_COMPARATOR.compare(sp, row) <= 0)
-                    break;
-            }
-
-            List<KeyValue> kvs = null;
-            if (!scan.hasFamilies()) {
-                kvs = toKeyValue(row, data.get(row), scan.getTimeRange().getMin(), scan.getTimeRange().getMax(), scan.getMaxVersions());
-            } else {
-                kvs = new ArrayList<KeyValue>();
-                for (byte[] family : scan.getFamilyMap().keySet()) {
-                    if (data.get(row).get(family) == null)
-                        continue;
-                    NavigableSet<byte[]> qualifiers = scan.getFamilyMap().get(family);
-                    if (qualifiers == null || qualifiers.isEmpty())
-                        qualifiers = data.get(row).get(family).navigableKeySet();
-                    for (byte[] qualifier : qualifiers) {
-                        if (data.get(row).get(family).get(qualifier) == null)
-                            continue;
-                        for (Long timestamp : data.get(row).get(family).get(qualifier).descendingKeySet()) {
-                            if (timestamp < scan.getTimeRange().getMin())
-                                continue;
-                            if (timestamp > scan.getTimeRange().getMax())
-                                continue;
-                            byte[] value = data.get(row).get(family).get(qualifier).get(timestamp);
-                            kvs.add(new KeyValue(row, family, qualifier, timestamp, value));
-                            if (kvs.size() == scan.getMaxVersions()) {
-                                break;
-                            }
-                        }
-                    }
-                }
-            }
-            if (filter != null) {
-                kvs = filter(filter, kvs);
-                // Check for early out optimization
-                if (filter.filterAllRemaining()) {
-                    break;
-                }
-            }
-            if (!kvs.isEmpty()) {
-                ret.add(new Result(kvs));
-            }
-        }
-
-        return new ResultScanner() {
-            private final Iterator<Result> iterator = ret.iterator();
-
-            public Iterator<Result> iterator() {
-                return iterator;
-            }
-
-            public Result[] next(int nbRows) throws IOException {
-                ArrayList<Result> resultSets = new ArrayList<Result>(nbRows);
-                for (int i = 0; i < nbRows; i++) {
-                    Result next = next();
-                    if (next != null) {
-                        resultSets.add(next);
-                    } else {
-                        break;
-                    }
-                }
-                return resultSets.toArray(new Result[resultSets.size()]);
-            }
-
-            public Result next() throws IOException {
-                try {
-                    return iterator().next();
-                } catch (NoSuchElementException e) {
-                    return null;
-                }
-            }
-
-            public void close() {
-            }
-        };
-    }
-
-    /**
-     * Follows the logical flow through the filter methods for a single row.
-     *
-     * @param filter HBase filter.
-     * @param kvs    List of a row's KeyValues
-     * @return List of KeyValues that were not filtered.
-     */
-    private List<KeyValue> filter(Filter filter, List<KeyValue> kvs) throws IOException {
-        filter.reset();
-
-        List<KeyValue> tmp = new ArrayList<KeyValue>(kvs.size());
-        tmp.addAll(kvs);
-
-        /*
-         * Note. Filter flow for a single row. Adapted from
-         * "HBase: The Definitive Guide" (p. 163) by Lars George, 2011.
-         * See Figure 4-2 on p. 163.
-         */
-        boolean filteredOnRowKey = false;
-        List<KeyValue> nkvs = new ArrayList<KeyValue>(tmp.size());
-        for (KeyValue kv : tmp) {
-            if (filter.filterRowKey(kv.getBuffer(), kv.getRowOffset(), kv.getRowLength())) {
-                filteredOnRowKey = true;
-                break;
-            }
-            Filter.ReturnCode filterResult = filter.filterKeyValue(kv);
-            if (filterResult == Filter.ReturnCode.INCLUDE) {
-                nkvs.add(kv);
-            } else if (filterResult == Filter.ReturnCode.NEXT_ROW) {
-                break;
-            } else if (filterResult == Filter.ReturnCode.NEXT_COL || filterResult == Filter.ReturnCode.SKIP) {
-                continue;
-            }
-            /*
-             * Ignoring next key hint which is a optimization to reduce file
-             * system IO
-             */
-        }
-        if (filter.hasFilterRow() && !filteredOnRowKey) {
-            filter.filterRow(nkvs);
-        }
-        if (filter.filterRow() || filteredOnRowKey) {
-            nkvs.clear();
-        }
-        tmp = nkvs;
-        return tmp;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public ResultScanner getScanner(byte[] family) throws IOException {
-        Scan scan = new Scan();
-        scan.addFamily(family);
-        return getScanner(scan);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public ResultScanner getScanner(byte[] family, byte[] qualifier) throws IOException {
-        Scan scan = new Scan();
-        scan.addColumn(family, qualifier);
-        return getScanner(scan);
-    }
-
-    private <K, V> V forceFind(NavigableMap<K, V> map, K key, V newObject) {
-        V data = map.get(key);
-        if (data == null) {
-            data = newObject;
-            map.put(key, data);
-        }
-        return data;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void put(Put put) throws IOException {
-        byte[] row = put.getRow();
-        NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> rowData = forceFind(data, row, new TreeMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>>(Bytes.BYTES_COMPARATOR));
-        for (byte[] family : put.getFamilyMap().keySet()) {
-            if (columnFamilies.contains(new String(family)) == false) {
-                throw new RuntimeException("Not Exists columnFamily : " + new String(family));
-            }
-            NavigableMap<byte[], NavigableMap<Long, byte[]>> familyData = forceFind(rowData, family, new TreeMap<byte[], NavigableMap<Long, byte[]>>(Bytes.BYTES_COMPARATOR));
-            for (KeyValue kv : put.getFamilyMap().get(family)) {
-                kv.updateLatestStamp(Bytes.toBytes(System.currentTimeMillis()));
-                byte[] qualifier = kv.getQualifier();
-                NavigableMap<Long, byte[]> qualifierData = forceFind(familyData, qualifier, new TreeMap<Long, byte[]>());
-                qualifierData.put(kv.getTimestamp(), kv.getValue());
-            }
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void put(List<Put> puts) throws IOException {
-        for (Put put : puts) {
-            put(put);
-        }
-
-    }
-
-    private boolean check(byte[] row, byte[] family, byte[] qualifier, byte[] value) {
-        if (value == null || value.length == 0)
-            return !data.containsKey(row) || !data.get(row).containsKey(family) || !data.get(row).get(family).containsKey(qualifier);
-        else
-            return data.containsKey(row) && data.get(row).containsKey(family) && data.get(row).get(family).containsKey(qualifier) && !data.get(row).get(family).get(qualifier).isEmpty() && Arrays.equals(data.get(row).get(family).get(qualifier).lastEntry().getValue(), value);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier, byte[] value, Put put) throws IOException {
-        if (check(row, family, qualifier, value)) {
-            put(put);
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void delete(Delete delete) throws IOException {
-        byte[] row = delete.getRow();
-        if (data.get(row) == null)
-            return;
-        if (delete.getFamilyMap().size() == 0) {
-            data.remove(row);
-            return;
-        }
-        for (byte[] family : delete.getFamilyMap().keySet()) {
-            if (data.get(row).get(family) == null)
-                continue;
-            if (delete.getFamilyMap().get(family).isEmpty()) {
-                data.get(row).remove(family);
-                continue;
-            }
-            for (KeyValue kv : delete.getFamilyMap().get(family)) {
-                if (kv.isDeleteFamily()) {
-                    data.get(row).get(kv.getFamily()).clear();
-                } else {
-                    data.get(row).get(kv.getFamily()).remove(kv.getQualifier());
-                }
-            }
-            if (data.get(row).get(family).isEmpty()) {
-                data.get(row).remove(family);
-            }
-        }
-        if (data.get(row).isEmpty()) {
-            data.remove(row);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void delete(List<Delete> deletes) throws IOException {
-        for (Delete delete : deletes) {
-            delete(delete);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, byte[] value, Delete delete) throws IOException {
-        if (check(row, family, qualifier, value)) {
-            delete(delete);
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Result increment(Increment increment) throws IOException {
-        throw new NotImplementedException();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public long incrementColumnValue(byte[] row, byte[] family, byte[] qualifier, long amount) throws IOException {
-        return incrementColumnValue(row, family, qualifier, amount, true);
-    }
-
-    @Override
-    public long incrementColumnValue(byte[] row, byte[] family, byte[] qualifier, long amount, Durability durability) throws IOException {
-        return 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public long incrementColumnValue(byte[] row, byte[] family, byte[] qualifier, long amount, boolean writeToWAL) throws IOException {
-        if (check(row, family, qualifier, null)) {
-            Put put = new Put(row);
-            put.add(family, qualifier, Bytes.toBytes(amount));
-            put(put);
-            return amount;
-        }
-        long newValue = Bytes.toLong(data.get(row).get(family).get(qualifier).lastEntry().getValue()) + amount;
-        data.get(row).get(family).get(qualifier).put(System.currentTimeMillis(), Bytes.toBytes(newValue));
-        return newValue;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean isAutoFlush() {
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void flushCommits() throws IOException {
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void close() throws IOException {
-    }
-
-    @Override
-    public CoprocessorRpcChannel coprocessorService(byte[] row) {
-        throw new NotImplementedException();
-
-    }
-
-    @Override
-    public <T extends Service, R> Map<byte[], R> coprocessorService(Class<T> service, byte[] startKey, byte[] endKey, Batch.Call<T, R> callable) throws ServiceException, Throwable {
-        throw new NotImplementedException();
-
-    }
-
-    @Override
-    public <T extends Service, R> void coprocessorService(Class<T> service, byte[] startKey, byte[] endKey, Batch.Call<T, R> callable, Batch.Callback<R> callback) throws ServiceException, Throwable {
-        throw new NotImplementedException();
-
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void setAutoFlush(boolean autoFlush) {
-        throw new NotImplementedException();
-
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void setAutoFlush(boolean autoFlush, boolean clearBufferOnFail) {
-        throw new NotImplementedException();
-
-    }
-
-    @Override
-    public void setAutoFlushTo(boolean autoFlush) {
-        throw new NotImplementedException();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public long getWriteBufferSize() {
-        throw new NotImplementedException();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void setWriteBufferSize(long writeBufferSize) throws IOException {
-        throw new NotImplementedException();
-
-    }
-
-    @Override
-    public <R extends Message> Map<byte[], R> batchCoprocessorService(Descriptors.MethodDescriptor methodDescriptor, Message request, byte[] startKey, byte[] endKey, R responsePrototype) throws ServiceException, Throwable {
-        throw new NotImplementedException();
-
-    }
-
-    @Override
-    public <R extends Message> void batchCoprocessorService(Descriptors.MethodDescriptor methodDescriptor, Message request, byte[] startKey, byte[] endKey, R responsePrototype, Batch.Callback<R> callback) throws ServiceException, Throwable {
-        throw new NotImplementedException();
-
-    }
-
-    //@Override  (only since 0.98.8)
-    public boolean checkAndMutate(byte[] row, byte[] family, byte[] qualifier, CompareFilter.CompareOp compareOp, byte[] value, RowMutations mutation) throws IOException {
-        throw new NotImplementedException();
-
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/security/PasswordPlaceholderConfigurer.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/PasswordPlaceholderConfigurer.java b/server/src/main/java/org/apache/kylin/rest/security/PasswordPlaceholderConfigurer.java
deleted file mode 100644
index 2692da9..0000000
--- a/server/src/main/java/org/apache/kylin/rest/security/PasswordPlaceholderConfigurer.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.security;
-
-import java.util.Properties;
-
-import javax.crypto.Cipher;
-import javax.crypto.spec.SecretKeySpec;
-
-import org.apache.commons.codec.binary.Base64;
-import org.apache.kylin.common.KylinConfig;
-import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
-import org.springframework.core.io.InputStreamResource;
-import org.springframework.core.io.Resource;
-import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
-
-/**
- * @author xduo
- * 
- */
-public class PasswordPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
-
-    private static byte[] key = { 0x74, 0x68, 0x69, 0x73, 0x49, 0x73, 0x41, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79 };
-
-    public PasswordPlaceholderConfigurer() {
-        Resource[] resources = new Resource[1];
-        resources[0] = new InputStreamResource(KylinConfig.getKylinPropertiesAsInputStream());
-        this.setLocations(resources);
-    }
-
-    public static String encrypt(String strToEncrypt) {
-        try {
-            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
-            final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
-            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
-            final String encryptedString = Base64.encodeBase64String(cipher.doFinal(strToEncrypt.getBytes()));
-            return encryptedString;
-        } catch (Exception e) {
-            throw new RuntimeException(e.getMessage(), e);
-        }
-    }
-
-    public static String decrypt(String strToDecrypt) {
-        try {
-            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
-            final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
-            cipher.init(Cipher.DECRYPT_MODE, secretKey);
-            final String decryptedString = new String(cipher.doFinal(Base64.decodeBase64(strToDecrypt)));
-            return decryptedString;
-        } catch (Exception e) {
-            throw new RuntimeException(e.getMessage(), e);
-        }
-    }
-
-    protected String resolvePlaceholder(String placeholder, Properties props) {
-        if (placeholder.toLowerCase().contains("password")) {
-            return decrypt(props.getProperty(placeholder));
-        } else {
-            return props.getProperty(placeholder);
-        }
-    }
-
-    private static void printUsage() {
-        System.out.println("Usage: java org.apache.kylin.rest.security.PasswordPlaceholderConfigurer <EncryptMethod> <your_password>");
-        System.out.println("EncryptMethod: AES or BCrypt");
-    }
-
-    public static void main(String[] args) {
-        if (args.length != 2) {
-            printUsage();
-            System.exit(1);
-        }
-
-        String encryptMethod = args[0];
-        String passwordTxt = args[1];
-        if ("AES".equalsIgnoreCase(encryptMethod)) {
-            // for encrypt password like LDAP password
-            System.out.println(encryptMethod + " encrypted password is: ");
-            System.out.println(encrypt(passwordTxt));
-        } else if ("BCrypt".equalsIgnoreCase(encryptMethod)) {
-            // for encrypt the predefined user password, like ADMIN, MODELER.
-            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
-            System.out.println(encryptMethod + " encrypted password is: ");
-            System.out.println(bCryptPasswordEncoder.encode(passwordTxt));
-        } else {
-            printUsage();
-            System.exit(1);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/security/RealAclHBaseStorage.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/RealAclHBaseStorage.java b/server/src/main/java/org/apache/kylin/rest/security/RealAclHBaseStorage.java
deleted file mode 100644
index 27d9720..0000000
--- a/server/src/main/java/org/apache/kylin/rest/security/RealAclHBaseStorage.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.security;
-
-import java.io.IOException;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.hadoop.hbase.client.HTableInterface;
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.rest.service.AclService;
-import org.apache.kylin.rest.service.UserService;
-import org.apache.kylin.storage.hbase.HBaseConnection;
-
-/**
- */
-public class RealAclHBaseStorage implements AclHBaseStorage {
-
-    private String hbaseUrl;
-    private String aclTableName;
-    private String userTableName;
-
-    @Override
-    public String prepareHBaseTable(Class<?> clazz) throws IOException {
-        String metadataUrl = KylinConfig.getInstanceFromEnv().getMetadataUrl();
-        int cut = metadataUrl.indexOf('@');
-        String tableNameBase = cut < 0 ? DEFAULT_TABLE_PREFIX : metadataUrl.substring(0, cut);
-        hbaseUrl = cut < 0 ? metadataUrl : metadataUrl.substring(cut + 1);
-
-        if (clazz == AclService.class) {
-            aclTableName = tableNameBase + ACL_TABLE_NAME;
-            HBaseConnection.createHTableIfNeeded(hbaseUrl, aclTableName, ACL_INFO_FAMILY, ACL_ACES_FAMILY);
-            return aclTableName;
-        } else if (clazz == UserService.class) {
-            userTableName = tableNameBase + USER_TABLE_NAME;
-            HBaseConnection.createHTableIfNeeded(hbaseUrl, userTableName, USER_AUTHORITY_FAMILY);
-            return userTableName;
-        } else {
-            throw new IllegalStateException("prepareHBaseTable for unknown class: " + clazz);
-        }
-    }
-
-    @Override
-    public HTableInterface getTable(String tableName) throws IOException {
-        if (StringUtils.equals(tableName, aclTableName)) {
-            return HBaseConnection.get(hbaseUrl).getTable(aclTableName);
-        } else if (StringUtils.equals(tableName, userTableName)) {
-            return HBaseConnection.get(hbaseUrl).getTable(userTableName);
-        } else {
-            throw new IllegalStateException("getTable failed" + tableName);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/security/SAMLUserDetailsService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/SAMLUserDetailsService.java b/server/src/main/java/org/apache/kylin/rest/security/SAMLUserDetailsService.java
deleted file mode 100644
index 24f8243..0000000
--- a/server/src/main/java/org/apache/kylin/rest/security/SAMLUserDetailsService.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.security;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.security.ldap.userdetails.LdapUserDetailsService;
-import org.springframework.security.saml.SAMLCredential;
-
-/**
- * An implementation of SAMLUserDetailsService by delegating the query to LdapUserDetailsService.
- */
-public class SAMLUserDetailsService implements org.springframework.security.saml.userdetails.SAMLUserDetailsService {
-
-    private static final Logger logger = LoggerFactory.getLogger(SAMLUserDetailsService.class);
-    private LdapUserDetailsService ldapUserDetailsService;
-
-    public SAMLUserDetailsService(LdapUserDetailsService ldapUserDetailsService) {
-        this.ldapUserDetailsService = ldapUserDetailsService;
-    }
-
-    @Override
-    public Object loadUserBySAML(SAMLCredential samlCredential) throws UsernameNotFoundException {
-        final String userEmail = samlCredential.getAttributeAsString("email");
-        logger.debug("samlCredential.email:" + userEmail);
-        final String userName = userEmail.substring(0, userEmail.indexOf("@"));
-
-        UserDetails userDetails = null;
-        try {
-            userDetails = ldapUserDetailsService.loadUserByUsername(userName);
-        } catch (org.springframework.security.core.userdetails.UsernameNotFoundException e) {
-            logger.error("User not found in LDAP, check whether he/she has been added to the groups.", e);
-        }
-        logger.debug("userDeail by search ldap with '" + userName + "' is: " + userDetails);
-        return userDetails;
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/security/UnauthorisedEntryPoint.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/security/UnauthorisedEntryPoint.java b/server/src/main/java/org/apache/kylin/rest/security/UnauthorisedEntryPoint.java
deleted file mode 100644
index 253bae3..0000000
--- a/server/src/main/java/org/apache/kylin/rest/security/UnauthorisedEntryPoint.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.security;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.springframework.security.core.AuthenticationException;
-import org.springframework.security.web.AuthenticationEntryPoint;
-import org.springframework.stereotype.Component;
-
-/**
- * Just return 401-unauthorized for every unauthorized request. The client side
- * catches this and handles login.
- * 
- * @author xduo
- */
-@Component(value = "unauthorisedEntryPoint")
-public class UnauthorisedEntryPoint implements AuthenticationEntryPoint {
-
-    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
-        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/service/AccessService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/AccessService.java b/server/src/main/java/org/apache/kylin/rest/service/AccessService.java
deleted file mode 100644
index 9561fbd..0000000
--- a/server/src/main/java/org/apache/kylin/rest/service/AccessService.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.service;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.kylin.common.persistence.AclEntity;
-import org.apache.kylin.common.persistence.RootPersistentEntity;
-import org.apache.kylin.rest.constant.Constant;
-import org.apache.kylin.rest.exception.ForbiddenException;
-import org.apache.kylin.rest.response.AccessEntryResponse;
-import org.apache.kylin.rest.security.AclEntityFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.security.acls.domain.BasePermission;
-import org.springframework.security.acls.domain.GrantedAuthoritySid;
-import org.springframework.security.acls.domain.ObjectIdentityImpl;
-import org.springframework.security.acls.domain.PrincipalSid;
-import org.springframework.security.acls.model.AccessControlEntry;
-import org.springframework.security.acls.model.Acl;
-import org.springframework.security.acls.model.AlreadyExistsException;
-import org.springframework.security.acls.model.MutableAcl;
-import org.springframework.security.acls.model.NotFoundException;
-import org.springframework.security.acls.model.ObjectIdentity;
-import org.springframework.security.acls.model.Permission;
-import org.springframework.security.acls.model.Sid;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.stereotype.Component;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.Assert;
-
-/**
- * @author xduo
- * 
- */
-@Component("accessService")
-public class AccessService {
-
-    @Autowired
-    private AclService aclService;
-
-    @Autowired
-    UserService userService;
-
-    // ~ Methods to manage acl life circle of domain objects ~
-
-    @Transactional
-    public Acl init(AclEntity ae, Permission initPermission) {
-        Acl acl = null;
-        ObjectIdentity objectIdentity = new ObjectIdentityImpl(ae.getClass(), ae.getId());
-
-        try {
-            // Create acl record for secured domain object.
-            acl = aclService.createAcl(objectIdentity);
-        } catch (AlreadyExistsException e) {
-            acl = (MutableAcl) aclService.readAclById(objectIdentity);
-        }
-
-        if (null != initPermission) {
-            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
-            PrincipalSid sid = new PrincipalSid(auth);
-            acl = grant(ae, initPermission, sid);
-        }
-
-        return acl;
-    }
-
-    @Transactional
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#ae, 'ADMINISTRATION')")
-    public Acl grant(AclEntity ae, Permission permission, Sid sid) {
-        Assert.notNull(ae, "Acl domain object required");
-        Assert.notNull(permission, "Acl permission required");
-        Assert.notNull(sid, "Sid required");
-
-        ObjectIdentity objectIdentity = new ObjectIdentityImpl(ae.getClass(), ae.getId());
-        MutableAcl acl = null;
-
-        try {
-            acl = (MutableAcl) aclService.readAclById(objectIdentity);
-        } catch (NotFoundException e) {
-            acl = (MutableAcl) init(ae, null);
-        }
-
-        int indexOfAce = -1;
-        for (int i = 0; i < acl.getEntries().size(); i++) {
-            AccessControlEntry ace = acl.getEntries().get(i);
-
-            if (ace.getSid().equals(sid)) {
-                indexOfAce = i;
-            }
-        }
-
-        if (indexOfAce != -1) {
-            secureOwner(acl, indexOfAce);
-            acl.updateAce(indexOfAce, permission);
-        } else {
-            acl.insertAce(acl.getEntries().size(), permission, sid, true);
-        }
-
-        acl = aclService.updateAcl(acl);
-
-        return acl;
-    }
-
-    @Transactional
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#ae, 'ADMINISTRATION')")
-    public Acl update(AclEntity ae, Long accessEntryId, Permission newPermission) {
-        Assert.notNull(ae, "Acl domain object required");
-        Assert.notNull(accessEntryId, "Ace id required");
-        Assert.notNull(newPermission, "Acl permission required");
-
-        ObjectIdentity objectIdentity = new ObjectIdentityImpl(ae.getClass(), ae.getId());
-        MutableAcl acl = (MutableAcl) aclService.readAclById(objectIdentity);
-
-        int indexOfAce = -1;
-        for (int i = 0; i < acl.getEntries().size(); i++) {
-            AccessControlEntry ace = acl.getEntries().get(i);
-            if (ace.getId().equals(accessEntryId)) {
-                indexOfAce = i;
-                break;
-            }
-        }
-
-        if (indexOfAce != -1) {
-            secureOwner(acl, indexOfAce);
-
-            try {
-                acl.updateAce(indexOfAce, newPermission);
-                acl = aclService.updateAcl(acl);
-            } catch (NotFoundException e) {
-                //do nothing?
-            }
-        }
-
-        return acl;
-    }
-
-    @Transactional
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#ae, 'ADMINISTRATION')")
-    public Acl revoke(AclEntity ae, Long accessEntryId) {
-        Assert.notNull(ae, "Acl domain object required");
-        Assert.notNull(accessEntryId, "Ace id required");
-
-        ObjectIdentity objectIdentity = new ObjectIdentityImpl(ae.getClass(), ae.getId());
-        MutableAcl acl = (MutableAcl) aclService.readAclById(objectIdentity);
-        int indexOfAce = -1;
-
-        for (int i = 0; i < acl.getEntries().size(); i++) {
-            AccessControlEntry ace = acl.getEntries().get(i);
-            if (((Long) ace.getId()).equals(accessEntryId)) {
-                indexOfAce = i;
-                break;
-            }
-        }
-
-        if (indexOfAce != -1) {
-            secureOwner(acl, indexOfAce);
-
-            try {
-                acl.deleteAce(indexOfAce);
-                acl = aclService.updateAcl(acl);
-            } catch (NotFoundException e) {
-                //do nothing?
-            }
-        }
-
-        return acl;
-    }
-
-    @Transactional
-    public void inherit(AclEntity ae, AclEntity parentAe) {
-        Assert.notNull(ae, "Acl domain object required");
-        Assert.notNull(parentAe, "Parent acl required");
-
-        ObjectIdentity objectIdentity = new ObjectIdentityImpl(ae.getClass(), ae.getId());
-        MutableAcl acl = null;
-        try {
-            acl = (MutableAcl) aclService.readAclById(objectIdentity);
-        } catch (NotFoundException e) {
-            acl = (MutableAcl) init(ae, null);
-        }
-
-        ObjectIdentity parentObjectIdentity = new ObjectIdentityImpl(parentAe.getClass(), parentAe.getId());
-        MutableAcl parentAcl = null;
-        try {
-            parentAcl = (MutableAcl) aclService.readAclById(parentObjectIdentity);
-        } catch (NotFoundException e) {
-            parentAcl = (MutableAcl) init(parentAe, null);
-        }
-
-        if (null == acl || null == parentAcl) {
-            return;
-        }
-
-        acl.setEntriesInheriting(true);
-        acl.setParent(parentAcl);
-        aclService.updateAcl(acl);
-    }
-
-    @Transactional
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#ae, 'ADMINISTRATION')")
-    public void clean(AclEntity ae, boolean deleteChildren) {
-        Assert.notNull(ae, "Acl domain object required");
-
-        // For those may have null uuid, like DataModel, won't delete Acl.
-        if (ae.getId() == null)
-            return;
-
-        ObjectIdentity objectIdentity = new ObjectIdentityImpl(ae.getClass(), ae.getId());
-
-        try {
-            aclService.deleteAcl(objectIdentity, deleteChildren);
-        } catch (NotFoundException e) {
-            //do nothing?
-        }
-    }
-
-    // ~ Methods to get acl info of domain objects ~
-
-    public RootPersistentEntity getAclEntity(String entityType, String uuid) {
-        if (null == uuid) {
-            return null;
-        }
-
-        return AclEntityFactory.createAclEntity(entityType, uuid);
-    }
-
-    public Acl getAcl(AclEntity ae) {
-        if (null == ae) {
-            return null;
-        }
-        ObjectIdentity objectIdentity = new ObjectIdentityImpl(ae.getClass(), ae.getId());
-        Acl acl = null;
-
-        try {
-            acl = (MutableAcl) aclService.readAclById(objectIdentity);
-        } catch (NotFoundException e) {
-            //do nothing?
-        }
-
-        return acl;
-    }
-
-    public Sid getSid(String sid, boolean isPrincepal) {
-        if (isPrincepal) {
-            return new PrincipalSid(sid);
-        } else {
-            return new GrantedAuthoritySid(sid);
-        }
-    }
-
-    public List<AccessEntryResponse> generateAceResponses(Acl acl) {
-        if (null == acl) {
-            return Collections.emptyList();
-        }
-        List<AccessEntryResponse> accessControlEntities = new ArrayList<AccessEntryResponse>();
-
-        // Cause there is a circle reference in AccessControlEntry, it needs to
-        // set acl to null as a workaround.
-        for (AccessControlEntry ace : acl.getEntries()) {
-            accessControlEntities.add(new AccessEntryResponse(ace.getId(), ace.getSid(), ace.getPermission(), ace.isGranting()));
-        }
-
-        return accessControlEntities;
-    }
-
-    /**
-     * Protect admin permission granted to acl owner.
-     * 
-     * @param acl
-     * @param indexOfAce
-     */
-    private void secureOwner(MutableAcl acl, int indexOfAce) {
-        // Can't revoke admin permission from domain object owner
-        if (acl.getOwner().equals(acl.getEntries().get(indexOfAce).getSid()) && BasePermission.ADMINISTRATION.equals(acl.getEntries().get(indexOfAce).getPermission())) {
-            throw new ForbiddenException("Can't revoke admin permission of owner.");
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/service/AclService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/AclService.java b/server/src/main/java/org/apache/kylin/rest/service/AclService.java
deleted file mode 100644
index d693a67..0000000
--- a/server/src/main/java/org/apache/kylin/rest/service/AclService.java
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.service;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.NavigableMap;
-
-import javax.annotation.PostConstruct;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.hadoop.hbase.client.Delete;
-import org.apache.hadoop.hbase.client.Get;
-import org.apache.hadoop.hbase.client.HTableInterface;
-import org.apache.hadoop.hbase.client.Put;
-import org.apache.hadoop.hbase.client.Result;
-import org.apache.hadoop.hbase.client.ResultScanner;
-import org.apache.hadoop.hbase.client.Scan;
-import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
-import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
-import org.apache.kylin.common.util.Bytes;
-import org.apache.kylin.rest.security.AclHBaseStorage;
-import org.apache.kylin.rest.util.Serializer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.acls.domain.AccessControlEntryImpl;
-import org.springframework.security.acls.domain.AclAuthorizationStrategy;
-import org.springframework.security.acls.domain.AclImpl;
-import org.springframework.security.acls.domain.AuditLogger;
-import org.springframework.security.acls.domain.GrantedAuthoritySid;
-import org.springframework.security.acls.domain.ObjectIdentityImpl;
-import org.springframework.security.acls.domain.PermissionFactory;
-import org.springframework.security.acls.domain.PrincipalSid;
-import org.springframework.security.acls.model.AccessControlEntry;
-import org.springframework.security.acls.model.Acl;
-import org.springframework.security.acls.model.AlreadyExistsException;
-import org.springframework.security.acls.model.ChildrenExistException;
-import org.springframework.security.acls.model.MutableAcl;
-import org.springframework.security.acls.model.MutableAclService;
-import org.springframework.security.acls.model.NotFoundException;
-import org.springframework.security.acls.model.ObjectIdentity;
-import org.springframework.security.acls.model.PermissionGrantingStrategy;
-import org.springframework.security.acls.model.Sid;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.util.FieldUtils;
-import org.springframework.stereotype.Component;
-import org.springframework.util.Assert;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-
-/**
- * @author xduo
- * 
- */
-@Component("aclService")
-public class AclService implements MutableAclService {
-
-    private static final Logger logger = LoggerFactory.getLogger(AclService.class);
-
-    private static String ACL_INFO_FAMILY_TYPE_COLUMN = "t";
-    private static String ACL_INFO_FAMILY_OWNER_COLUMN = "o";
-    private static String ACL_INFO_FAMILY_PARENT_COLUMN = "p";
-    private static String ACL_INFO_FAMILY_ENTRY_INHERIT_COLUMN = "i";
-
-    private Serializer<SidInfo> sidSerializer = new Serializer<SidInfo>(SidInfo.class);
-    private Serializer<DomainObjectInfo> domainObjSerializer = new Serializer<DomainObjectInfo>(DomainObjectInfo.class);
-    private Serializer<AceInfo> aceSerializer = new Serializer<AceInfo>(AceInfo.class);
-
-    private String aclTableName = null;
-
-    private final Field fieldAces = FieldUtils.getField(AclImpl.class, "aces");
-    private final Field fieldAcl = FieldUtils.getField(AccessControlEntryImpl.class, "acl");
-
-    @Autowired
-    protected PermissionGrantingStrategy permissionGrantingStrategy;
-
-    @Autowired
-    protected PermissionFactory aclPermissionFactory;
-
-    @Autowired
-    protected AclAuthorizationStrategy aclAuthorizationStrategy;
-
-    @Autowired
-    protected AuditLogger auditLogger;
-
-    @Autowired
-    protected AclHBaseStorage aclHBaseStorage;
-
-    public AclService() throws IOException {
-        fieldAces.setAccessible(true);
-        fieldAcl.setAccessible(true);
-    }
-
-    @PostConstruct
-    public void init() throws IOException {
-        aclTableName = aclHBaseStorage.prepareHBaseTable(AclService.class);
-    }
-
-    @Override
-    public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
-        List<ObjectIdentity> oids = new ArrayList<ObjectIdentity>();
-        HTableInterface htable = null;
-        try {
-            htable = aclHBaseStorage.getTable(aclTableName);
-
-            Scan scan = new Scan();
-            SingleColumnValueFilter parentFilter = new SingleColumnValueFilter(Bytes.toBytes(AclHBaseStorage.ACL_INFO_FAMILY), Bytes.toBytes(ACL_INFO_FAMILY_PARENT_COLUMN), CompareOp.EQUAL, domainObjSerializer.serialize(new DomainObjectInfo(parentIdentity)));
-            parentFilter.setFilterIfMissing(true);
-            scan.setFilter(parentFilter);
-
-            ResultScanner scanner = htable.getScanner(scan);
-            for (Result result = scanner.next(); result != null; result = scanner.next()) {
-                String id = Bytes.toString(result.getRow());
-                String type = Bytes.toString(result.getValue(Bytes.toBytes(AclHBaseStorage.ACL_INFO_FAMILY), Bytes.toBytes(ACL_INFO_FAMILY_TYPE_COLUMN)));
-
-                oids.add(new ObjectIdentityImpl(type, id));
-            }
-        } catch (IOException e) {
-            throw new RuntimeException(e.getMessage(), e);
-        } finally {
-            IOUtils.closeQuietly(htable);
-        }
-
-        return oids;
-    }
-
-    @Override
-    public Acl readAclById(ObjectIdentity object) throws NotFoundException {
-        Map<ObjectIdentity, Acl> aclsMap = readAclsById(Arrays.asList(object), null);
-        //        Assert.isTrue(aclsMap.containsKey(object), "There should have been an Acl entry for ObjectIdentity " + object);
-
-        return aclsMap.get(object);
-    }
-
-    @Override
-    public Acl readAclById(ObjectIdentity object, List<Sid> sids) throws NotFoundException {
-        Map<ObjectIdentity, Acl> aclsMap = readAclsById(Arrays.asList(object), sids);
-        Assert.isTrue(aclsMap.containsKey(object), "There should have been an Acl entry for ObjectIdentity " + object);
-
-        return aclsMap.get(object);
-    }
-
-    @Override
-    public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects) throws NotFoundException {
-        return readAclsById(objects, null);
-    }
-
-    @Override
-    public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> oids, List<Sid> sids) throws NotFoundException {
-        Map<ObjectIdentity, Acl> aclMaps = new HashMap<ObjectIdentity, Acl>();
-        HTableInterface htable = null;
-        Result result = null;
-        try {
-            htable = aclHBaseStorage.getTable(aclTableName);
-
-            for (ObjectIdentity oid : oids) {
-                result = htable.get(new Get(Bytes.toBytes(String.valueOf(oid.getIdentifier()))));
-
-                if (null != result && !result.isEmpty()) {
-                    SidInfo owner = sidSerializer.deserialize(result.getValue(Bytes.toBytes(AclHBaseStorage.ACL_INFO_FAMILY), Bytes.toBytes(ACL_INFO_FAMILY_OWNER_COLUMN)));
-                    Sid ownerSid = (null == owner) ? null : (owner.isPrincipal() ? new PrincipalSid(owner.getSid()) : new GrantedAuthoritySid(owner.getSid()));
-                    boolean entriesInheriting = Bytes.toBoolean(result.getValue(Bytes.toBytes(AclHBaseStorage.ACL_INFO_FAMILY), Bytes.toBytes(ACL_INFO_FAMILY_ENTRY_INHERIT_COLUMN)));
-
-                    Acl parentAcl = null;
-                    DomainObjectInfo parentInfo = domainObjSerializer.deserialize(result.getValue(Bytes.toBytes(AclHBaseStorage.ACL_INFO_FAMILY), Bytes.toBytes(ACL_INFO_FAMILY_PARENT_COLUMN)));
-                    if (null != parentInfo) {
-                        ObjectIdentity parentObj = new ObjectIdentityImpl(parentInfo.getType(), parentInfo.getId());
-                        parentAcl = readAclById(parentObj, null);
-                    }
-
-                    AclImpl acl = new AclImpl(oid, oid.getIdentifier(), aclAuthorizationStrategy, permissionGrantingStrategy, parentAcl, null, entriesInheriting, ownerSid);
-                    genAces(sids, result, acl);
-
-                    aclMaps.put(oid, acl);
-                } else {
-                    throw new NotFoundException("Unable to find ACL information for object identity '" + oid + "'");
-                }
-            }
-        } catch (IOException e) {
-            throw new RuntimeException(e.getMessage(), e);
-        } finally {
-            IOUtils.closeQuietly(htable);
-        }
-
-        return aclMaps;
-    }
-
-    @Override
-    public MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException {
-        Acl acl = null;
-
-        try {
-            acl = readAclById(objectIdentity);
-        } catch (NotFoundException e) {
-            //do nothing?
-        }
-        if (null != acl) {
-            throw new AlreadyExistsException("ACL of " + objectIdentity + " exists!");
-        }
-
-        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
-        PrincipalSid sid = new PrincipalSid(auth);
-
-        HTableInterface htable = null;
-        try {
-            htable = aclHBaseStorage.getTable(aclTableName);
-
-            Put put = new Put(Bytes.toBytes(String.valueOf(objectIdentity.getIdentifier())));
-            put.add(Bytes.toBytes(AclHBaseStorage.ACL_INFO_FAMILY), Bytes.toBytes(ACL_INFO_FAMILY_TYPE_COLUMN), Bytes.toBytes(objectIdentity.getType()));
-            put.add(Bytes.toBytes(AclHBaseStorage.ACL_INFO_FAMILY), Bytes.toBytes(ACL_INFO_FAMILY_OWNER_COLUMN), sidSerializer.serialize(new SidInfo(sid)));
-            put.add(Bytes.toBytes(AclHBaseStorage.ACL_INFO_FAMILY), Bytes.toBytes(ACL_INFO_FAMILY_ENTRY_INHERIT_COLUMN), Bytes.toBytes(true));
-
-            htable.put(put);
-            htable.flushCommits();
-
-            logger.debug("ACL of " + objectIdentity + " created successfully.");
-        } catch (IOException e) {
-            throw new RuntimeException(e.getMessage(), e);
-        } finally {
-            IOUtils.closeQuietly(htable);
-        }
-
-        return (MutableAcl) readAclById(objectIdentity);
-    }
-
-    @Override
-    public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws ChildrenExistException {
-        HTableInterface htable = null;
-        try {
-            htable = aclHBaseStorage.getTable(aclTableName);
-
-            Delete delete = new Delete(Bytes.toBytes(String.valueOf(objectIdentity.getIdentifier())));
-
-            List<ObjectIdentity> children = findChildren(objectIdentity);
-            if (!deleteChildren && children.size() > 0) {
-                throw new ChildrenExistException("Children exists for " + objectIdentity);
-            }
-
-            for (ObjectIdentity oid : children) {
-                deleteAcl(oid, deleteChildren);
-            }
-
-            htable.delete(delete);
-            htable.flushCommits();
-
-            logger.debug("ACL of " + objectIdentity + " deleted successfully.");
-        } catch (IOException e) {
-            throw new RuntimeException(e.getMessage(), e);
-        } finally {
-            IOUtils.closeQuietly(htable);
-        }
-    }
-
-    @Override
-    public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException {
-        try {
-            readAclById(acl.getObjectIdentity());
-        } catch (NotFoundException e) {
-            throw e;
-        }
-
-        HTableInterface htable = null;
-        try {
-            htable = aclHBaseStorage.getTable(aclTableName);
-
-            Delete delete = new Delete(Bytes.toBytes(String.valueOf(acl.getObjectIdentity().getIdentifier())));
-            delete.deleteFamily(Bytes.toBytes(AclHBaseStorage.ACL_ACES_FAMILY));
-            htable.delete(delete);
-
-            Put put = new Put(Bytes.toBytes(String.valueOf(acl.getObjectIdentity().getIdentifier())));
-
-            if (null != acl.getParentAcl()) {
-                put.add(Bytes.toBytes(AclHBaseStorage.ACL_INFO_FAMILY), Bytes.toBytes(ACL_INFO_FAMILY_PARENT_COLUMN), domainObjSerializer.serialize(new DomainObjectInfo(acl.getParentAcl().getObjectIdentity())));
-            }
-
-            for (AccessControlEntry ace : acl.getEntries()) {
-                AceInfo aceInfo = new AceInfo(ace);
-                put.add(Bytes.toBytes(AclHBaseStorage.ACL_ACES_FAMILY), Bytes.toBytes(aceInfo.getSidInfo().getSid()), aceSerializer.serialize(aceInfo));
-            }
-
-            if (!put.isEmpty()) {
-                htable.put(put);
-                htable.flushCommits();
-
-                logger.debug("ACL of " + acl.getObjectIdentity() + " updated successfully.");
-            }
-        } catch (IOException e) {
-            throw new RuntimeException(e.getMessage(), e);
-        } finally {
-            IOUtils.closeQuietly(htable);
-        }
-
-        return (MutableAcl) readAclById(acl.getObjectIdentity());
-    }
-
-    private void genAces(List<Sid> sids, Result result, AclImpl acl) throws JsonParseException, JsonMappingException, IOException {
-        List<AceInfo> aceInfos = new ArrayList<AceInfo>();
-        if (null != sids) {
-            // Just return aces in sids
-            for (Sid sid : sids) {
-                String sidName = null;
-                if (sid instanceof PrincipalSid) {
-                    sidName = ((PrincipalSid) sid).getPrincipal();
-                } else if (sid instanceof GrantedAuthoritySid) {
-                    sidName = ((GrantedAuthoritySid) sid).getGrantedAuthority();
-                }
-
-                AceInfo aceInfo = aceSerializer.deserialize(result.getValue(Bytes.toBytes(AclHBaseStorage.ACL_ACES_FAMILY), Bytes.toBytes(sidName)));
-                if (null != aceInfo) {
-                    aceInfos.add(aceInfo);
-                }
-            }
-        } else {
-            NavigableMap<byte[], byte[]> familyMap = result.getFamilyMap(Bytes.toBytes(AclHBaseStorage.ACL_ACES_FAMILY));
-            for (byte[] qualifier : familyMap.keySet()) {
-                AceInfo aceInfo = aceSerializer.deserialize(familyMap.get(qualifier));
-
-                if (null != aceInfo) {
-                    aceInfos.add(aceInfo);
-                }
-            }
-        }
-
-        List<AccessControlEntry> newAces = new ArrayList<AccessControlEntry>();
-        for (int i = 0; i < aceInfos.size(); i++) {
-            AceInfo aceInfo = aceInfos.get(i);
-
-            if (null != aceInfo) {
-                Sid sid = aceInfo.getSidInfo().isPrincipal() ? new PrincipalSid(aceInfo.getSidInfo().getSid()) : new GrantedAuthoritySid(aceInfo.getSidInfo().getSid());
-                AccessControlEntry ace = new AccessControlEntryImpl(Long.valueOf(i), acl, sid, aclPermissionFactory.buildFromMask(aceInfo.getPermissionMask()), true, false, false);
-                newAces.add(ace);
-            }
-        }
-
-        this.setAces(acl, newAces);
-    }
-
-    private void setAces(AclImpl acl, List<AccessControlEntry> aces) {
-        try {
-            fieldAces.set(acl, aces);
-        } catch (IllegalAccessException e) {
-            throw new IllegalStateException("Could not set AclImpl entries", e);
-        }
-    }
-
-    protected static class DomainObjectInfo {
-        private String id;
-        private String type;
-
-        public DomainObjectInfo() {
-        }
-
-        public DomainObjectInfo(ObjectIdentity oid) {
-            super();
-            this.id = (String) oid.getIdentifier();
-            this.type = oid.getType();
-        }
-
-        public Serializable getId() {
-            return id;
-        }
-
-        public void setId(String id) {
-            this.id = id;
-        }
-
-        public String getType() {
-            return type;
-        }
-
-        public void setType(String type) {
-            this.type = type;
-        }
-    }
-
-    protected static class SidInfo {
-        private String sid;
-        private boolean isPrincipal;
-
-        public SidInfo() {
-        }
-
-        public SidInfo(Sid sid) {
-            if (sid instanceof PrincipalSid) {
-                this.sid = ((PrincipalSid) sid).getPrincipal();
-                this.isPrincipal = true;
-            } else if (sid instanceof GrantedAuthoritySid) {
-                this.sid = ((GrantedAuthoritySid) sid).getGrantedAuthority();
-                this.isPrincipal = false;
-            }
-        }
-
-        public String getSid() {
-            return sid;
-        }
-
-        public void setSid(String sid) {
-            this.sid = sid;
-        }
-
-        public boolean isPrincipal() {
-            return isPrincipal;
-        }
-
-        public void setPrincipal(boolean isPrincipal) {
-            this.isPrincipal = isPrincipal;
-        }
-    }
-
-    protected static class AceInfo {
-        private SidInfo sidInfo;
-        private int permissionMask;
-
-        public AceInfo() {
-        }
-
-        public AceInfo(AccessControlEntry ace) {
-            super();
-            this.sidInfo = new SidInfo(ace.getSid());
-            this.permissionMask = ace.getPermission().getMask();
-        }
-
-        public SidInfo getSidInfo() {
-            return sidInfo;
-        }
-
-        public void setSidInfo(SidInfo sidInfo) {
-            this.sidInfo = sidInfo;
-        }
-
-        public int getPermissionMask() {
-            return permissionMask;
-        }
-
-        public void setPermissionMask(int permissionMask) {
-            this.permissionMask = permissionMask;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/service/AdminService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/AdminService.java b/server/src/main/java/org/apache/kylin/rest/service/AdminService.java
deleted file mode 100644
index 1a9ae95..0000000
--- a/server/src/main/java/org/apache/kylin/rest/service/AdminService.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.service;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Map;
-import java.util.Properties;
-
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.commons.configuration.PropertiesConfiguration;
-import org.apache.hadoop.util.ToolRunner;
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.rest.constant.Constant;
-import org.apache.kylin.rest.exception.InternalErrorException;
-import org.apache.kylin.storage.hbase.util.StorageCleanupJob;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.stereotype.Component;
-
-/**
- * @author jianliu
- */
-@Component("adminService")
-public class AdminService extends BasicService {
-    private static final Logger logger = LoggerFactory.getLogger(AdminService.class);
-
-    /**
-     * Get Java Env info as string
-     *
-     * @return
-     */
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
-    public String getEnv() {
-        logger.debug("Get Kylin Runtime environment");
-        PropertiesConfiguration tempConfig = new PropertiesConfiguration();
-
-        // Add Java Env
-
-        try {
-            String content = "";
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            // env
-            Map<String, String> env = System.getenv();
-
-            for (Map.Entry<String, String> entry : env.entrySet()) {
-                tempConfig.addProperty(entry.getKey(), entry.getValue());
-            }
-
-            // properties
-            Properties proterties = System.getProperties();
-
-            for (Map.Entry<Object, Object> entry : proterties.entrySet()) {
-                tempConfig.setProperty((String) entry.getKey(), entry.getValue());
-            }
-
-            // do save
-            tempConfig.save(baos);
-            content = baos.toString();
-            return content;
-        } catch (ConfigurationException e) {
-            throw new InternalErrorException("Failed to get Kylin env Config", e);
-        }
-    }
-
-    /**
-     * Get Java config info as String
-     *
-     * @return
-     */
-    // @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
-    public String getConfigAsString() {
-        logger.debug("Get Kylin Runtime Config");
-
-        try {
-            return KylinConfig.getInstanceFromEnv().getConfigAsString();
-        } catch (IOException e) {
-            throw new InternalErrorException("Failed to get Kylin Runtime Config", e);
-        }
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
-    public void cleanupStorage() {
-        StorageCleanupJob job = new StorageCleanupJob();
-        String[] args = new String[] { "-delete", "true" };
-        try {
-            ToolRunner.run(job, args);
-        } catch (Exception e) {
-            throw new InternalErrorException(e.getMessage(), e);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/service/BadQueryDetector.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/BadQueryDetector.java b/server/src/main/java/org/apache/kylin/rest/service/BadQueryDetector.java
deleted file mode 100644
index 79e1d4a..0000000
--- a/server/src/main/java/org/apache/kylin/rest/service/BadQueryDetector.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.service;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.NavigableSet;
-import java.util.TreeSet;
-import java.util.concurrent.ConcurrentMap;
-
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.common.util.Pair;
-import org.apache.kylin.metadata.badquery.BadQueryHistoryManager;
-import org.apache.kylin.rest.request.SQLRequest;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Maps;
-
-public class BadQueryDetector extends Thread {
-
-    private static final Logger logger = LoggerFactory.getLogger(BadQueryDetector.class);
-
-    private final ConcurrentMap<Thread, Entry> runningQueries = Maps.newConcurrentMap();
-    private final long detectionInterval;
-    private final int alertMB;
-    private final int alertRunningSec;
-    private KylinConfig kylinConfig;
-
-    private ArrayList<Notifier> notifiers = new ArrayList<Notifier>();
-
-    public BadQueryDetector() {
-        super("BadQueryDetector");
-        this.setDaemon(true);
-        this.kylinConfig = KylinConfig.getInstanceFromEnv();
-        this.detectionInterval = kylinConfig.getBadQueryDefaultDetectIntervalSeconds() * 1000;
-        this.alertMB = 100;
-        this.alertRunningSec = kylinConfig.getBadQueryDefaultAlertingSeconds();
-
-        initNotifiers();
-    }
-
-    public BadQueryDetector(long detectionInterval, int alertMB, int alertRunningSec) {
-        super("BadQueryDetector");
-        this.setDaemon(true);
-        this.detectionInterval = detectionInterval;
-        this.alertMB = alertMB;
-        this.alertRunningSec = alertRunningSec;
-        this.kylinConfig = KylinConfig.getInstanceFromEnv();
-
-        initNotifiers();
-    }
-
-    private void initNotifiers() {
-        this.notifiers.add(new LoggerNotifier());
-        if (kylinConfig.getBadQueryPersistentEnabled()) {
-            this.notifiers.add(new PersistenceNotifier());
-        }
-    }
-
-    public void registerNotifier(Notifier notifier) {
-        notifiers.add(notifier);
-    }
-
-    private void notify(String adj, float runningSec, long startTime, String project, String sql, Thread t) {
-        for (Notifier notifier : notifiers) {
-            try {
-                notifier.badQueryFound(adj, runningSec, startTime, project, sql, t);
-            } catch (Exception e) {
-                logger.error("", e);
-            }
-        }
-    }
-
-    public interface Notifier {
-        void badQueryFound(String adj, float runningSec, long startTime, String project, String sql, Thread t);
-    }
-
-    private class LoggerNotifier implements Notifier {
-        @Override
-        public void badQueryFound(String adj, float runningSec, long startTime, String project, String sql, Thread t) {
-            logger.info(adj + " query has been running " + runningSec + " seconds (project:" + project + ", thread: 0x" + Long.toHexString(t.getId()) + ") -- " + sql);
-        }
-    }
-
-    private class PersistenceNotifier implements Notifier {
-        BadQueryHistoryManager badQueryManager = BadQueryHistoryManager.getInstance(kylinConfig);
-        String serverHostname;
-        NavigableSet<Pair<Long, String>> cacheQueue = new TreeSet<>(new Comparator<Pair<Long, String>>() {
-            @Override
-            public int compare(Pair<Long, String> o1, Pair<Long, String> o2) {
-                if (o1.equals(o2)) {
-                    return 0;
-                } else if (o1.getFirst().equals(o2.getFirst())) {
-                    return o2.getSecond().compareTo(o2.getSecond());
-                } else {
-                    return (int) (o1.getFirst() - o2.getFirst());
-                }
-            }
-        });
-
-        public PersistenceNotifier() {
-            try {
-                serverHostname = InetAddress.getLocalHost().getHostName();
-            } catch (UnknownHostException e) {
-                serverHostname = "Unknow";
-                logger.warn("Error in get current hostname.", e);
-            }
-        }
-
-        @Override
-        public void badQueryFound(String adj, float runningSec, long startTime, String project, String sql, Thread t) {
-            try {
-                long cachingSeconds = (kylinConfig.getBadQueryDefaultAlertingSeconds() + 1) * 30;
-                Pair<Long, String> sqlPair = new Pair<>(startTime, sql);
-                if (!cacheQueue.contains(sqlPair)) {
-                    badQueryManager.addEntryToProject(sql, startTime, adj, runningSec, serverHostname, t.getName(), project);
-                    cacheQueue.add(sqlPair);
-                    while (!cacheQueue.isEmpty() && (System.currentTimeMillis() - cacheQueue.first().getFirst() > cachingSeconds * 1000 || cacheQueue.size() > kylinConfig.getBadQueryHistoryNum() * 3)) {
-                        cacheQueue.pollFirst();
-                    }
-                } else {
-                    badQueryManager.updateEntryToProject(sql, startTime, adj, runningSec, serverHostname, t.getName(), project);
-                }
-            } catch (IOException e) {
-                logger.error("Error in bad query persistence.", e);
-            }
-        }
-    }
-
-    public void queryStart(Thread thread, SQLRequest sqlRequest) {
-        runningQueries.put(thread, new Entry(sqlRequest, thread));
-    }
-
-    public void queryEnd(Thread thread) {
-        runningQueries.remove(thread);
-    }
-
-    private class Entry implements Comparable<Entry> {
-        final SQLRequest sqlRequest;
-        final long startTime;
-        final Thread thread;
-
-        Entry(SQLRequest sqlRequest, Thread thread) {
-            this.sqlRequest = sqlRequest;
-            this.startTime = System.currentTimeMillis();
-            this.thread = thread;
-        }
-
-        @Override
-        public int compareTo(Entry o) {
-            return (int) (this.startTime - o.startTime);
-        }
-    }
-
-    public void run() {
-        while (true) {
-            try {
-                Thread.sleep(detectionInterval);
-            } catch (InterruptedException e) {
-                // stop detection and exit
-                return;
-            }
-
-            try {
-                detectBadQuery();
-            } catch (Exception ex) {
-                logger.error("", ex);
-            }
-        }
-    }
-
-    private void detectBadQuery() {
-        long now = System.currentTimeMillis();
-        ArrayList<Entry> entries = new ArrayList<Entry>(runningQueries.values());
-        Collections.sort(entries);
-
-        // report if query running long
-        for (Entry e : entries) {
-            float runningSec = (float) (now - e.startTime) / 1000;
-            if (runningSec >= alertRunningSec) {
-                notify("Slow", runningSec, e.startTime, e.sqlRequest.getProject(), e.sqlRequest.getSql(), e.thread);
-                dumpStackTrace(e.thread);
-            } else {
-                break; // entries are sorted by startTime
-            }
-        }
-
-        // report if low memory
-        if (getSystemAvailMB() < alertMB) {
-            logger.info("System free memory less than " + alertMB + " MB. " + entries.size() + " queries running.");
-        }
-    }
-
-    // log the stack trace of bad query thread for further analysis
-    private void dumpStackTrace(Thread t) {
-        int maxStackTraceDepth = kylinConfig.getBadQueryStackTraceDepth();
-        int current = 0;
-
-        StackTraceElement[] stackTrace = t.getStackTrace();
-        StringBuilder buf = new StringBuilder("Problematic thread 0x" + Long.toHexString(t.getId()));
-        buf.append("\n");
-        for (StackTraceElement e : stackTrace) {
-            if (++current > maxStackTraceDepth) {
-                break;
-            }
-            buf.append("\t").append("at ").append(e.toString()).append("\n");
-        }
-        logger.info(buf.toString());
-    }
-
-    public static final int ONE_MB = 1024 * 1024;
-
-    public static long getSystemAvailBytes() {
-        Runtime runtime = Runtime.getRuntime();
-        long totalMemory = runtime.totalMemory(); // current heap allocated to the VM process
-        long freeMemory = runtime.freeMemory(); // out of the current heap, how much is free
-        long maxMemory = runtime.maxMemory(); // Max heap VM can use e.g. Xmx setting
-        long usedMemory = totalMemory - freeMemory; // how much of the current heap the VM is using
-        long availableMemory = maxMemory - usedMemory; // available memory i.e. Maximum heap size minus the current amount used
-        return availableMemory;
-    }
-
-    public static int getSystemAvailMB() {
-        return (int) (getSystemAvailBytes() / ONE_MB);
-    }
-
-}


[10/13] kylin git commit: KYLIN-1823 split code from kylin-server into kylin-server-base

Posted by li...@apache.org.
http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/JobBuildRequest2.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/JobBuildRequest2.java b/server-base/src/main/java/org/apache/kylin/rest/request/JobBuildRequest2.java
new file mode 100644
index 0000000..dc3b433
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/JobBuildRequest2.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.request;
+
+public class JobBuildRequest2 {
+
+    private long startSourceOffset;
+
+    private long endSourceOffset;
+
+    private String buildType;
+
+    private boolean force;
+
+    public long getStartSourceOffset() {
+        return startSourceOffset;
+    }
+
+    public void setStartSourceOffset(long startSourceOffset) {
+        this.startSourceOffset = startSourceOffset;
+    }
+
+    public long getEndSourceOffset() {
+        return endSourceOffset;
+    }
+
+    public void setEndSourceOffset(long endSourceOffset) {
+        this.endSourceOffset = endSourceOffset;
+    }
+
+    public String getBuildType() {
+        return buildType;
+    }
+
+    public void setBuildType(String buildType) {
+        this.buildType = buildType;
+    }
+
+    public boolean isForce() {
+        return force;
+    }
+
+    public void setForce(boolean force) {
+        this.force = force;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/JobListRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/JobListRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/JobListRequest.java
new file mode 100644
index 0000000..51160d2
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/JobListRequest.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.request;
+
+import java.util.List;
+
+/**
+ * @author xduo
+ * 
+ */
+public class JobListRequest {
+
+    private List<Integer> status;
+    private String cubeName;
+    private String projectName;
+    private Integer offset;
+    private Integer limit;
+    private Integer timeFilter;
+
+    public JobListRequest() {
+    }
+
+    public List<Integer> getStatus() {
+        return status;
+    }
+
+    public void setStatus(List<Integer> status) {
+        this.status = status;
+    }
+
+    public String getCubeName() {
+        return cubeName;
+    }
+
+    public void setCubeName(String cubeName) {
+        this.cubeName = cubeName;
+    }
+
+    public String getProjectName() {
+        return projectName;
+    }
+
+    public void setProjectName(String projectName) {
+        this.projectName = projectName;
+    }
+
+    public Integer getOffset() {
+        return offset;
+    }
+
+    public void setOffset(Integer offset) {
+        this.offset = offset;
+    }
+
+    public Integer getLimit() {
+        return limit;
+    }
+
+    public void setLimit(Integer limit) {
+        this.limit = limit;
+    }
+
+    public Integer getTimeFilter() {
+        return timeFilter;
+    }
+
+    public void setTimeFilter(Integer timeFilter) {
+        this.timeFilter = timeFilter;
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/MetaRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/MetaRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/MetaRequest.java
new file mode 100644
index 0000000..66e8ec0
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/MetaRequest.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.request;
+
+/**
+ */
+public class MetaRequest {
+
+    private String project;
+
+    public MetaRequest() {
+    }
+
+    public MetaRequest(String project) {
+        this.project = project;
+    }
+
+    public String getProject() {
+        return project;
+    }
+
+    public void setProject(String project) {
+        this.project = project;
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/MetricsRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/MetricsRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/MetricsRequest.java
new file mode 100644
index 0000000..daee8f0
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/MetricsRequest.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.request;
+
+import java.util.Date;
+
+/**
+ * @author xduo
+ * 
+ */
+public class MetricsRequest {
+
+    private Date startTime;
+
+    private Date endTime;
+
+    private String account;
+
+    public Date getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(Date startTime) {
+        this.startTime = startTime;
+    }
+
+    public Date getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(Date endTime) {
+        this.endTime = endTime;
+    }
+
+    public String getAccount() {
+        return account;
+    }
+
+    public void setAccount(String account) {
+        this.account = account;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/ModelRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/ModelRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/ModelRequest.java
new file mode 100644
index 0000000..dc8e06e
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/ModelRequest.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.request;
+
+public class ModelRequest {
+
+    private String uuid;
+    private String modelName;
+    private String modelDescData;
+    private boolean successful;
+    private String message;
+    private String project;
+
+    public String getUuid() {
+        return uuid;
+    }
+
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+
+    /**
+     * @return the message
+     */
+    public String getMessage() {
+        return message;
+    }
+
+    /**
+     * @param message
+     *            the message to set
+     */
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    /**
+     * @return the status
+     */
+    public boolean getSuccessful() {
+        return successful;
+    }
+
+    /**
+     * @param status
+     *            the status to set
+     */
+    public void setSuccessful(boolean status) {
+        this.successful = status;
+    }
+
+    public ModelRequest() {
+    }
+
+    public ModelRequest(String modelName, String modelDescData) {
+        this.modelName = modelName;
+        this.modelDescData = modelDescData;
+    }
+
+    public String getModelDescData() {
+        return modelDescData;
+    }
+
+    public void setModelDescData(String modelDescData) {
+        this.modelDescData = modelDescData;
+    }
+
+    /**
+     * @return the modelName
+     */
+    public String getModelName() {
+        return modelName;
+    }
+
+    /**
+     * @param modelName
+     *            the cubeName to set
+     */
+    public void setModelName(String modelName) {
+        this.modelName = modelName;
+    }
+
+    public String getProject() {
+        return project;
+    }
+
+    public void setProject(String project) {
+        this.project = project;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/PrepareSqlRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/PrepareSqlRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/PrepareSqlRequest.java
new file mode 100644
index 0000000..95bc2f5
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/PrepareSqlRequest.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.request;
+
+import java.util.Arrays;
+
+/**
+ * @author xduo
+ * 
+ */
+public class PrepareSqlRequest extends SQLRequest {
+
+    public PrepareSqlRequest() {
+        super();
+    }
+
+    private StateParam[] params;
+
+    public StateParam[] getParams() {
+        return params;
+    }
+
+    public void setParams(StateParam[] params) {
+        this.params = params;
+    }
+
+    public static class StateParam {
+        private String className;
+        private String value;
+
+        public StateParam() {
+        }
+
+        public String getClassName() {
+            return className;
+        }
+
+        public void setClassName(String className) {
+            this.className = className;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        public void setValue(String value) {
+            this.value = value;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((className == null) ? 0 : className.hashCode());
+            result = prime * result + ((value == null) ? 0 : value.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            StateParam other = (StateParam) obj;
+            if (className == null) {
+                if (other.className != null)
+                    return false;
+            } else if (!className.equals(other.className))
+                return false;
+            if (value == null) {
+                if (other.value != null)
+                    return false;
+            } else if (!value.equals(other.value))
+                return false;
+            return true;
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = super.hashCode();
+        result = prime * result + ((params == null) ? 0 : Arrays.hashCode(params));
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        if (!super.equals(obj))
+            return false;
+        PrepareSqlRequest other = (PrepareSqlRequest) obj;
+        if (!Arrays.equals(params, other.params))
+            return false;
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/SQLRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/SQLRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/SQLRequest.java
new file mode 100644
index 0000000..96f5faa
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/SQLRequest.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.request;
+
+import java.io.Serializable;
+import java.util.Map;
+
+public class SQLRequest implements Serializable {
+    protected static final long serialVersionUID = 1L;
+
+    private String sql;
+    private String project;
+    private Integer offset = 0;
+    private Integer limit = 0;
+    private boolean acceptPartial = false;
+
+    private Map<String, String> backdoorToggles;
+
+    public SQLRequest() {
+    }
+
+    public Map<String, String> getBackdoorToggles() {
+        return backdoorToggles;
+    }
+
+    public void setBackdoorToggles(Map<String, String> backdoorToggles) {
+        this.backdoorToggles = backdoorToggles;
+    }
+
+    public String getProject() {
+        return project;
+    }
+
+    public void setProject(String project) {
+        this.project = project;
+    }
+
+    public String getSql() {
+        return sql;
+    }
+
+    public void setSql(String sql) {
+        this.sql = sql;
+    }
+
+    public Integer getOffset() {
+        return offset;
+    }
+
+    public void setOffset(Integer offset) {
+        this.offset = offset;
+    }
+
+    public Integer getLimit() {
+        return limit;
+    }
+
+    public void setLimit(Integer limit) {
+        this.limit = limit;
+    }
+
+    public boolean isAcceptPartial() {
+        return acceptPartial;
+    }
+
+    public void setAcceptPartial(boolean acceptPartial) {
+        this.acceptPartial = acceptPartial;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (acceptPartial ? 1231 : 1237);
+        result = prime * result + ((offset == null) ? 0 : offset.hashCode());
+        result = prime * result + ((limit == null) ? 0 : limit.hashCode());
+        result = prime * result + ((project == null) ? 0 : project.hashCode());
+        result = prime * result + ((sql == null) ? 0 : sql.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        SQLRequest other = (SQLRequest) obj;
+        if (acceptPartial != other.acceptPartial)
+            return false;
+        if (offset == null) {
+            if (other.offset != null)
+                return false;
+        } else if (!offset.equals(other.offset))
+            return false;
+        if (limit == null) {
+            if (other.limit != null)
+                return false;
+        } else if (!limit.equals(other.limit))
+            return false;
+        if (project == null) {
+            if (other.project != null)
+                return false;
+        } else if (!project.equals(other.project))
+            return false;
+        if (sql == null) {
+            if (other.sql != null)
+                return false;
+        } else if (!sql.equals(other.sql))
+            return false;
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/SaveSqlRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/SaveSqlRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/SaveSqlRequest.java
new file mode 100644
index 0000000..affab1c
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/SaveSqlRequest.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.request;
+
+/**
+ * @author xduo
+ * 
+ */
+public class SaveSqlRequest {
+    private long id;
+    private String name;
+    private String sql;
+    private String project;
+    private String description;
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getSql() {
+        return sql;
+    }
+
+    public void setSql(String sql) {
+        this.sql = sql;
+    }
+
+    public String getProject() {
+        return project;
+    }
+
+    public void setProject(String project) {
+        this.project = project;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/StreamingRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/StreamingRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/StreamingRequest.java
new file mode 100644
index 0000000..96db4da
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/StreamingRequest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.request;
+
+public class StreamingRequest {
+
+    private String project;
+
+    private String tableData;
+
+    private String streamingConfig;
+
+    private String kafkaConfig;
+
+    private boolean successful;
+
+    private String message;
+
+    public String getProject() {
+        return project;
+    }
+
+    public void setProject(String project) {
+        this.project = project;
+    }
+
+    public String getTableData() {
+        return tableData;
+    }
+
+    public void setTableData(String tableData) {
+        this.tableData = tableData;
+    }
+
+    public boolean isSuccessful() {
+        return successful;
+    }
+
+    public void setSuccessful(boolean successful) {
+        this.successful = successful;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public String getStreamingConfig() {
+        return streamingConfig;
+    }
+
+    public void setStreamingConfig(String streamingConfig) {
+        this.streamingConfig = streamingConfig;
+    }
+
+    public String getKafkaConfig() {
+        return kafkaConfig;
+    }
+
+    public void setKafkaConfig(String kafkaConfig) {
+        this.kafkaConfig = kafkaConfig;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/UpdateConfigRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/UpdateConfigRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/UpdateConfigRequest.java
new file mode 100644
index 0000000..50f7f9b
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/UpdateConfigRequest.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.request;
+
+/**
+ * @author xduo
+ * 
+ */
+public class UpdateConfigRequest {
+    private String key;
+
+    private String value;
+
+    public String getKey() {
+        return key;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java
new file mode 100644
index 0000000..29ba162
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/UpdateProjectRequest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.request;
+
+/**
+ */
+public class UpdateProjectRequest {
+    private String formerProjectName;
+    private String newProjectName;
+    private String newDescription;
+
+    public UpdateProjectRequest() {
+    }
+
+    public String getFormerProjectName() {
+        return formerProjectName;
+    }
+
+    public void setFormerProjectName(String formerProjectName) {
+
+        this.formerProjectName = formerProjectName;
+    }
+
+    public String getNewDescription() {
+        return newDescription;
+    }
+
+    public void setNewDescription(String newDescription) {
+        this.newDescription = newDescription;
+    }
+
+    public String getNewProjectName() {
+        return newProjectName;
+    }
+
+    public void setNewProjectName(String newProjectName) {
+        this.newProjectName = newProjectName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/response/AccessEntryResponse.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/response/AccessEntryResponse.java b/server-base/src/main/java/org/apache/kylin/rest/response/AccessEntryResponse.java
new file mode 100644
index 0000000..5c55d58
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/response/AccessEntryResponse.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.response;
+
+import java.io.Serializable;
+
+import org.springframework.security.acls.model.Permission;
+import org.springframework.security.acls.model.Sid;
+import org.springframework.util.Assert;
+
+/**
+ * @author xduo
+ * 
+ */
+public class AccessEntryResponse {
+
+    private Permission permission;
+    private Serializable id;
+    private Sid sid;
+    private boolean granting;
+
+    public AccessEntryResponse() {
+    }
+
+    public AccessEntryResponse(Serializable id, Sid sid, Permission permission, boolean granting) {
+        Assert.notNull(sid, "Sid required");
+        Assert.notNull(permission, "Permission required");
+        this.id = id;
+        this.sid = sid;
+        this.permission = permission;
+        this.granting = granting;
+    }
+
+    public Permission getPermission() {
+        return permission;
+    }
+
+    public void setPermission(Permission permission) {
+        this.permission = permission;
+    }
+
+    public Serializable getId() {
+        return id;
+    }
+
+    public Sid getSid() {
+        return sid;
+    }
+
+    public boolean isGranting() {
+        return granting;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/response/ErrorResponse.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/response/ErrorResponse.java b/server-base/src/main/java/org/apache/kylin/rest/response/ErrorResponse.java
new file mode 100644
index 0000000..3327cc0
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/response/ErrorResponse.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.response;
+
+/**
+ * @author xduo
+ * 
+ */
+public class ErrorResponse {
+
+    public String url;
+    public String exception;
+
+    /**
+     * @param exception
+     */
+    public ErrorResponse(String url, Exception exception) {
+        this.url = url;
+        this.exception = exception.getLocalizedMessage();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/response/GeneralResponse.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/response/GeneralResponse.java b/server-base/src/main/java/org/apache/kylin/rest/response/GeneralResponse.java
new file mode 100644
index 0000000..bc7c081
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/response/GeneralResponse.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.response;
+
+import java.util.Properties;
+
+/**
+ * @author xduo
+ * 
+ */
+public class GeneralResponse extends Properties {
+
+    private static final long serialVersionUID = -6540990247122312493L;
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/response/HBaseResponse.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/response/HBaseResponse.java b/server-base/src/main/java/org/apache/kylin/rest/response/HBaseResponse.java
new file mode 100644
index 0000000..607d61a
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/response/HBaseResponse.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.response;
+
+import java.io.Serializable;
+
+public class HBaseResponse implements Serializable {
+    private static final long serialVersionUID = 7263557115683263492L;
+    private String tableName;
+    private long tableSize;
+    private int regionCount;
+    private long dateRangeStart;
+    private long dateRangeEnd;
+
+    public HBaseResponse() {
+    }
+
+    /**
+     * @return The hbase table name.
+     */
+    public String getTableName() {
+        return tableName;
+    }
+
+    /**
+     * @param tableName
+     *            The hbase table name.
+     */
+    public void setTableName(String tableName) {
+        this.tableName = tableName;
+    }
+
+    /**
+     * @return the tableSize
+     */
+    public long getTableSize() {
+        return tableSize;
+    }
+
+    /**
+     * @param tableSize
+     *            the tableSize to set
+     */
+    public void setTableSize(long tableSize) {
+        this.tableSize = tableSize;
+    }
+
+    /**
+     * @return the regionCount
+     */
+    public int getRegionCount() {
+        return regionCount;
+    }
+
+    /**
+     * @param regionCount
+     *            the regionCount to set
+     */
+    public void setRegionCount(int regionCount) {
+        this.regionCount = regionCount;
+    }
+
+    /**
+     * @return the segmentStartTime
+     */
+    public long getDateRangeStart() {
+        return dateRangeStart;
+    }
+
+    /**
+     * @param segmentStartTime
+     *            the segmentStartTime to set
+     */
+    public void setDateRangeStart(long dateRangeStart) {
+        this.dateRangeStart = dateRangeStart;
+    }
+
+    /**
+     * @return the segmentEndTime
+     */
+    public long getDateRangeEnd() {
+        return dateRangeEnd;
+    }
+
+    /**
+     * @param segmentEndTime
+     *            the segmentEndTime to set
+     */
+    public void setDateRangeEnd(long dateRangeEnd) {
+        this.dateRangeEnd = dateRangeEnd;
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/response/MetricsResponse.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/response/MetricsResponse.java b/server-base/src/main/java/org/apache/kylin/rest/response/MetricsResponse.java
new file mode 100644
index 0000000..34cdfcb
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/response/MetricsResponse.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.response;
+
+import java.util.HashMap;
+
+/**
+ * @author xduo
+ * 
+ */
+public class MetricsResponse extends HashMap<String, Float> {
+
+    private static final long serialVersionUID = 1L;
+
+    public void increase(String key) {
+        increase(key, (float) 1);
+    }
+
+    public void increase(String key, Float increased) {
+        if (this.containsKey(key)) {
+            this.put(key, (this.get(key) + increased));
+        } else {
+            this.put(key, increased);
+        }
+    }
+
+    public void decrease(String key) {
+        decrease(key, (float) 1);
+    }
+
+    public void decrease(String key, Float decreased) {
+        if (this.containsKey(key)) {
+            this.put(key, (this.get(key) - decreased));
+        } else {
+            this.put(key, decreased);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/response/SQLResponse.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/response/SQLResponse.java b/server-base/src/main/java/org/apache/kylin/rest/response/SQLResponse.java
new file mode 100644
index 0000000..9c4e9da
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/response/SQLResponse.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.response;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.apache.kylin.rest.model.SelectedColumnMeta;
+
+public class SQLResponse implements Serializable {
+    protected static final long serialVersionUID = 1L;
+
+    // private static final Logger logger =
+    // LoggerFactory.getLogger(SQLResponse.class);
+
+    // the data type for each column
+    protected List<SelectedColumnMeta> columnMetas;
+
+    // the results rows, each row contains several columns
+    protected List<List<String>> results;
+
+    /**
+     * for historical reasons it is named "cube", however it might also refer to any realizations like hybrid, II or etc.
+     */
+    protected String cube;
+
+    // if not select query, only return affected row count
+    protected int affectedRowCount;
+
+    // flag indicating whether an exception occurred
+    protected boolean isException;
+
+    // if isException, the detailed exception message
+    protected String exceptionMessage;
+
+    protected long duration;
+
+    protected boolean isPartial = false;
+
+    protected long totalScanCount;
+
+    protected boolean hitExceptionCache = false;
+
+    protected boolean storageCacheUsed = false;
+
+    public SQLResponse() {
+    }
+
+    public SQLResponse(List<SelectedColumnMeta> columnMetas, List<List<String>> results, int affectedRowCount, boolean isException, String exceptionMessage) {
+        this.columnMetas = columnMetas;
+        this.results = results;
+        this.affectedRowCount = affectedRowCount;
+        this.isException = isException;
+        this.exceptionMessage = exceptionMessage;
+    }
+
+    public SQLResponse(List<SelectedColumnMeta> columnMetas, List<List<String>> results, String cube, int affectedRowCount, boolean isException, String exceptionMessage) {
+        this.columnMetas = columnMetas;
+        this.results = results;
+        this.cube = cube;
+        this.affectedRowCount = affectedRowCount;
+        this.isException = isException;
+        this.exceptionMessage = exceptionMessage;
+    }
+
+    public SQLResponse(List<SelectedColumnMeta> columnMetas, List<List<String>> results, String cube, int affectedRowCount, boolean isException, String exceptionMessage, boolean isPartial) {
+        this.columnMetas = columnMetas;
+        this.results = results;
+        this.cube = cube;
+        this.affectedRowCount = affectedRowCount;
+        this.isException = isException;
+        this.exceptionMessage = exceptionMessage;
+        this.isPartial = isPartial;
+    }
+
+    public List<SelectedColumnMeta> getColumnMetas() {
+        return columnMetas;
+    }
+
+    public List<List<String>> getResults() {
+        return results;
+    }
+
+    public void setResults(List<List<String>> results) {
+        this.results = results;
+    }
+
+    public String getCube() {
+        return cube;
+    }
+
+    public void setCube(String cube) {
+        this.cube = cube;
+    }
+
+    public int getAffectedRowCount() {
+        return affectedRowCount;
+    }
+
+    public boolean getIsException() {
+        return isException;
+    }
+
+    public void setIsException(boolean v) {
+        isException = v;
+    }
+
+    public String getExceptionMessage() {
+        return exceptionMessage;
+    }
+
+    public void setExceptionMessage(String msg) {
+        exceptionMessage = msg;
+    }
+
+    public long getDuration() {
+        return duration;
+    }
+
+    public void setDuration(long duration) {
+        this.duration = duration;
+    }
+
+    public boolean isPartial() {
+
+        return isPartial;
+    }
+
+    public long getTotalScanCount() {
+        return totalScanCount;
+    }
+
+    public void setTotalScanCount(long totalScanCount) {
+        this.totalScanCount = totalScanCount;
+    }
+
+    public boolean isHitExceptionCache() {
+        return hitExceptionCache;
+    }
+
+    public void setHitExceptionCache(boolean hitExceptionCache) {
+        this.hitExceptionCache = hitExceptionCache;
+    }
+
+    public boolean isStorageCacheUsed() {
+        return storageCacheUsed;
+    }
+
+    public void setStorageCacheUsed(boolean storageCacheUsed) {
+        this.storageCacheUsed = storageCacheUsed;
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/response/TableDescResponse.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/response/TableDescResponse.java b/server-base/src/main/java/org/apache/kylin/rest/response/TableDescResponse.java
new file mode 100644
index 0000000..c3b1e7c
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/response/TableDescResponse.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.response;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.kylin.metadata.model.TableDesc;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * A response class to wrap TableDesc
+ * 
+ * @author jianliu
+ * 
+ */
+public class TableDescResponse extends TableDesc {
+    @JsonProperty("exd")
+    Map<String, String> descExd = new HashMap<String, String>();
+    @JsonProperty("cardinality")
+    Map<String, Long> cardinality = new HashMap<String, Long>();
+
+    /**
+     * @return the cardinality
+     */
+    public Map<String, Long> getCardinality() {
+        return cardinality;
+    }
+
+    /**
+     * @param cardinality
+     *            the cardinality to set
+     */
+    public void setCardinality(Map<String, Long> cardinality) {
+        this.cardinality = cardinality;
+    }
+
+    /**
+     * @return the descExd
+     */
+    public Map<String, String> getDescExd() {
+        return descExd;
+    }
+
+    /**
+     * @param descExd
+     *            the descExd to set
+     */
+    public void setDescExd(Map<String, String> descExd) {
+        this.descExd = descExd;
+    }
+
+    /**
+     * @param table
+     */
+    public TableDescResponse(TableDesc table) {
+        this.setColumns(table.getColumns());
+        this.setDatabase(table.getDatabase());
+        this.setName(table.getName());
+        this.setSourceType(table.getSourceType());
+        this.setUuid(table.getUuid());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/security/AclEntityFactory.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/AclEntityFactory.java b/server-base/src/main/java/org/apache/kylin/rest/security/AclEntityFactory.java
new file mode 100644
index 0000000..621fbe4
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/security/AclEntityFactory.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.security;
+
+import org.apache.kylin.common.persistence.RootPersistentEntity;
+import org.apache.kylin.cube.CubeInstance;
+import org.apache.kylin.job.JobInstance;
+import org.apache.kylin.metadata.model.DataModelDesc;
+import org.apache.kylin.metadata.project.ProjectInstance;
+
+/**
+ * @author xduo
+ * 
+ */
+public class AclEntityFactory {
+
+    public static RootPersistentEntity createAclEntity(String entityType, String uuid) {
+        if ("CubeInstance".equals(entityType)) {
+            CubeInstance cubeInstance = new CubeInstance();
+            cubeInstance.setUuid(uuid);
+
+            return cubeInstance;
+        }
+
+        if ("DataModelDesc".equals(entityType)) {
+            DataModelDesc modelInstance = new DataModelDesc();
+            modelInstance.setUuid(uuid);
+
+            return modelInstance;
+        }
+
+        if ("JobInstance".equals(entityType)) {
+            JobInstance jobInstance = new JobInstance();
+            jobInstance.setUuid(uuid);
+
+            return jobInstance;
+        }
+
+        if ("ProjectInstance".equals(entityType)) {
+            ProjectInstance projectInstance = new ProjectInstance();
+            projectInstance.setUuid(uuid);
+
+            return projectInstance;
+        }
+
+        throw new RuntimeException("Unsupported entity type!");
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/security/AclHBaseStorage.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/AclHBaseStorage.java b/server-base/src/main/java/org/apache/kylin/rest/security/AclHBaseStorage.java
new file mode 100644
index 0000000..38f299e
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/security/AclHBaseStorage.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.security;
+
+import java.io.IOException;
+
+import org.apache.hadoop.hbase.client.HTableInterface;
+
+/**
+ */
+public interface AclHBaseStorage {
+    String DEFAULT_TABLE_PREFIX = "kylin_metadata";
+
+    String ACL_INFO_FAMILY = "i";
+    String ACL_ACES_FAMILY = "a";
+    String ACL_TABLE_NAME = "_acl";
+
+    String USER_AUTHORITY_FAMILY = "a";
+    String USER_TABLE_NAME = "_user";
+    String USER_AUTHORITY_COLUMN = "c";
+
+    String prepareHBaseTable(Class<?> clazz) throws IOException;
+
+    HTableInterface getTable(String tableName) throws IOException;
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/security/AclPermission.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/AclPermission.java b/server-base/src/main/java/org/apache/kylin/rest/security/AclPermission.java
new file mode 100644
index 0000000..4e2e182
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/security/AclPermission.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.security;
+
+import org.springframework.security.acls.domain.BasePermission;
+import org.springframework.security.acls.model.Permission;
+
+/**
+ * @author xduo
+ * 
+ */
+public class AclPermission extends BasePermission {
+
+    private static final long serialVersionUID = 6121785617686149123L;
+
+    public static final Permission MANAGEMENT = new AclPermission(1 << 5, 'M'); // 32
+    public static final Permission OPERATION = new AclPermission(1 << 6, 'O'); // 64
+
+    protected AclPermission(int mask) {
+        super(mask);
+    }
+
+    protected AclPermission(int mask, char code) {
+        super(mask, code);
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/security/AclPermissionFactory.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/AclPermissionFactory.java b/server-base/src/main/java/org/apache/kylin/rest/security/AclPermissionFactory.java
new file mode 100644
index 0000000..d662403
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/security/AclPermissionFactory.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.security;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.security.acls.domain.DefaultPermissionFactory;
+import org.springframework.security.acls.model.Permission;
+
+/**
+ * @author xduo
+ * 
+ */
+public class AclPermissionFactory extends DefaultPermissionFactory {
+
+    public AclPermissionFactory() {
+        super();
+        registerPublicPermissions(AclPermission.class);
+    }
+
+    public static List<Permission> getPermissions() {
+        List<Permission> permissions = new ArrayList<Permission>();
+        Field[] fields = AclPermission.class.getFields();
+
+        for (Field field : fields) {
+            try {
+                Object fieldValue = field.get(null);
+
+                if (Permission.class.isAssignableFrom(fieldValue.getClass())) {
+                    // Found a Permission static field
+                    permissions.add((Permission) fieldValue);
+                }
+            } catch (Exception ignore) {
+                //ignore on purpose
+            }
+        }
+
+        return permissions;
+    }
+
+    public static Permission getPermission(String perName) {
+        Field[] fields = AclPermission.class.getFields();
+
+        for (Field field : fields) {
+            try {
+                Object fieldValue = field.get(null);
+
+                if (Permission.class.isAssignableFrom(fieldValue.getClass())) {
+                    // Found a Permission static field
+                    if (perName.equals(field.getName())) {
+                        return (Permission) fieldValue;
+                    }
+                }
+            } catch (Exception ignore) {
+                //ignore on purpose
+            }
+        }
+
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/security/AuthoritiesPopulator.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/AuthoritiesPopulator.java b/server-base/src/main/java/org/apache/kylin/rest/security/AuthoritiesPopulator.java
new file mode 100644
index 0000000..7983fc0
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/security/AuthoritiesPopulator.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.security;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.kylin.rest.constant.Constant;
+import org.springframework.ldap.core.ContextSource;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator;
+
+/**
+ * @author xduo
+ * 
+ */
+public class AuthoritiesPopulator extends DefaultLdapAuthoritiesPopulator {
+
+    String adminRole;
+    SimpleGrantedAuthority adminRoleAsAuthority;
+
+    SimpleGrantedAuthority adminAuthority = new SimpleGrantedAuthority(Constant.ROLE_ADMIN);
+    SimpleGrantedAuthority modelerAuthority = new SimpleGrantedAuthority(Constant.ROLE_MODELER);
+    SimpleGrantedAuthority analystAuthority = new SimpleGrantedAuthority(Constant.ROLE_ANALYST);
+
+    Set<GrantedAuthority> defaultAuthorities = new HashSet<GrantedAuthority>();
+
+    /**
+     * @param contextSource
+     * @param groupSearchBase
+     */
+    public AuthoritiesPopulator(ContextSource contextSource, String groupSearchBase, String adminRole, String defaultRole) {
+        super(contextSource, groupSearchBase);
+        this.adminRole = adminRole;
+        this.adminRoleAsAuthority = new SimpleGrantedAuthority(adminRole);
+
+        if (defaultRole.contains(Constant.ROLE_MODELER))
+            this.defaultAuthorities.add(modelerAuthority);
+        if (defaultRole.contains(Constant.ROLE_ANALYST))
+            this.defaultAuthorities.add(analystAuthority);
+    }
+
+    @Override
+    public Set<GrantedAuthority> getGroupMembershipRoles(String userDn, String username) {
+        Set<GrantedAuthority> authorities = super.getGroupMembershipRoles(userDn, username);
+
+        if (authorities.contains(adminRoleAsAuthority)) {
+            authorities.add(adminAuthority);
+            authorities.add(modelerAuthority);
+            authorities.add(analystAuthority);
+        }
+
+        authorities.addAll(defaultAuthorities);
+
+        return authorities;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/security/CrossDomainFilter.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/CrossDomainFilter.java b/server-base/src/main/java/org/apache/kylin/rest/security/CrossDomainFilter.java
new file mode 100644
index 0000000..7d9d9ac
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/security/CrossDomainFilter.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.security;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.kylin.common.KylinConfig;
+
+/**
+ * @author xduo
+ * 
+ */
+public class CrossDomainFilter implements Filter {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
+     */
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
+     * javax.servlet.ServletResponse, javax.servlet.FilterChain)
+     */
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+        if (KylinConfig.getInstanceFromEnv().isWebCrossDomainEnabled()) {
+            ((HttpServletResponse) response).addHeader("Access-Control-Allow-Origin", "*");
+            ((HttpServletResponse) response).addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
+            ((HttpServletResponse) response).addHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With, Accept, Authorization");
+        }
+
+        chain.doFilter(request, response);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see javax.servlet.Filter#destroy()
+     */
+    @Override
+    public void destroy() {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/security/KylinAuthenticationProvider.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/KylinAuthenticationProvider.java b/server-base/src/main/java/org/apache/kylin/rest/security/KylinAuthenticationProvider.java
new file mode 100644
index 0000000..d0dd06a
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/security/KylinAuthenticationProvider.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.security;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+
+import org.apache.kylin.rest.service.UserService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.AuthenticationProvider;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.util.Assert;
+
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheManager;
+import net.sf.ehcache.Element;
+
+/**
+ * A wrapper class for the authentication provider; Will do something more for Kylin.
+ */
+public class KylinAuthenticationProvider implements AuthenticationProvider {
+
+    private static final Logger logger = LoggerFactory.getLogger(KylinAuthenticationProvider.class);
+
+    @Autowired
+    UserService userService;
+
+    @Autowired
+    private CacheManager cacheManager;
+
+    //Embedded authentication provider
+    private AuthenticationProvider authenticationProvider;
+
+    MessageDigest md = null;
+
+    public KylinAuthenticationProvider(AuthenticationProvider authenticationProvider) {
+        super();
+        Assert.notNull(authenticationProvider, "The embedded authenticationProvider should not be null.");
+        this.authenticationProvider = authenticationProvider;
+        try {
+            md = MessageDigest.getInstance("MD5");
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException("Failed to init Message Digest ", e);
+        }
+    }
+
+    @Override
+    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+        Authentication authed = null;
+        Cache userCache = cacheManager.getCache("UserCache");
+        md.reset();
+        byte[] hashKey = md.digest((authentication.getName() + authentication.getCredentials()).getBytes());
+        String userKey = Arrays.toString(hashKey);
+
+        Element authedUser = userCache.get(userKey);
+        if (null != authedUser) {
+            authed = (Authentication) authedUser.getObjectValue();
+            SecurityContextHolder.getContext().setAuthentication(authed);
+        } else {
+            try {
+                authed = authenticationProvider.authenticate(authentication);
+                userCache.put(new Element(userKey, authed));
+            } catch (AuthenticationException e) {
+                logger.error("Failed to auth user: " + authentication.getName(), e);
+                throw e;
+            }
+
+            logger.debug("Authenticated user " + authed.toString());
+
+            UserDetails user;
+
+            if (authed.getDetails() == null) {
+                //authed.setAuthenticated(false);
+                throw new UsernameNotFoundException("User not found in LDAP, check whether he/she has been added to the groups.");
+            }
+
+            if (authed.getDetails() instanceof UserDetails) {
+                user = (UserDetails) authed.getDetails();
+            } else {
+                user = new User(authentication.getName(), "skippped-ldap", authed.getAuthorities());
+            }
+            Assert.notNull(user, "The UserDetail is null.");
+
+            logger.debug("User authorities :" + user.getAuthorities());
+            if (!userService.userExists(user.getUsername())) {
+                userService.createUser(user);
+            } else {
+                userService.updateUser(user);
+            }
+        }
+
+        return authed;
+    }
+
+    @Override
+    public boolean supports(Class<?> authentication) {
+        return authenticationProvider.supports(authentication);
+    }
+
+    public AuthenticationProvider getAuthenticationProvider() {
+        return authenticationProvider;
+    }
+
+    public void setAuthenticationProvider(AuthenticationProvider authenticationProvider) {
+        this.authenticationProvider = authenticationProvider;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/security/LdapProvider.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/LdapProvider.java b/server-base/src/main/java/org/apache/kylin/rest/security/LdapProvider.java
new file mode 100644
index 0000000..2c5fe50
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/security/LdapProvider.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.security;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+
+import org.apache.kylin.rest.service.UserService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
+import org.springframework.security.ldap.authentication.LdapAuthenticator;
+import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
+
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheManager;
+import net.sf.ehcache.Element;
+
+/**
+ * @author xduo
+ * @deprecated replaced by KylinAuthenticationProvider
+ * 
+ */
+public class LdapProvider extends LdapAuthenticationProvider {
+
+    private static final Logger logger = LoggerFactory.getLogger(LdapProvider.class);
+
+    @Autowired
+    UserService userService;
+
+    @Autowired
+    private CacheManager cacheManager;
+
+    MessageDigest md = null;
+
+    /**
+     * @param authenticator
+     * @param authoritiesPopulator
+     */
+    public LdapProvider(LdapAuthenticator authenticator, LdapAuthoritiesPopulator authoritiesPopulator) {
+        super(authenticator, authoritiesPopulator);
+
+        try {
+            md = MessageDigest.getInstance("MD5");
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException("Failed to init Message Digest ", e);
+        }
+    }
+
+    @Override
+    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+        Authentication authed = null;
+        Cache userCache = cacheManager.getCache("UserCache");
+        md.reset();
+        byte[] hashKey = md.digest((authentication.getName() + authentication.getCredentials()).getBytes());
+        String userKey = Arrays.toString(hashKey);
+
+        Element authedUser = userCache.get(userKey);
+        if (null != authedUser) {
+            authed = (Authentication) authedUser.getObjectValue();
+            SecurityContextHolder.getContext().setAuthentication(authed);
+        } else {
+            try {
+                authed = super.authenticate(authentication);
+                userCache.put(new Element(userKey, authed));
+            } catch (AuthenticationException e) {
+                logger.error("Failed to auth user: " + authentication.getName(), e);
+                throw e;
+            }
+
+            UserDetails user = new User(authentication.getName(), "skippped-ldap", authed.getAuthorities());
+
+            if (!userService.userExists(authentication.getName())) {
+                userService.createUser(user);
+            } else {
+                userService.updateUser(user);
+            }
+        }
+
+        return authed;
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/security/MockAclHBaseStorage.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/MockAclHBaseStorage.java b/server-base/src/main/java/org/apache/kylin/rest/security/MockAclHBaseStorage.java
new file mode 100644
index 0000000..6c8081d
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/security/MockAclHBaseStorage.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.security;
+
+import java.io.IOException;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.rest.service.AclService;
+import org.apache.kylin.rest.service.UserService;
+
+/**
+ */
+public class MockAclHBaseStorage implements AclHBaseStorage {
+
+    private static final String aclTableName = "MOCK-ACL-TABLE";
+    private static final String userTableName = "MOCK-USER-TABLE";
+
+    private HTableInterface mockedAclTable;
+    private HTableInterface mockedUserTable;
+    private RealAclHBaseStorage realAcl;
+
+    public MockAclHBaseStorage() {
+        String metadataUrl = KylinConfig.getInstanceFromEnv().getMetadataUrl();
+        if (metadataUrl != null && metadataUrl.endsWith("hbase")) {
+            // hbase must be available since metadata is on it
+            // in this case, let us use a real ACL instead of mockup
+            realAcl = new RealAclHBaseStorage();
+        }
+    }
+
+    @Override
+    public String prepareHBaseTable(Class<?> clazz) throws IOException {
+        if (realAcl != null) {
+            return realAcl.prepareHBaseTable(clazz);
+        }
+
+        if (clazz == AclService.class) {
+            mockedAclTable = new MockHTable(aclTableName, ACL_INFO_FAMILY, ACL_ACES_FAMILY);
+            return aclTableName;
+        } else if (clazz == UserService.class) {
+            mockedUserTable = new MockHTable(userTableName, USER_AUTHORITY_FAMILY);
+            return userTableName;
+        } else {
+            throw new IllegalStateException("prepareHBaseTable for unknown class: " + clazz);
+        }
+    }
+
+    @Override
+    public HTableInterface getTable(String tableName) throws IOException {
+        if (realAcl != null) {
+            return realAcl.getTable(tableName);
+        }
+
+        if (StringUtils.equals(tableName, aclTableName)) {
+            return mockedAclTable;
+        } else if (StringUtils.equals(tableName, userTableName)) {
+            return mockedUserTable;
+        } else {
+            throw new IllegalStateException("getTable failed" + tableName);
+        }
+    }
+}


[11/13] kylin git commit: KYLIN-1823 split code from kylin-server into kylin-server-base

Posted by li...@apache.org.
http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/controller/StreamingController.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/StreamingController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/StreamingController.java
new file mode 100644
index 0000000..f3374c3
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/controller/StreamingController.java
@@ -0,0 +1,297 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.controller;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.util.JsonUtil;
+import org.apache.kylin.engine.mr.HadoopUtil;
+import org.apache.kylin.engine.streaming.StreamingConfig;
+import org.apache.kylin.metadata.MetadataManager;
+import org.apache.kylin.metadata.model.TableDesc;
+import org.apache.kylin.rest.exception.BadRequestException;
+import org.apache.kylin.rest.exception.ForbiddenException;
+import org.apache.kylin.rest.exception.InternalErrorException;
+import org.apache.kylin.rest.exception.NotFoundException;
+import org.apache.kylin.rest.request.StreamingRequest;
+import org.apache.kylin.rest.service.CubeService;
+import org.apache.kylin.rest.service.KafkaConfigService;
+import org.apache.kylin.rest.service.StreamingService;
+import org.apache.kylin.source.kafka.config.KafkaConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+
+/**
+ * StreamingController is defined as Restful API entrance for UI.
+ *
+ * @author jiazhong
+ */
+@Controller
+@RequestMapping(value = "/streaming")
+public class StreamingController extends BasicController {
+    private static final Logger logger = LoggerFactory.getLogger(StreamingController.class);
+
+    @Autowired
+    private StreamingService streamingService;
+    @Autowired
+    private KafkaConfigService kafkaConfigService;
+    @Autowired
+    private CubeService cubeMgmtService;
+
+    @RequestMapping(value = "/getConfig", method = { RequestMethod.GET })
+    @ResponseBody
+    public List<StreamingConfig> getStreamings(@RequestParam(value = "table", required = false) String table, @RequestParam(value = "limit", required = false) Integer limit, @RequestParam(value = "offset", required = false) Integer offset) {
+        try {
+            return streamingService.getStreamingConfigs(table, limit, offset);
+        } catch (IOException e) {
+            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
+            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
+        }
+    }
+
+    @RequestMapping(value = "/getKfkConfig", method = { RequestMethod.GET })
+    @ResponseBody
+    public List<KafkaConfig> getKafkaConfigs(@RequestParam(value = "kafkaConfigName", required = false) String kafkaConfigName, @RequestParam(value = "limit", required = false) Integer limit, @RequestParam(value = "offset", required = false) Integer offset) {
+        try {
+            return kafkaConfigService.getKafkaConfigs(kafkaConfigName, limit, offset);
+        } catch (IOException e) {
+            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
+            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
+        }
+    }
+
+    /**
+     *
+     * create Streaming Schema
+     * @throws java.io.IOException
+     */
+    @RequestMapping(value = "", method = { RequestMethod.POST })
+    @ResponseBody
+    public StreamingRequest saveStreamingConfig(@RequestBody StreamingRequest streamingRequest) {
+
+        String project = streamingRequest.getProject();
+        TableDesc tableDesc = deserializeTableDesc(streamingRequest);
+        StreamingConfig streamingConfig = deserializeSchemalDesc(streamingRequest);
+        KafkaConfig kafkaConfig = deserializeKafkaSchemalDesc(streamingRequest);
+        boolean saveStreamingSuccess = false, saveKafkaSuccess = false;
+
+        try {
+            tableDesc.setUuid(UUID.randomUUID().toString());
+            MetadataManager metaMgr = MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
+            metaMgr.saveSourceTable(tableDesc);
+            cubeMgmtService.syncTableToProject(new String[] { tableDesc.getIdentity() }, project);
+        } catch (IOException e) {
+            throw new BadRequestException("Failed to add streaming table.");
+        }
+
+        streamingConfig.setName(tableDesc.getIdentity());
+        kafkaConfig.setName(tableDesc.getIdentity());
+        try {
+            if (StringUtils.isEmpty(streamingConfig.getName())) {
+                logger.info("StreamingConfig should not be empty.");
+                throw new BadRequestException("StremingConfig name should not be empty.");
+            }
+            try {
+                streamingConfig.setUuid(UUID.randomUUID().toString());
+                streamingService.createStreamingConfig(streamingConfig);
+                saveStreamingSuccess = true;
+            } catch (IOException e) {
+                logger.error("Failed to save StreamingConfig:" + e.getLocalizedMessage(), e);
+                throw new InternalErrorException("Failed to save StreamingConfig: " + e.getLocalizedMessage());
+            }
+            try {
+                kafkaConfig.setUuid(UUID.randomUUID().toString());
+                kafkaConfigService.createKafkaConfig(kafkaConfig);
+                saveKafkaSuccess = true;
+            } catch (IOException e) {
+                try {
+                    streamingService.dropStreamingConfig(streamingConfig);
+                } catch (IOException e1) {
+                    throw new InternalErrorException("StreamingConfig is created, but failed to create KafkaConfig: " + e.getLocalizedMessage());
+                }
+                logger.error("Failed to save KafkaConfig:" + e.getLocalizedMessage(), e);
+                throw new InternalErrorException("Failed to save KafkaConfig: " + e.getLocalizedMessage());
+            }
+        } finally {
+            if (saveKafkaSuccess == false || saveStreamingSuccess == false) {
+
+                if (saveStreamingSuccess == true) {
+                    StreamingConfig sConfig = streamingService.getStreamingManager().getStreamingConfig(streamingConfig.getName());
+                    try {
+                        streamingService.dropStreamingConfig(sConfig);
+                    } catch (IOException e) {
+                        throw new InternalErrorException("Action failed and failed to rollback the created streaming config: " + e.getLocalizedMessage());
+                    }
+                }
+                if (saveKafkaSuccess == true) {
+                    try {
+                        KafkaConfig kConfig = kafkaConfigService.getKafkaConfig(kafkaConfig.getName());
+                        kafkaConfigService.dropKafkaConfig(kConfig);
+                    } catch (IOException e) {
+                        throw new InternalErrorException("Action failed and failed to rollback the created kafka config: " + e.getLocalizedMessage());
+                    }
+                }
+            }
+
+        }
+        streamingRequest.setSuccessful(true);
+        return streamingRequest;
+    }
+
+    @RequestMapping(value = "", method = { RequestMethod.PUT })
+    @ResponseBody
+    public StreamingRequest updateStreamingConfig(@RequestBody StreamingRequest streamingRequest) throws JsonProcessingException {
+        StreamingConfig streamingConfig = deserializeSchemalDesc(streamingRequest);
+        KafkaConfig kafkaConfig = deserializeKafkaSchemalDesc(streamingRequest);
+
+        if (streamingConfig == null) {
+            return streamingRequest;
+        }
+        try {
+            streamingConfig = streamingService.updateStreamingConfig(streamingConfig);
+        } catch (AccessDeniedException accessDeniedException) {
+            throw new ForbiddenException("You don't have right to update this StreamingConfig.");
+        } catch (Exception e) {
+            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
+            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
+        }
+        try {
+            kafkaConfig = kafkaConfigService.updateKafkaConfig(kafkaConfig);
+        } catch (AccessDeniedException accessDeniedException) {
+            throw new ForbiddenException("You don't have right to update this KafkaConfig.");
+        } catch (Exception e) {
+            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
+            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
+        }
+
+        streamingRequest.setSuccessful(true);
+
+        return streamingRequest;
+    }
+
+    @RequestMapping(value = "/{configName}", method = { RequestMethod.DELETE })
+    @ResponseBody
+    public void deleteConfig(@PathVariable String configName) throws IOException {
+        StreamingConfig config = streamingService.getStreamingManager().getStreamingConfig(configName);
+        KafkaConfig kafkaConfig = kafkaConfigService.getKafkaConfig(configName);
+        if (null == config) {
+            throw new NotFoundException("StreamingConfig with name " + configName + " not found..");
+        }
+        try {
+            streamingService.dropStreamingConfig(config);
+            kafkaConfigService.dropKafkaConfig(kafkaConfig);
+        } catch (Exception e) {
+            logger.error(e.getLocalizedMessage(), e);
+            throw new InternalErrorException("Failed to delete StreamingConfig. " + " Caused by: " + e.getMessage(), e);
+        }
+    }
+
+    private TableDesc deserializeTableDesc(StreamingRequest streamingRequest) {
+        TableDesc desc = null;
+        try {
+            logger.debug("Saving TableDesc " + streamingRequest.getTableData());
+            desc = JsonUtil.readValue(streamingRequest.getTableData(), TableDesc.class);
+        } catch (JsonParseException e) {
+            logger.error("The TableDesc definition is invalid.", e);
+            updateRequest(streamingRequest, false, e.getMessage());
+        } catch (JsonMappingException e) {
+            logger.error("The data TableDesc definition is invalid.", e);
+            updateRequest(streamingRequest, false, e.getMessage());
+        } catch (IOException e) {
+            logger.error("Failed to deal with the request.", e);
+            throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
+        }
+
+        String[] dbTable = HadoopUtil.parseHiveTableName(desc.getName());
+        desc.setName(dbTable[1]);
+        desc.setDatabase(dbTable[0]);
+        desc.getIdentity();
+        return desc;
+    }
+
+    private StreamingConfig deserializeSchemalDesc(StreamingRequest streamingRequest) {
+        StreamingConfig desc = null;
+        try {
+            logger.debug("Saving StreamingConfig " + streamingRequest.getStreamingConfig());
+            desc = JsonUtil.readValue(streamingRequest.getStreamingConfig(), StreamingConfig.class);
+        } catch (JsonParseException e) {
+            logger.error("The StreamingConfig definition is invalid.", e);
+            updateRequest(streamingRequest, false, e.getMessage());
+        } catch (JsonMappingException e) {
+            logger.error("The data StreamingConfig definition is invalid.", e);
+            updateRequest(streamingRequest, false, e.getMessage());
+        } catch (IOException e) {
+            logger.error("Failed to deal with the request.", e);
+            throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
+        }
+        return desc;
+    }
+
+    private KafkaConfig deserializeKafkaSchemalDesc(StreamingRequest streamingRequest) {
+        KafkaConfig desc = null;
+        try {
+            logger.debug("Saving KafkaConfig " + streamingRequest.getKafkaConfig());
+            desc = JsonUtil.readValue(streamingRequest.getKafkaConfig(), KafkaConfig.class);
+        } catch (JsonParseException e) {
+            logger.error("The KafkaConfig definition is invalid.", e);
+            updateRequest(streamingRequest, false, e.getMessage());
+        } catch (JsonMappingException e) {
+            logger.error("The data KafkaConfig definition is invalid.", e);
+            updateRequest(streamingRequest, false, e.getMessage());
+        } catch (IOException e) {
+            logger.error("Failed to deal with the request.", e);
+            throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
+        }
+        return desc;
+    }
+
+    private void updateRequest(StreamingRequest request, boolean success, String message) {
+        request.setSuccessful(success);
+        request.setMessage(message);
+    }
+
+    public void setStreamingService(StreamingService streamingService) {
+        this.streamingService = streamingService;
+    }
+
+    public void setKafkaConfigService(KafkaConfigService kafkaConfigService) {
+        this.kafkaConfigService = kafkaConfigService;
+    }
+
+    public void setCubeService(CubeService cubeService) {
+        this.cubeMgmtService = cubeService;
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/controller/TableController.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/TableController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/TableController.java
new file mode 100644
index 0000000..1c3377b
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/controller/TableController.java
@@ -0,0 +1,350 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.controller;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.util.JsonUtil;
+import org.apache.kylin.engine.mr.HadoopUtil;
+import org.apache.kylin.engine.streaming.StreamingConfig;
+import org.apache.kylin.metadata.MetadataConstants;
+import org.apache.kylin.metadata.MetadataManager;
+import org.apache.kylin.metadata.model.ColumnDesc;
+import org.apache.kylin.metadata.model.TableDesc;
+import org.apache.kylin.rest.exception.InternalErrorException;
+import org.apache.kylin.rest.request.CardinalityRequest;
+import org.apache.kylin.rest.request.HiveTableRequest;
+import org.apache.kylin.rest.request.StreamingRequest;
+import org.apache.kylin.rest.response.TableDescResponse;
+import org.apache.kylin.rest.service.CubeService;
+import org.apache.kylin.rest.service.KafkaConfigService;
+import org.apache.kylin.rest.service.ModelService;
+import org.apache.kylin.rest.service.ProjectService;
+import org.apache.kylin.rest.service.StreamingService;
+import org.apache.kylin.source.hive.HiveClient;
+import org.apache.kylin.source.kafka.config.KafkaConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.google.common.collect.Sets;
+
+/**
+ * @author xduo
+ */
+@Controller
+@RequestMapping(value = "/tables")
+public class TableController extends BasicController {
+    private static final Logger logger = LoggerFactory.getLogger(TableController.class);
+
+    @Autowired
+    private CubeService cubeMgmtService;
+    @Autowired
+    private ProjectService projectService;
+    @Autowired
+    private StreamingService streamingService;
+    @Autowired
+    private KafkaConfigService kafkaConfigService;
+    @Autowired
+    private ModelService modelService;
+
+    /**
+     * Get available table list of the input database
+     *
+     * @return Table metadata array
+     * @throws IOException
+     */
+    @RequestMapping(value = "", method = { RequestMethod.GET })
+    @ResponseBody
+    public List<TableDesc> getHiveTables(@RequestParam(value = "ext", required = false) boolean withExt, @RequestParam(value = "project", required = false) String project) {
+        long start = System.currentTimeMillis();
+        List<TableDesc> tables = null;
+        try {
+            tables = cubeMgmtService.getProjectManager().listDefinedTables(project);
+        } catch (Exception e) {
+            logger.error("Failed to deal with the request.", e);
+            throw new InternalErrorException(e.getLocalizedMessage());
+        }
+
+        if (withExt) {
+            tables = cloneTableDesc(tables);
+        }
+        long end = System.currentTimeMillis();
+        logger.info("Return all table metadata in " + (end - start) + " seconds");
+
+        return tables;
+    }
+
+    /**
+     * Get available table list of the input database
+     *
+     * @return Table metadata array
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{tableName:.+}", method = { RequestMethod.GET })
+    @ResponseBody
+    public TableDesc getHiveTable(@PathVariable String tableName) {
+        return cubeMgmtService.getMetadataManager().getTableDesc(tableName);
+    }
+
+    /**
+     * Get available table list of the input database
+     *
+     * @return Table metadata array
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{tableName}/exd-map", method = { RequestMethod.GET })
+    @ResponseBody
+    public Map<String, String> getHiveTableExd(@PathVariable String tableName) {
+        Map<String, String> tableExd = cubeMgmtService.getMetadataManager().getTableDescExd(tableName);
+        return tableExd;
+    }
+
+    @RequestMapping(value = "/reload", method = { RequestMethod.PUT })
+    @ResponseBody
+    public String reloadSourceTable() {
+        cubeMgmtService.getMetadataManager().reload();
+        return "ok";
+    }
+
+    @RequestMapping(value = "/{tables}/{project}", method = { RequestMethod.POST })
+    @ResponseBody
+    public Map<String, String[]> loadHiveTable(@PathVariable String tables, @PathVariable String project, @RequestBody HiveTableRequest request) throws IOException {
+        String submitter = SecurityContextHolder.getContext().getAuthentication().getName();
+        String[] loaded = cubeMgmtService.reloadHiveTable(tables);
+        if (request.isCalculate()) {
+            cubeMgmtService.calculateCardinalityIfNotPresent(loaded, submitter);
+        }
+        cubeMgmtService.syncTableToProject(loaded, project);
+        Map<String, String[]> result = new HashMap<String, String[]>();
+        result.put("result.loaded", loaded);
+        result.put("result.unloaded", new String[] {});
+        return result;
+    }
+
+    @RequestMapping(value = "/{tables}/{project}", method = { RequestMethod.DELETE })
+    @ResponseBody
+    public Map<String, String[]> unLoadHiveTables(@PathVariable String tables, @PathVariable String project) {
+        Set<String> unLoadSuccess = Sets.newHashSet();
+        Set<String> unLoadFail = Sets.newHashSet();
+        Map<String, String[]> result = new HashMap<String, String[]>();
+        for (String tableName : tables.split(",")) {
+            if (unLoadHiveTable(tableName, project)) {
+                unLoadSuccess.add(tableName);
+            } else {
+                unLoadFail.add(tableName);
+            }
+        }
+        result.put("result.unload.success", (String[]) unLoadSuccess.toArray(new String[unLoadSuccess.size()]));
+        result.put("result.unload.fail", (String[]) unLoadFail.toArray(new String[unLoadFail.size()]));
+        return result;
+    }
+
+    /**
+     * table may referenced by several projects, and kylin only keep one copy of meta for each table,
+     * that's why we have two if statement here.
+     * @param tableName
+     * @param project
+     * @return
+     */
+    private boolean unLoadHiveTable(String tableName, String project) {
+        boolean rtn = false;
+        int tableType = 0;
+
+        //remove streaming info
+        String[] dbTableName = HadoopUtil.parseHiveTableName(tableName);
+        tableName = dbTableName[0] + "." + dbTableName[1];
+        TableDesc desc = cubeMgmtService.getMetadataManager().getTableDesc(tableName);
+        tableType = desc.getSourceType();
+
+        try {
+            if (!modelService.isTableInModel(tableName, project)) {
+                cubeMgmtService.removeTableFromProject(tableName, project);
+                rtn = true;
+            }
+        } catch (IOException e) {
+            logger.error(e.getMessage(), e);
+        }
+        if (!projectService.isTableInAnyProject(tableName) && !modelService.isTableInAnyModel(tableName)) {
+            try {
+                cubeMgmtService.unLoadHiveTable(tableName);
+                rtn = true;
+            } catch (IOException e) {
+                logger.error(e.getMessage(), e);
+                rtn = false;
+            }
+        }
+
+        if (tableType == 1 && !projectService.isTableInAnyProject(tableName) && !modelService.isTableInAnyModel(tableName)) {
+            StreamingConfig config = null;
+            KafkaConfig kafkaConfig = null;
+            try {
+                config = streamingService.getStreamingManager().getStreamingConfig(tableName);
+                kafkaConfig = kafkaConfigService.getKafkaConfig(tableName);
+                streamingService.dropStreamingConfig(config);
+                kafkaConfigService.dropKafkaConfig(kafkaConfig);
+                rtn = true;
+            } catch (Exception e) {
+                rtn = false;
+                logger.error(e.getLocalizedMessage(), e);
+            }
+        }
+        return rtn;
+    }
+
+    @RequestMapping(value = "/addStreamingSrc", method = { RequestMethod.POST })
+    @ResponseBody
+    public Map<String, String> addStreamingTable(@RequestBody StreamingRequest request) throws IOException {
+        Map<String, String> result = new HashMap<String, String>();
+        String project = request.getProject();
+        TableDesc desc = JsonUtil.readValue(request.getTableData(), TableDesc.class);
+        desc.setUuid(UUID.randomUUID().toString());
+        MetadataManager metaMgr = MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
+        metaMgr.saveSourceTable(desc);
+        cubeMgmtService.syncTableToProject(new String[] { desc.getName() }, project);
+        result.put("success", "true");
+        return result;
+    }
+
+    /**
+     * Regenerate table cardinality
+     *
+     * @return Table metadata array
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{tableNames}/cardinality", method = { RequestMethod.PUT })
+    @ResponseBody
+    public CardinalityRequest generateCardinality(@PathVariable String tableNames, @RequestBody CardinalityRequest request) {
+        String submitter = SecurityContextHolder.getContext().getAuthentication().getName();
+        String[] tables = tableNames.split(",");
+        for (String table : tables) {
+            cubeMgmtService.calculateCardinality(table.trim().toUpperCase(), submitter);
+        }
+        return request;
+    }
+
+    /**
+     * @param tables
+     * @return
+     */
+    private List<TableDesc> cloneTableDesc(List<TableDesc> tables) {
+        if (null == tables) {
+            return Collections.emptyList();
+        }
+
+        List<TableDesc> descs = new ArrayList<TableDesc>();
+        Iterator<TableDesc> it = tables.iterator();
+        while (it.hasNext()) {
+            TableDesc table = it.next();
+            Map<String, String> exd = cubeMgmtService.getMetadataManager().getTableDescExd(table.getIdentity());
+            if (exd == null) {
+                descs.add(table);
+            } else {
+                // Clone TableDesc
+                TableDescResponse rtableDesc = new TableDescResponse(table);
+                rtableDesc.setDescExd(exd);
+                if (exd.containsKey(MetadataConstants.TABLE_EXD_CARDINALITY)) {
+                    Map<String, Long> cardinality = new HashMap<String, Long>();
+                    String scard = exd.get(MetadataConstants.TABLE_EXD_CARDINALITY);
+                    if (!StringUtils.isEmpty(scard)) {
+                        String[] cards = StringUtils.split(scard, ",");
+                        ColumnDesc[] cdescs = rtableDesc.getColumns();
+                        for (int i = 0; i < cdescs.length; i++) {
+                            ColumnDesc columnDesc = cdescs[i];
+                            if (cards.length > i) {
+                                cardinality.put(columnDesc.getName(), Long.parseLong(cards[i]));
+                            } else {
+                                logger.error("The result cardinality is not identical with hive table metadata, cardinaly : " + scard + " column array length: " + cdescs.length);
+                                break;
+                            }
+                        }
+                        rtableDesc.setCardinality(cardinality);
+                    }
+                }
+                descs.add(rtableDesc);
+            }
+        }
+        return descs;
+    }
+
+    /**
+     * Show all databases in Hive
+     *
+     * @return Hive databases list
+     * @throws IOException
+     */
+    @RequestMapping(value = "/hive", method = { RequestMethod.GET })
+    @ResponseBody
+    private static List<String> showHiveDatabases() throws IOException {
+        HiveClient hiveClient = new HiveClient();
+        List<String> results = null;
+
+        try {
+            results = hiveClient.getHiveDbNames();
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new IOException(e);
+        }
+        return results;
+    }
+
+    /**
+     * Show all tables in a Hive database
+     *
+     * @return Hive table list
+     * @throws IOException
+     */
+    @RequestMapping(value = "/hive/{database}", method = { RequestMethod.GET })
+    @ResponseBody
+    private static List<String> showHiveTables(@PathVariable String database) throws IOException {
+        HiveClient hiveClient = new HiveClient();
+        List<String> results = null;
+
+        try {
+            results = hiveClient.getHiveTableNames(database);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new IOException(e);
+        }
+        return results;
+    }
+
+    public void setCubeService(CubeService cubeService) {
+        this.cubeMgmtService = cubeService;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/controller/UserController.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/UserController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/UserController.java
new file mode 100644
index 0000000..bccfed4
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/controller/UserController.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.controller;
+
+import java.util.List;
+
+import org.apache.kylin.rest.service.UserService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+/**
+ * Handle user authentication request to protected kylin rest resources by
+ * spring security.
+ * 
+ * @author xduo
+ * 
+ */
+@Controller
+@RequestMapping(value = "/user")
+public class UserController {
+
+    private static final Logger logger = LoggerFactory.getLogger(UserController.class);
+    @Autowired
+    UserService userService;
+
+    @RequestMapping(value = "/authentication", method = RequestMethod.POST, produces = "application/json")
+    public UserDetails authenticate() {
+        return authenticatedUser();
+    }
+
+    @RequestMapping(value = "/authentication", method = RequestMethod.GET, produces = "application/json")
+    public UserDetails authenticatedUser() {
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+
+        if (authentication == null) {
+            logger.debug("authentication is null.");
+            return null;
+        }
+
+        if (authentication.getPrincipal() instanceof UserDetails) {
+            logger.debug("authentication.getPrincipal() is " + authentication.getPrincipal());
+            return (UserDetails) authentication.getPrincipal();
+        }
+
+        if (authentication.getDetails() instanceof UserDetails) {
+            logger.debug("authentication.getDetails() is " + authentication.getDetails());
+            return (UserDetails) authentication.getDetails();
+        }
+
+        return null;
+    }
+
+    @RequestMapping(value = "/authentication/authorities", method = RequestMethod.GET, produces = "application/json")
+    public List<String> getAuthorities() {
+        return userService.listUserAuthorities();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/exception/BadRequestException.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/exception/BadRequestException.java b/server-base/src/main/java/org/apache/kylin/rest/exception/BadRequestException.java
new file mode 100644
index 0000000..42b671b
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/exception/BadRequestException.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.exception;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * @author xduo
+ *
+ */
+@ResponseStatus(value = HttpStatus.BAD_REQUEST)
+public class BadRequestException extends RuntimeException {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = -6798154278095441848L;
+
+    public BadRequestException(String s) {
+        super(s);
+    }
+
+    /**
+     * 
+     */
+    public BadRequestException() {
+        super();
+    }
+
+    /**
+     * @param arg0
+     * @param arg1
+     */
+    public BadRequestException(String arg0, Throwable arg1) {
+        super(arg0, arg1);
+    }
+
+    /**
+     * @param arg0
+     */
+    public BadRequestException(Throwable arg0) {
+        super(arg0);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/exception/ForbiddenException.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/exception/ForbiddenException.java b/server-base/src/main/java/org/apache/kylin/rest/exception/ForbiddenException.java
new file mode 100644
index 0000000..6a2ed7c
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/exception/ForbiddenException.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.exception;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * @author xduo
+ * 
+ */
+@ResponseStatus(value = HttpStatus.FORBIDDEN)
+public class ForbiddenException extends RuntimeException {
+
+    private static final long serialVersionUID = 2741885728370162194L;
+
+    public ForbiddenException() {
+        super();
+    }
+
+    public ForbiddenException(String message) {
+        super(message);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/exception/InternalErrorException.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/exception/InternalErrorException.java b/server-base/src/main/java/org/apache/kylin/rest/exception/InternalErrorException.java
new file mode 100644
index 0000000..6d7586f
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/exception/InternalErrorException.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.exception;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * Class to wrap backend exception
+ * 
+ * @author jianliu
+ * 
+ */
+@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
+public class InternalErrorException extends RuntimeException {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = -6798154278095441848L;
+
+    public InternalErrorException(String s) {
+        super(s);
+    }
+
+    /**
+     * 
+     */
+    public InternalErrorException() {
+        super();
+    }
+
+    /**
+     * @param arg0
+     * @param arg1
+     */
+    public InternalErrorException(String arg0, Throwable arg1) {
+        super(arg0, arg1);
+    }
+
+    /**
+     * @param arg0
+     */
+    public InternalErrorException(Throwable arg0) {
+        super(arg0);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/exception/NotFoundException.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/exception/NotFoundException.java b/server-base/src/main/java/org/apache/kylin/rest/exception/NotFoundException.java
new file mode 100644
index 0000000..0ed898c
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/exception/NotFoundException.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.exception;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+/**
+ * @author xduo
+ *
+ */
+@ResponseStatus(value = HttpStatus.NOT_FOUND)
+public class NotFoundException extends RuntimeException {
+    private static final long serialVersionUID = 1L;
+
+    public NotFoundException(String s) {
+        super(s);
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/init/ClientInfoTask.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/init/ClientInfoTask.java b/server-base/src/main/java/org/apache/kylin/rest/init/ClientInfoTask.java
new file mode 100644
index 0000000..301a9df
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/init/ClientInfoTask.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.init;
+
+import java.io.File;
+
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.KylinVersion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ClientInfoTask extends InitialTask {
+
+    private static final Logger logger = LoggerFactory.getLogger(ClientInfoTask.class);
+
+    @Override
+    public void execute() {
+        logger.info(getClientDetailInformation());
+    }
+
+    public static String getClientDetailInformation() {
+        StringBuilder buf = new StringBuilder();
+
+        buf.append("kylin.home: ").append(new File(KylinConfig.getKylinHome()).getAbsolutePath()).append("\n");
+        buf.append("kylin.version:").append(KylinVersion.getCurrentVersion()).append("\n");
+        buf.append("commit:").append(KylinVersion.getGitCommitInfo()).append("\n");
+        buf.append("os.name:").append(System.getProperty("os.name")).append("\n");
+        buf.append("os.arch:").append(System.getProperty("os.arch")).append("\n");
+        buf.append("os.version:").append(System.getProperty("os.version")).append("\n");
+        buf.append("java.version:").append(System.getProperty("java.version")).append("\n");
+        buf.append("java.vendor:").append(System.getProperty("java.vendor"));
+
+        return buf.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/init/InitialTask.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/init/InitialTask.java b/server-base/src/main/java/org/apache/kylin/rest/init/InitialTask.java
new file mode 100644
index 0000000..24691b1
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/init/InitialTask.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.init;
+
+/**
+ * Created by dongli on 3/16/16.
+ */
+public abstract class InitialTask {
+    public abstract void execute();
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/init/InitialTaskManager.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/init/InitialTaskManager.java b/server-base/src/main/java/org/apache/kylin/rest/init/InitialTaskManager.java
new file mode 100644
index 0000000..8912968
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/init/InitialTaskManager.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.init;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.kylin.common.KylinConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.InitializingBean;
+
+/**
+ * Created by dongli on 3/16/16.
+ */
+public class InitialTaskManager implements InitializingBean {
+
+    private static final Logger logger = LoggerFactory.getLogger(InitialTaskManager.class);
+
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        logger.info("Kylin service is starting.....");
+
+        runInitialTasks();
+    }
+
+    private void runInitialTasks() {
+        KylinConfig kylinConfig = KylinConfig.getInstanceFromEnv();
+        String initTasks = kylinConfig.getInitTasks();
+        if (!StringUtils.isEmpty(initTasks)) {
+            String[] taskClasses = initTasks.split(",");
+            for (String taskClass : taskClasses) {
+                try {
+                    InitialTask task = (InitialTask) Class.forName(taskClass).newInstance();
+                    logger.info("Running task: " + taskClass);
+                    task.execute();
+                } catch (Exception e) {
+                    logger.error("Initial task failed: " + taskClass, e);
+                }
+            }
+            logger.info("All initial tasks finished.");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/model/ColumnMeta.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/model/ColumnMeta.java b/server-base/src/main/java/org/apache/kylin/rest/model/ColumnMeta.java
new file mode 100644
index 0000000..15afb2e
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/model/ColumnMeta.java
@@ -0,0 +1,264 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.model;
+
+import java.io.Serializable;
+
+/**
+ */
+public class ColumnMeta implements Serializable {
+    private static final long serialVersionUID = 1L;
+    private String TABLE_CAT;
+    private String TABLE_SCHEM;
+    private String TABLE_NAME;
+    private String COLUMN_NAME;
+    private int DATA_TYPE;
+    private String TYPE_NAME;
+    private int COLUMN_SIZE;
+    private int BUFFER_LENGTH;
+    private int DECIMAL_DIGITS;
+    private int NUM_PREC_RADIX;
+    private int NULLABLE;
+    private String REMARKS;
+    private String COLUMN_DEF;
+    private int SQL_DATA_TYPE;
+    private int SQL_DATETIME_SUB;
+    private int CHAR_OCTET_LENGTH;
+    private int ORDINAL_POSITION;
+    private String IS_NULLABLE;
+    private String SCOPE_CATLOG;
+    private String SCOPE_SCHEMA;
+    private String SCOPE_TABLE;
+    private short SOURCE_DATA_TYPE;
+    private String IS_AUTOINCREMENT;
+
+    public ColumnMeta() {
+    }
+
+    public ColumnMeta(String tABLE_CAT, String tABLE_SCHEM, String tABLE_NAME, String cOLUMN_NAME, int dATA_TYPE, String tYPE_NAME, int cOLUMN_SIZE, int bUFFER_LENGTH, int dECIMAL_DIGITS, int nUM_PREC_RADIX, int nULLABLE, String rEMARKS, String cOLUMN_DEF, int sQL_DATA_TYPE, int sQL_DATETIME_SUB, int cHAR_OCTET_LENGTH, int oRDINAL_POSITION, String iS_NULLABLE, String sCOPE_CATLOG, String sCOPE_SCHEMA, String sCOPE_TABLE, short sOURCE_DATA_TYPE, String iS_AUTOINCREMENT) {
+        super();
+        TABLE_CAT = tABLE_CAT;
+        TABLE_SCHEM = tABLE_SCHEM;
+        TABLE_NAME = tABLE_NAME;
+        COLUMN_NAME = cOLUMN_NAME;
+        DATA_TYPE = dATA_TYPE;
+        TYPE_NAME = tYPE_NAME;
+        COLUMN_SIZE = cOLUMN_SIZE;
+        BUFFER_LENGTH = bUFFER_LENGTH;
+        DECIMAL_DIGITS = dECIMAL_DIGITS;
+        NUM_PREC_RADIX = nUM_PREC_RADIX;
+        NULLABLE = nULLABLE;
+        REMARKS = rEMARKS;
+        COLUMN_DEF = cOLUMN_DEF;
+        SQL_DATA_TYPE = sQL_DATA_TYPE;
+        SQL_DATETIME_SUB = sQL_DATETIME_SUB;
+        CHAR_OCTET_LENGTH = cHAR_OCTET_LENGTH;
+        ORDINAL_POSITION = oRDINAL_POSITION;
+        IS_NULLABLE = iS_NULLABLE;
+        SCOPE_CATLOG = sCOPE_CATLOG;
+        SCOPE_SCHEMA = sCOPE_SCHEMA;
+        SCOPE_TABLE = sCOPE_TABLE;
+        SOURCE_DATA_TYPE = sOURCE_DATA_TYPE;
+        IS_AUTOINCREMENT = iS_AUTOINCREMENT;
+    }
+
+    public String getTABLE_CAT() {
+        return TABLE_CAT;
+    }
+
+    public void setTABLE_CAT(String tABLE_CAT) {
+        TABLE_CAT = tABLE_CAT;
+    }
+
+    public String getTABLE_SCHEM() {
+        return TABLE_SCHEM;
+    }
+
+    public void setTABLE_SCHEM(String tABLE_SCHEM) {
+        TABLE_SCHEM = tABLE_SCHEM;
+    }
+
+    public String getTABLE_NAME() {
+        return TABLE_NAME;
+    }
+
+    public void setTABLE_NAME(String tABLE_NAME) {
+        TABLE_NAME = tABLE_NAME;
+    }
+
+    public String getCOLUMN_NAME() {
+        return COLUMN_NAME;
+    }
+
+    public void setCOLUMN_NAME(String cOLUMN_NAME) {
+        COLUMN_NAME = cOLUMN_NAME;
+    }
+
+    public int getDATA_TYPE() {
+        return DATA_TYPE;
+    }
+
+    public void setDATA_TYPE(int dATA_TYPE) {
+        DATA_TYPE = dATA_TYPE;
+    }
+
+    public String getTYPE_NAME() {
+        return TYPE_NAME;
+    }
+
+    public void setTYPE_NAME(String tYPE_NAME) {
+        TYPE_NAME = tYPE_NAME;
+    }
+
+    public int getCOLUMN_SIZE() {
+        return COLUMN_SIZE;
+    }
+
+    public void setCOLUMN_SIZE(int cOLUMN_SIZE) {
+        COLUMN_SIZE = cOLUMN_SIZE;
+    }
+
+    public int getBUFFER_LENGTH() {
+        return BUFFER_LENGTH;
+    }
+
+    public void setBUFFER_LENGTH(int bUFFER_LENGTH) {
+        BUFFER_LENGTH = bUFFER_LENGTH;
+    }
+
+    public int getDECIMAL_DIGITS() {
+        return DECIMAL_DIGITS;
+    }
+
+    public void setDECIMAL_DIGITS(int dECIMAL_DIGITS) {
+        DECIMAL_DIGITS = dECIMAL_DIGITS;
+    }
+
+    public int getNUM_PREC_RADIX() {
+        return NUM_PREC_RADIX;
+    }
+
+    public void setNUM_PREC_RADIX(int nUM_PREC_RADIX) {
+        NUM_PREC_RADIX = nUM_PREC_RADIX;
+    }
+
+    public int getNULLABLE() {
+        return NULLABLE;
+    }
+
+    public void setNULLABLE(int nULLABLE) {
+        NULLABLE = nULLABLE;
+    }
+
+    public String getREMARKS() {
+        return REMARKS;
+    }
+
+    public void setREMARKS(String rEMARKS) {
+        REMARKS = rEMARKS;
+    }
+
+    public String getCOLUMN_DEF() {
+        return COLUMN_DEF;
+    }
+
+    public void setCOLUMN_DEF(String cOLUMN_DEF) {
+        COLUMN_DEF = cOLUMN_DEF;
+    }
+
+    public int getSQL_DATA_TYPE() {
+        return SQL_DATA_TYPE;
+    }
+
+    public void setSQL_DATA_TYPE(int sQL_DATA_TYPE) {
+        SQL_DATA_TYPE = sQL_DATA_TYPE;
+    }
+
+    public int getSQL_DATETIME_SUB() {
+        return SQL_DATETIME_SUB;
+    }
+
+    public void setSQL_DATETIME_SUB(int sQL_DATETIME_SUB) {
+        SQL_DATETIME_SUB = sQL_DATETIME_SUB;
+    }
+
+    public int getCHAR_OCTET_LENGTH() {
+        return CHAR_OCTET_LENGTH;
+    }
+
+    public void setCHAR_OCTET_LENGTH(int cHAR_OCTET_LENGTH) {
+        CHAR_OCTET_LENGTH = cHAR_OCTET_LENGTH;
+    }
+
+    public int getORDINAL_POSITION() {
+        return ORDINAL_POSITION;
+    }
+
+    public void setORDINAL_POSITION(int oRDINAL_POSITION) {
+        ORDINAL_POSITION = oRDINAL_POSITION;
+    }
+
+    public String getIS_NULLABLE() {
+        return IS_NULLABLE;
+    }
+
+    public void setIS_NULLABLE(String iS_NULLABLE) {
+        IS_NULLABLE = iS_NULLABLE;
+    }
+
+    public String getSCOPE_CATLOG() {
+        return SCOPE_CATLOG;
+    }
+
+    public void setSCOPE_CATLOG(String sCOPE_CATLOG) {
+        SCOPE_CATLOG = sCOPE_CATLOG;
+    }
+
+    public String getSCOPE_SCHEMA() {
+        return SCOPE_SCHEMA;
+    }
+
+    public void setSCOPE_SCHEMA(String sCOPE_SCHEMA) {
+        SCOPE_SCHEMA = sCOPE_SCHEMA;
+    }
+
+    public String getSCOPE_TABLE() {
+        return SCOPE_TABLE;
+    }
+
+    public void setSCOPE_TABLE(String sCOPE_TABLE) {
+        SCOPE_TABLE = sCOPE_TABLE;
+    }
+
+    public short getSOURCE_DATA_TYPE() {
+        return SOURCE_DATA_TYPE;
+    }
+
+    public void setSOURCE_DATA_TYPE(short sOURCE_DATA_TYPE) {
+        SOURCE_DATA_TYPE = sOURCE_DATA_TYPE;
+    }
+
+    public String getIS_AUTOINCREMENT() {
+        return IS_AUTOINCREMENT;
+    }
+
+    public void setIS_AUTOINCREMENT(String iS_AUTOINCREMENT) {
+        this.IS_AUTOINCREMENT = iS_AUTOINCREMENT;
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/model/Query.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/model/Query.java b/server-base/src/main/java/org/apache/kylin/rest/model/Query.java
new file mode 100644
index 0000000..6b2ef5e
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/model/Query.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class Query {
+
+    private String name;
+    private String project;
+    private String sql;
+    private String description;
+
+    public Query() {
+    }
+
+    public Query(String name, String project, String sql, String description) {
+        super();
+        this.name = name;
+        this.project = project;
+        this.sql = sql;
+        this.description = description;
+    }
+
+    public String getId() {
+        return String.valueOf(this.hashCode());
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getProject() {
+        return project;
+    }
+
+    public void setProject(String project) {
+        this.project = project;
+    }
+
+    public String getSql() {
+        return sql;
+    }
+
+    public void setSql(String sql) {
+        this.sql = sql;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((description == null) ? 0 : description.hashCode());
+        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        result = prime * result + ((project == null) ? 0 : project.hashCode());
+        result = prime * result + ((sql == null) ? 0 : sql.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        Query other = (Query) obj;
+        if (description == null) {
+            if (other.description != null)
+                return false;
+        } else if (!description.equals(other.description))
+            return false;
+        if (name == null) {
+            if (other.name != null)
+                return false;
+        } else if (!name.equals(other.name))
+            return false;
+        if (project == null) {
+            if (other.project != null)
+                return false;
+        } else if (!project.equals(other.project))
+            return false;
+        if (sql == null) {
+            if (other.sql != null)
+                return false;
+        } else if (!sql.equals(other.sql))
+            return false;
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/model/SelectedColumnMeta.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/model/SelectedColumnMeta.java b/server-base/src/main/java/org/apache/kylin/rest/model/SelectedColumnMeta.java
new file mode 100644
index 0000000..95582e4
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/model/SelectedColumnMeta.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.model;
+
+import java.io.Serializable;
+
+/**
+ */
+public class SelectedColumnMeta implements Serializable {
+    public SelectedColumnMeta(boolean isAutoIncrement, boolean isCaseSensitive, boolean isSearchable, boolean isCurrency, int isNullalbe, boolean isSigned, int displaySize, String label, String name, String schemaName, String catelogName, String tableName, int precision, int scale, int columnType, String columnTypeName, boolean isReadOnly, boolean isWritable, boolean isDefinitelyWritable) {
+        super();
+        this.isAutoIncrement = isAutoIncrement;
+        this.isCaseSensitive = isCaseSensitive;
+        this.isSearchable = isSearchable;
+        this.isCurrency = isCurrency;
+        this.isNullable = isNullalbe;
+        this.isSigned = isSigned;
+        this.displaySize = displaySize;
+        this.label = label;
+        this.name = name;
+        this.schemaName = schemaName;
+        this.catelogName = catelogName;
+        this.tableName = tableName;
+        this.precision = precision;
+        this.scale = scale;
+        this.columnType = columnType;
+        this.columnTypeName = columnTypeName;
+        this.isReadOnly = isReadOnly;
+        this.isWritable = isWritable;
+        this.isDefinitelyWritable = isDefinitelyWritable;
+    }
+
+    public boolean isAutoIncrement() {
+        return isAutoIncrement;
+    }
+
+    public boolean isCaseSensitive() {
+        return isCaseSensitive;
+    }
+
+    public boolean isSearchable() {
+        return isSearchable;
+    }
+
+    public boolean isCurrency() {
+        return isCurrency;
+    }
+
+    public int getIsNullable() {
+        return isNullable;
+    }
+
+    public boolean isSigned() {
+        return isSigned;
+    }
+
+    public int getDisplaySize() {
+        return displaySize;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getSchemaName() {
+        return schemaName;
+    }
+
+    public String getCatelogName() {
+        return catelogName;
+    }
+
+    public String getTableName() {
+        return tableName;
+    }
+
+    public int getPrecision() {
+        return precision;
+    }
+
+    public int getScale() {
+        return scale;
+    }
+
+    public int getColumnType() {
+        return columnType;
+    }
+
+    public String getColumnTypeName() {
+        return columnTypeName;
+    }
+
+    public boolean isReadOnly() {
+        return isReadOnly;
+    }
+
+    public boolean isWritable() {
+        return isWritable;
+    }
+
+    public boolean isDefinitelyWritable() {
+        return isDefinitelyWritable;
+    }
+
+    private final boolean isAutoIncrement;
+    private final boolean isCaseSensitive;
+    private final boolean isSearchable;
+    private final boolean isCurrency;
+    private final int isNullable;// 0:nonull, 1:nullable, 2: nullableunknown
+    private final boolean isSigned;
+    private final int displaySize;
+    private final String label;// AS keyword
+    private final String name;
+    private final String schemaName;
+    private final String catelogName;
+    private final String tableName;
+    private final int precision;
+    private final int scale;
+    private final int columnType;// as defined in java.sql.Types
+    private final String columnTypeName;
+    private final boolean isReadOnly;
+    private final boolean isWritable;
+    private final boolean isDefinitelyWritable;
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/model/TableMeta.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/model/TableMeta.java b/server-base/src/main/java/org/apache/kylin/rest/model/TableMeta.java
new file mode 100644
index 0000000..9a48851
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/model/TableMeta.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.model;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ */
+public class TableMeta implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+    private String TABLE_CAT;
+    private String TABLE_SCHEM;
+    private String TABLE_NAME;
+    private String TABLE_TYPE;
+    private String REMARKS;
+    private String TYPE_CAT;
+    private String TYPE_SCHEM;
+    private String TYPE_NAME;
+    private String SELF_REFERENCING_COL_NAME;
+    private String REF_GENERATION;
+    private List<ColumnMeta> columns = new ArrayList<ColumnMeta>();
+
+    public TableMeta() {
+    }
+
+    public TableMeta(String tABLE_CAT, String tABLE_SCHEM, String tABLE_NAME, String tABLE_TYPE, String rEMARKS, String tYPE_CAT, String tYPE_SCHEM, String tYPE_NAME, String sELF_REFERENCING_COL_NAME, String rEF_GENERATION) {
+        super();
+        TABLE_CAT = tABLE_CAT;
+        TABLE_SCHEM = tABLE_SCHEM;
+        TABLE_NAME = tABLE_NAME;
+        TABLE_TYPE = tABLE_TYPE;
+        REMARKS = rEMARKS;
+        TYPE_CAT = tYPE_CAT;
+        TYPE_SCHEM = tYPE_SCHEM;
+        TYPE_NAME = tYPE_NAME;
+        SELF_REFERENCING_COL_NAME = sELF_REFERENCING_COL_NAME;
+        REF_GENERATION = rEF_GENERATION;
+    }
+
+    public String getTABLE_CAT() {
+        return TABLE_CAT;
+    }
+
+    public void setTABLE_CAT(String tABLE_CAT) {
+        TABLE_CAT = tABLE_CAT;
+    }
+
+    public String getTABLE_SCHEM() {
+        return TABLE_SCHEM;
+    }
+
+    public void setTABLE_SCHEM(String tABLE_SCHEM) {
+        TABLE_SCHEM = tABLE_SCHEM;
+    }
+
+    public String getTABLE_NAME() {
+        return TABLE_NAME;
+    }
+
+    public void setTABLE_NAME(String tABLE_NAME) {
+        TABLE_NAME = tABLE_NAME;
+    }
+
+    public String getTABLE_TYPE() {
+        return TABLE_TYPE;
+    }
+
+    public void setTABLE_TYPE(String tABLE_TYPE) {
+        TABLE_TYPE = tABLE_TYPE;
+    }
+
+    public String getREMARKS() {
+        return REMARKS;
+    }
+
+    public void setREMARKS(String rEMARKS) {
+        REMARKS = rEMARKS;
+    }
+
+    public String getTYPE_CAT() {
+        return TYPE_CAT;
+    }
+
+    public void setTYPE_CAT(String tYPE_CAT) {
+        TYPE_CAT = tYPE_CAT;
+    }
+
+    public String getTYPE_SCHEM() {
+        return TYPE_SCHEM;
+    }
+
+    public void setTYPE_SCHEM(String tYPE_SCHEM) {
+        TYPE_SCHEM = tYPE_SCHEM;
+    }
+
+    public String getTYPE_NAME() {
+        return TYPE_NAME;
+    }
+
+    public void setTYPE_NAME(String tYPE_NAME) {
+        TYPE_NAME = tYPE_NAME;
+    }
+
+    public String getSELF_REFERENCING_COL_NAME() {
+        return SELF_REFERENCING_COL_NAME;
+    }
+
+    public void setSELF_REFERENCING_COL_NAME(String sELF_REFERENCING_COL_NAME) {
+        SELF_REFERENCING_COL_NAME = sELF_REFERENCING_COL_NAME;
+    }
+
+    public String getREF_GENERATION() {
+        return REF_GENERATION;
+    }
+
+    public void setREF_GENERATION(String rEF_GENERATION) {
+        REF_GENERATION = rEF_GENERATION;
+    }
+
+    public List<ColumnMeta> getColumns() {
+        return columns;
+    }
+
+    public void setColumns(List<ColumnMeta> columns) {
+        this.columns = columns;
+    }
+
+    public void addColumn(ColumnMeta column) {
+        this.columns.add(column);
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/AccessRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/AccessRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/AccessRequest.java
new file mode 100644
index 0000000..0ff57b2
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/AccessRequest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.request;
+
+/**
+ * @author xduo
+ * 
+ */
+public class AccessRequest {
+
+    private Long accessEntryId;
+    private String permission;
+    private String sid;
+    private boolean principal;
+
+    public AccessRequest() {
+    }
+
+    public Long getAccessEntryId() {
+        return accessEntryId;
+    }
+
+    public void setAccessEntryId(Long accessEntryId) {
+        this.accessEntryId = accessEntryId;
+    }
+
+    public String getPermission() {
+        return permission;
+    }
+
+    public void setPermission(String permission) {
+        this.permission = permission;
+    }
+
+    public String getSid() {
+        return sid;
+    }
+
+    public void setSid(String sid) {
+        this.sid = sid;
+    }
+
+    public boolean isPrincipal() {
+        return principal;
+    }
+
+    public void setPrincipal(boolean principal) {
+        this.principal = principal;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/CardinalityRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/CardinalityRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/CardinalityRequest.java
new file mode 100644
index 0000000..aaf0537
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/CardinalityRequest.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.request;
+
+/**
+ * @author jianliu
+ * 
+ */
+public class CardinalityRequest {
+    private int delimiter;
+
+    private int format;
+
+    /**
+     * @return the delimiter
+     */
+    public String getDelimiter() {
+        switch (delimiter) {
+        case 0:
+            return null;
+        case 1:
+            return "177";
+        case 2:
+            return "t";
+        default:
+            return null;
+        }
+    }
+
+    /**
+     * @param delimiter
+     *            the delimiter to set
+     */
+    public void setDelimiter(int delimiter) {
+        this.delimiter = delimiter;
+    }
+
+    /**
+     * @return the format
+     */
+    public String getFormat() {
+        switch (format) {
+        case 0:
+            return null;
+        case 1:
+            return "text";
+        case 2:
+            return "sequence";
+        default:
+            return null;
+        }
+    }
+
+    /**
+     * @param format
+     *            the format to set
+     */
+    public void setFormat(int format) {
+        this.format = format;
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java
new file mode 100644
index 0000000..71cd1c4
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.request;
+
+/**
+ */
+public class CreateProjectRequest {
+    private String name;
+    private String description;
+
+    public CreateProjectRequest() {
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/CubeRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/CubeRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/CubeRequest.java
new file mode 100644
index 0000000..fb9952b
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/CubeRequest.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.request;
+
+public class CubeRequest {
+
+    private String uuid;
+    private String cubeName;
+    private String cubeDescData;
+    private String streamingData;
+    private String kafkaData;
+    private boolean successful;
+    private String message;
+    private String project;
+    private String streamingCube;
+
+    public String getUuid() {
+        return uuid;
+    }
+
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+
+    /**
+     * @return the message
+     */
+    public String getMessage() {
+        return message;
+    }
+
+    /**
+     * @param message
+     *            the message to set
+     */
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    /**
+     * @return the status
+     */
+    public boolean getSuccessful() {
+        return successful;
+    }
+
+    /**
+     * @param status
+     *            the status to set
+     */
+    public void setSuccessful(boolean status) {
+        this.successful = status;
+    }
+
+    public CubeRequest() {
+    }
+
+    public CubeRequest(String cubeName, String cubeDescData) {
+        this.cubeName = cubeName;
+        this.cubeDescData = cubeDescData;
+    }
+
+    public String getCubeDescData() {
+        return cubeDescData;
+    }
+
+    public void setCubeDescData(String cubeDescData) {
+        this.cubeDescData = cubeDescData;
+    }
+
+    /**
+     * @return the cubeDescName
+     */
+    public String getCubeName() {
+        return cubeName;
+    }
+
+    /**
+     * @param cubeName
+     *            the cubeDescName to set
+     */
+    public void setCubeName(String cubeName) {
+        this.cubeName = cubeName;
+    }
+
+    public String getProject() {
+        return project;
+    }
+
+    public void setProject(String project) {
+        this.project = project;
+    }
+
+    public String getStreamingCube() {
+        return streamingCube;
+    }
+
+    public void setStreamingCube(String streamingCube) {
+        this.streamingCube = streamingCube;
+    }
+
+    public String getStreamingData() {
+        return streamingData;
+    }
+
+    public void setStreamingData(String streamingData) {
+        this.streamingData = streamingData;
+    }
+
+    public String getKafkaData() {
+        return kafkaData;
+    }
+
+    public void setKafkaData(String kafkaData) {
+        this.kafkaData = kafkaData;
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/CubeSegmentRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/CubeSegmentRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/CubeSegmentRequest.java
new file mode 100644
index 0000000..17122ad
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/CubeSegmentRequest.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.request;
+
+public class CubeSegmentRequest {
+
+    private String uuid;
+    private String cubeName;
+    private String cubeSegmentData;
+    private boolean successful;
+    private String message;
+    private String project;
+
+    public String getUuid() {
+        return uuid;
+    }
+
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+
+    /**
+     * @return the message
+     */
+    public String getMessage() {
+        return message;
+    }
+
+    /**
+     * @param message
+     *            the message to set
+     */
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    /**
+     * @return the status
+     */
+    public boolean getSuccessful() {
+        return successful;
+    }
+
+    /**
+     * @param status
+     *            the status to set
+     */
+    public void setSuccessful(boolean status) {
+        this.successful = status;
+    }
+
+    public CubeSegmentRequest() {
+    }
+
+    public CubeSegmentRequest(String cubeName, String cubeDescData) {
+        this.cubeName = cubeName;
+        this.cubeSegmentData = cubeDescData;
+    }
+
+    public String getCubeSegmentData() {
+        return cubeSegmentData;
+    }
+
+    public void setCubeSegmentData(String cubeSegmentData) {
+        this.cubeSegmentData = cubeSegmentData;
+    }
+
+    /**
+     * @return the cubeDescName
+     */
+    public String getCubeName() {
+        return cubeName;
+    }
+
+    /**
+     * @param cubeName
+     *            the cubeDescName to set
+     */
+    public void setCubeName(String cubeName) {
+        this.cubeName = cubeName;
+    }
+
+    public String getProject() {
+        return project;
+    }
+
+    public void setProject(String project) {
+        this.project = project;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/ExternalFilterRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/ExternalFilterRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/ExternalFilterRequest.java
new file mode 100644
index 0000000..887e9ef
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/ExternalFilterRequest.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.request;
+
+public class ExternalFilterRequest {
+
+    private String project;
+
+    private String extFilter;
+
+    private boolean successful;
+
+    private String message;
+
+    public String getProject() {
+        return project;
+    }
+
+    public void setProject(String project) {
+        this.project = project;
+    }
+
+    public boolean isSuccessful() {
+        return successful;
+    }
+
+    public String getExtFilter() {
+        return extFilter;
+    }
+
+    public void setExtFilter(String extFilter) {
+        this.extFilter = extFilter;
+    }
+
+    public void setSuccessful(boolean successful) {
+        this.successful = successful;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/HiveTableRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/HiveTableRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/HiveTableRequest.java
new file mode 100644
index 0000000..c529360
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/HiveTableRequest.java
@@ -0,0 +1,22 @@
+package org.apache.kylin.rest.request;
+
+/**
+ * Created by kangkaisen on 16/5/21.
+ */
+public class HiveTableRequest {
+
+    public HiveTableRequest() {
+
+    }
+
+    private boolean calculate = true;
+
+    public boolean isCalculate() {
+        return calculate;
+    }
+
+    public void setCalculate(boolean calculate) {
+        this.calculate = calculate;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/request/JobBuildRequest.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/request/JobBuildRequest.java b/server-base/src/main/java/org/apache/kylin/rest/request/JobBuildRequest.java
new file mode 100644
index 0000000..a8ffe5f
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/request/JobBuildRequest.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.request;
+
+public class JobBuildRequest {
+
+    private long startTime;
+
+    private long endTime;
+
+    private String buildType;
+
+    private boolean force;
+
+    @Deprecated
+    private boolean forceMergeEmptySegment = false;
+
+    public long getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(long startTime) {
+        this.startTime = startTime;
+    }
+
+    public long getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(long endTime) {
+        this.endTime = endTime;
+    }
+
+    public String getBuildType() {
+        return buildType;
+    }
+
+    public void setBuildType(String buildType) {
+        this.buildType = buildType;
+    }
+
+    public boolean isForce() {
+        return force;
+    }
+
+    public void setForce(boolean force) {
+        this.force = force;
+    }
+
+    @Deprecated
+    public boolean isForceMergeEmptySegment() {
+        return forceMergeEmptySegment;
+    }
+
+    @Deprecated
+    public void setForceMergeEmptySegment(boolean forceMergeEmptySegment) {
+        this.forceMergeEmptySegment = forceMergeEmptySegment;
+    }
+}


[09/13] kylin git commit: KYLIN-1823 split code from kylin-server into kylin-server-base

Posted by li...@apache.org.
http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/security/MockHTable.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/MockHTable.java b/server-base/src/main/java/org/apache/kylin/rest/security/MockHTable.java
new file mode 100644
index 0000000..d0aa0ed
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/security/MockHTable.java
@@ -0,0 +1,729 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+/**
+ * This file is licensed to you 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.
+ */
+
+package org.apache.kylin.rest.security;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NavigableMap;
+import java.util.NavigableSet;
+import java.util.NoSuchElementException;
+import java.util.TreeMap;
+
+import org.apache.commons.lang.NotImplementedException;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.client.Append;
+import org.apache.hadoop.hbase.client.Delete;
+import org.apache.hadoop.hbase.client.Durability;
+import org.apache.hadoop.hbase.client.Get;
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.hadoop.hbase.client.Increment;
+import org.apache.hadoop.hbase.client.Mutation;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.ResultScanner;
+import org.apache.hadoop.hbase.client.Row;
+import org.apache.hadoop.hbase.client.RowMutations;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.client.coprocessor.Batch;
+import org.apache.hadoop.hbase.filter.CompareFilter;
+import org.apache.hadoop.hbase.filter.Filter;
+import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
+import org.apache.hadoop.hbase.util.Bytes;
+
+import com.google.protobuf.Descriptors;
+import com.google.protobuf.Message;
+import com.google.protobuf.Service;
+import com.google.protobuf.ServiceException;
+
+/**
+ * MockHTable.
+ *
+ * original MockHTable (by agaoglu) : https://gist.github.com/agaoglu/613217#file_mock_h_table.java
+ *
+ * Modifications
+ *
+ * <ul>
+ *     <li>fix filter (by k-mack) : https://gist.github.com/k-mack/4600133</li>
+ *     <li>fix batch() : implement all mutate operation and fix result[] count.</li>
+ *     <li>fix exists()</li>
+ *     <li>fix increment() : wrong return value</li>
+ *     <li>check columnFamily</li>
+ *     <li>implement mutateRow()</li>
+ *     <li>implement getTableName()</li>
+ *     <li>implement getTableDescriptor()</li>
+ *     <li>throws RuntimeException when unimplemented method was called.</li>
+ *     <li>remove some methods for loading data, checking values ...</li>
+ * </ul>
+ */
+public class MockHTable implements HTableInterface {
+    private final String tableName;
+    private final List<String> columnFamilies = new ArrayList<>();
+
+    private NavigableMap<byte[], NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>>> data = new TreeMap<>(Bytes.BYTES_COMPARATOR);
+
+    private static List<KeyValue> toKeyValue(byte[] row, NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> rowdata, int maxVersions) {
+        return toKeyValue(row, rowdata, 0, Long.MAX_VALUE, maxVersions);
+    }
+
+    public MockHTable(String tableName) {
+        this.tableName = tableName;
+    }
+
+    public MockHTable(String tableName, String... columnFamilies) {
+        this.tableName = tableName;
+        this.columnFamilies.addAll(Arrays.asList(columnFamilies));
+    }
+
+    public void addColumnFamily(String columnFamily) {
+        this.columnFamilies.add(columnFamily);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public byte[] getTableName() {
+        return tableName.getBytes();
+    }
+
+    @Override
+    public TableName getName() {
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Configuration getConfiguration() {
+        throw new RuntimeException(this.getClass() + " does NOT implement this method.");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public HTableDescriptor getTableDescriptor() throws IOException {
+        HTableDescriptor table = new HTableDescriptor(tableName);
+        for (String columnFamily : columnFamilies) {
+            table.addFamily(new HColumnDescriptor(columnFamily));
+        }
+        return table;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void mutateRow(RowMutations rm) throws IOException {
+        // currently only support Put and Delete
+        for (Mutation mutation : rm.getMutations()) {
+            if (mutation instanceof Put) {
+                put((Put) mutation);
+            } else if (mutation instanceof Delete) {
+                delete((Delete) mutation);
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Result append(Append append) throws IOException {
+        throw new RuntimeException(this.getClass() + " does NOT implement this method.");
+    }
+
+    private static List<KeyValue> toKeyValue(byte[] row, NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> rowdata, long timestampStart, long timestampEnd, int maxVersions) {
+        List<KeyValue> ret = new ArrayList<KeyValue>();
+        for (byte[] family : rowdata.keySet())
+            for (byte[] qualifier : rowdata.get(family).keySet()) {
+                int versionsAdded = 0;
+                for (Map.Entry<Long, byte[]> tsToVal : rowdata.get(family).get(qualifier).descendingMap().entrySet()) {
+                    if (versionsAdded++ == maxVersions)
+                        break;
+                    Long timestamp = tsToVal.getKey();
+                    if (timestamp < timestampStart)
+                        continue;
+                    if (timestamp > timestampEnd)
+                        continue;
+                    byte[] value = tsToVal.getValue();
+                    ret.add(new KeyValue(row, family, qualifier, timestamp, value));
+                }
+            }
+        return ret;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean exists(Get get) throws IOException {
+        Result result = get(get);
+        return result != null && result.isEmpty() == false;
+    }
+
+    @Override
+    public Boolean[] exists(List<Get> gets) throws IOException {
+        return new Boolean[0];
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void batch(List<? extends Row> actions, Object[] results) throws IOException, InterruptedException {
+        results = batch(actions);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Object[] batch(List<? extends Row> actions) throws IOException, InterruptedException {
+        Object[] results = new Object[actions.size()]; // same size.
+        for (int i = 0; i < actions.size(); i++) {
+            Row r = actions.get(i);
+            if (r instanceof Delete) {
+                delete((Delete) r);
+                results[i] = new Result();
+            }
+            if (r instanceof Put) {
+                put((Put) r);
+                results[i] = new Result();
+            }
+            if (r instanceof Get) {
+                Result result = get((Get) r);
+                results[i] = result;
+            }
+            if (r instanceof Increment) {
+                Result result = increment((Increment) r);
+                results[i] = result;
+            }
+            if (r instanceof Append) {
+                Result result = append((Append) r);
+                results[i] = result;
+            }
+        }
+        return results;
+    }
+
+    @Override
+    public <R> void batchCallback(List<? extends Row> actions, Object[] results, Batch.Callback<R> callback) throws IOException, InterruptedException {
+
+    }
+
+    @Override
+    public <R> Object[] batchCallback(List<? extends Row> actions, Batch.Callback<R> callback) throws IOException, InterruptedException {
+        return new Object[0];
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Result get(Get get) throws IOException {
+        if (!data.containsKey(get.getRow()))
+            return new Result();
+        byte[] row = get.getRow();
+        List<KeyValue> kvs = new ArrayList<KeyValue>();
+        if (!get.hasFamilies()) {
+            kvs = toKeyValue(row, data.get(row), get.getMaxVersions());
+        } else {
+            for (byte[] family : get.getFamilyMap().keySet()) {
+                if (data.get(row).get(family) == null)
+                    continue;
+                NavigableSet<byte[]> qualifiers = get.getFamilyMap().get(family);
+                if (qualifiers == null || qualifiers.isEmpty())
+                    qualifiers = data.get(row).get(family).navigableKeySet();
+                for (byte[] qualifier : qualifiers) {
+                    if (qualifier == null)
+                        qualifier = "".getBytes();
+                    if (!data.get(row).containsKey(family) || !data.get(row).get(family).containsKey(qualifier) || data.get(row).get(family).get(qualifier).isEmpty())
+                        continue;
+                    Map.Entry<Long, byte[]> timestampAndValue = data.get(row).get(family).get(qualifier).lastEntry();
+                    kvs.add(new KeyValue(row, family, qualifier, timestampAndValue.getKey(), timestampAndValue.getValue()));
+                }
+            }
+        }
+        Filter filter = get.getFilter();
+        if (filter != null) {
+            kvs = filter(filter, kvs);
+        }
+
+        return new Result(kvs);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Result[] get(List<Get> gets) throws IOException {
+        List<Result> results = new ArrayList<Result>();
+        for (Get g : gets) {
+            results.add(get(g));
+        }
+        return results.toArray(new Result[results.size()]);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Result getRowOrBefore(byte[] row, byte[] family) throws IOException {
+        // FIXME: implement
+        return null;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ResultScanner getScanner(Scan scan) throws IOException {
+        final List<Result> ret = new ArrayList<Result>();
+        byte[] st = scan.getStartRow();
+        byte[] sp = scan.getStopRow();
+        Filter filter = scan.getFilter();
+
+        for (byte[] row : data.keySet()) {
+            // if row is equal to startRow emit it. When startRow (inclusive) and
+            // stopRow (exclusive) is the same, it should not be excluded which would
+            // happen w/o this control.
+            if (st != null && st.length > 0 && Bytes.BYTES_COMPARATOR.compare(st, row) != 0) {
+                // if row is before startRow do not emit, pass to next row
+                if (st != null && st.length > 0 && Bytes.BYTES_COMPARATOR.compare(st, row) > 0)
+                    continue;
+                // if row is equal to stopRow or after it do not emit, stop iteration
+                if (sp != null && sp.length > 0 && Bytes.BYTES_COMPARATOR.compare(sp, row) <= 0)
+                    break;
+            }
+
+            List<KeyValue> kvs = null;
+            if (!scan.hasFamilies()) {
+                kvs = toKeyValue(row, data.get(row), scan.getTimeRange().getMin(), scan.getTimeRange().getMax(), scan.getMaxVersions());
+            } else {
+                kvs = new ArrayList<KeyValue>();
+                for (byte[] family : scan.getFamilyMap().keySet()) {
+                    if (data.get(row).get(family) == null)
+                        continue;
+                    NavigableSet<byte[]> qualifiers = scan.getFamilyMap().get(family);
+                    if (qualifiers == null || qualifiers.isEmpty())
+                        qualifiers = data.get(row).get(family).navigableKeySet();
+                    for (byte[] qualifier : qualifiers) {
+                        if (data.get(row).get(family).get(qualifier) == null)
+                            continue;
+                        for (Long timestamp : data.get(row).get(family).get(qualifier).descendingKeySet()) {
+                            if (timestamp < scan.getTimeRange().getMin())
+                                continue;
+                            if (timestamp > scan.getTimeRange().getMax())
+                                continue;
+                            byte[] value = data.get(row).get(family).get(qualifier).get(timestamp);
+                            kvs.add(new KeyValue(row, family, qualifier, timestamp, value));
+                            if (kvs.size() == scan.getMaxVersions()) {
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+            if (filter != null) {
+                kvs = filter(filter, kvs);
+                // Check for early out optimization
+                if (filter.filterAllRemaining()) {
+                    break;
+                }
+            }
+            if (!kvs.isEmpty()) {
+                ret.add(new Result(kvs));
+            }
+        }
+
+        return new ResultScanner() {
+            private final Iterator<Result> iterator = ret.iterator();
+
+            public Iterator<Result> iterator() {
+                return iterator;
+            }
+
+            public Result[] next(int nbRows) throws IOException {
+                ArrayList<Result> resultSets = new ArrayList<Result>(nbRows);
+                for (int i = 0; i < nbRows; i++) {
+                    Result next = next();
+                    if (next != null) {
+                        resultSets.add(next);
+                    } else {
+                        break;
+                    }
+                }
+                return resultSets.toArray(new Result[resultSets.size()]);
+            }
+
+            public Result next() throws IOException {
+                try {
+                    return iterator().next();
+                } catch (NoSuchElementException e) {
+                    return null;
+                }
+            }
+
+            public void close() {
+            }
+        };
+    }
+
+    /**
+     * Follows the logical flow through the filter methods for a single row.
+     *
+     * @param filter HBase filter.
+     * @param kvs    List of a row's KeyValues
+     * @return List of KeyValues that were not filtered.
+     */
+    private List<KeyValue> filter(Filter filter, List<KeyValue> kvs) throws IOException {
+        filter.reset();
+
+        List<KeyValue> tmp = new ArrayList<KeyValue>(kvs.size());
+        tmp.addAll(kvs);
+
+        /*
+         * Note. Filter flow for a single row. Adapted from
+         * "HBase: The Definitive Guide" (p. 163) by Lars George, 2011.
+         * See Figure 4-2 on p. 163.
+         */
+        boolean filteredOnRowKey = false;
+        List<KeyValue> nkvs = new ArrayList<KeyValue>(tmp.size());
+        for (KeyValue kv : tmp) {
+            if (filter.filterRowKey(kv.getBuffer(), kv.getRowOffset(), kv.getRowLength())) {
+                filteredOnRowKey = true;
+                break;
+            }
+            Filter.ReturnCode filterResult = filter.filterKeyValue(kv);
+            if (filterResult == Filter.ReturnCode.INCLUDE) {
+                nkvs.add(kv);
+            } else if (filterResult == Filter.ReturnCode.NEXT_ROW) {
+                break;
+            } else if (filterResult == Filter.ReturnCode.NEXT_COL || filterResult == Filter.ReturnCode.SKIP) {
+                continue;
+            }
+            /*
+             * Ignoring next key hint which is a optimization to reduce file
+             * system IO
+             */
+        }
+        if (filter.hasFilterRow() && !filteredOnRowKey) {
+            filter.filterRow(nkvs);
+        }
+        if (filter.filterRow() || filteredOnRowKey) {
+            nkvs.clear();
+        }
+        tmp = nkvs;
+        return tmp;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ResultScanner getScanner(byte[] family) throws IOException {
+        Scan scan = new Scan();
+        scan.addFamily(family);
+        return getScanner(scan);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ResultScanner getScanner(byte[] family, byte[] qualifier) throws IOException {
+        Scan scan = new Scan();
+        scan.addColumn(family, qualifier);
+        return getScanner(scan);
+    }
+
+    private <K, V> V forceFind(NavigableMap<K, V> map, K key, V newObject) {
+        V data = map.get(key);
+        if (data == null) {
+            data = newObject;
+            map.put(key, data);
+        }
+        return data;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void put(Put put) throws IOException {
+        byte[] row = put.getRow();
+        NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> rowData = forceFind(data, row, new TreeMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>>(Bytes.BYTES_COMPARATOR));
+        for (byte[] family : put.getFamilyMap().keySet()) {
+            if (columnFamilies.contains(new String(family)) == false) {
+                throw new RuntimeException("Not Exists columnFamily : " + new String(family));
+            }
+            NavigableMap<byte[], NavigableMap<Long, byte[]>> familyData = forceFind(rowData, family, new TreeMap<byte[], NavigableMap<Long, byte[]>>(Bytes.BYTES_COMPARATOR));
+            for (KeyValue kv : put.getFamilyMap().get(family)) {
+                kv.updateLatestStamp(Bytes.toBytes(System.currentTimeMillis()));
+                byte[] qualifier = kv.getQualifier();
+                NavigableMap<Long, byte[]> qualifierData = forceFind(familyData, qualifier, new TreeMap<Long, byte[]>());
+                qualifierData.put(kv.getTimestamp(), kv.getValue());
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void put(List<Put> puts) throws IOException {
+        for (Put put : puts) {
+            put(put);
+        }
+
+    }
+
+    private boolean check(byte[] row, byte[] family, byte[] qualifier, byte[] value) {
+        if (value == null || value.length == 0)
+            return !data.containsKey(row) || !data.get(row).containsKey(family) || !data.get(row).get(family).containsKey(qualifier);
+        else
+            return data.containsKey(row) && data.get(row).containsKey(family) && data.get(row).get(family).containsKey(qualifier) && !data.get(row).get(family).get(qualifier).isEmpty() && Arrays.equals(data.get(row).get(family).get(qualifier).lastEntry().getValue(), value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier, byte[] value, Put put) throws IOException {
+        if (check(row, family, qualifier, value)) {
+            put(put);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void delete(Delete delete) throws IOException {
+        byte[] row = delete.getRow();
+        if (data.get(row) == null)
+            return;
+        if (delete.getFamilyMap().size() == 0) {
+            data.remove(row);
+            return;
+        }
+        for (byte[] family : delete.getFamilyMap().keySet()) {
+            if (data.get(row).get(family) == null)
+                continue;
+            if (delete.getFamilyMap().get(family).isEmpty()) {
+                data.get(row).remove(family);
+                continue;
+            }
+            for (KeyValue kv : delete.getFamilyMap().get(family)) {
+                if (kv.isDeleteFamily()) {
+                    data.get(row).get(kv.getFamily()).clear();
+                } else {
+                    data.get(row).get(kv.getFamily()).remove(kv.getQualifier());
+                }
+            }
+            if (data.get(row).get(family).isEmpty()) {
+                data.get(row).remove(family);
+            }
+        }
+        if (data.get(row).isEmpty()) {
+            data.remove(row);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void delete(List<Delete> deletes) throws IOException {
+        for (Delete delete : deletes) {
+            delete(delete);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, byte[] value, Delete delete) throws IOException {
+        if (check(row, family, qualifier, value)) {
+            delete(delete);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Result increment(Increment increment) throws IOException {
+        throw new NotImplementedException();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public long incrementColumnValue(byte[] row, byte[] family, byte[] qualifier, long amount) throws IOException {
+        return incrementColumnValue(row, family, qualifier, amount, true);
+    }
+
+    @Override
+    public long incrementColumnValue(byte[] row, byte[] family, byte[] qualifier, long amount, Durability durability) throws IOException {
+        return 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public long incrementColumnValue(byte[] row, byte[] family, byte[] qualifier, long amount, boolean writeToWAL) throws IOException {
+        if (check(row, family, qualifier, null)) {
+            Put put = new Put(row);
+            put.add(family, qualifier, Bytes.toBytes(amount));
+            put(put);
+            return amount;
+        }
+        long newValue = Bytes.toLong(data.get(row).get(family).get(qualifier).lastEntry().getValue()) + amount;
+        data.get(row).get(family).get(qualifier).put(System.currentTimeMillis(), Bytes.toBytes(newValue));
+        return newValue;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean isAutoFlush() {
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void flushCommits() throws IOException {
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void close() throws IOException {
+    }
+
+    @Override
+    public CoprocessorRpcChannel coprocessorService(byte[] row) {
+        throw new NotImplementedException();
+
+    }
+
+    @Override
+    public <T extends Service, R> Map<byte[], R> coprocessorService(Class<T> service, byte[] startKey, byte[] endKey, Batch.Call<T, R> callable) throws ServiceException, Throwable {
+        throw new NotImplementedException();
+
+    }
+
+    @Override
+    public <T extends Service, R> void coprocessorService(Class<T> service, byte[] startKey, byte[] endKey, Batch.Call<T, R> callable, Batch.Callback<R> callback) throws ServiceException, Throwable {
+        throw new NotImplementedException();
+
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setAutoFlush(boolean autoFlush) {
+        throw new NotImplementedException();
+
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setAutoFlush(boolean autoFlush, boolean clearBufferOnFail) {
+        throw new NotImplementedException();
+
+    }
+
+    @Override
+    public void setAutoFlushTo(boolean autoFlush) {
+        throw new NotImplementedException();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public long getWriteBufferSize() {
+        throw new NotImplementedException();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setWriteBufferSize(long writeBufferSize) throws IOException {
+        throw new NotImplementedException();
+
+    }
+
+    @Override
+    public <R extends Message> Map<byte[], R> batchCoprocessorService(Descriptors.MethodDescriptor methodDescriptor, Message request, byte[] startKey, byte[] endKey, R responsePrototype) throws ServiceException, Throwable {
+        throw new NotImplementedException();
+
+    }
+
+    @Override
+    public <R extends Message> void batchCoprocessorService(Descriptors.MethodDescriptor methodDescriptor, Message request, byte[] startKey, byte[] endKey, R responsePrototype, Batch.Callback<R> callback) throws ServiceException, Throwable {
+        throw new NotImplementedException();
+
+    }
+
+    //@Override  (only since 0.98.8)
+    public boolean checkAndMutate(byte[] row, byte[] family, byte[] qualifier, CompareFilter.CompareOp compareOp, byte[] value, RowMutations mutation) throws IOException {
+        throw new NotImplementedException();
+
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/security/PasswordPlaceholderConfigurer.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/PasswordPlaceholderConfigurer.java b/server-base/src/main/java/org/apache/kylin/rest/security/PasswordPlaceholderConfigurer.java
new file mode 100644
index 0000000..2692da9
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/security/PasswordPlaceholderConfigurer.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.security;
+
+import java.util.Properties;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.kylin.common.KylinConfig;
+import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+import org.springframework.core.io.InputStreamResource;
+import org.springframework.core.io.Resource;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+
+/**
+ * @author xduo
+ * 
+ */
+public class PasswordPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
+
+    private static byte[] key = { 0x74, 0x68, 0x69, 0x73, 0x49, 0x73, 0x41, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79 };
+
+    public PasswordPlaceholderConfigurer() {
+        Resource[] resources = new Resource[1];
+        resources[0] = new InputStreamResource(KylinConfig.getKylinPropertiesAsInputStream());
+        this.setLocations(resources);
+    }
+
+    public static String encrypt(String strToEncrypt) {
+        try {
+            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+            final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
+            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
+            final String encryptedString = Base64.encodeBase64String(cipher.doFinal(strToEncrypt.getBytes()));
+            return encryptedString;
+        } catch (Exception e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    public static String decrypt(String strToDecrypt) {
+        try {
+            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
+            final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
+            cipher.init(Cipher.DECRYPT_MODE, secretKey);
+            final String decryptedString = new String(cipher.doFinal(Base64.decodeBase64(strToDecrypt)));
+            return decryptedString;
+        } catch (Exception e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    protected String resolvePlaceholder(String placeholder, Properties props) {
+        if (placeholder.toLowerCase().contains("password")) {
+            return decrypt(props.getProperty(placeholder));
+        } else {
+            return props.getProperty(placeholder);
+        }
+    }
+
+    private static void printUsage() {
+        System.out.println("Usage: java org.apache.kylin.rest.security.PasswordPlaceholderConfigurer <EncryptMethod> <your_password>");
+        System.out.println("EncryptMethod: AES or BCrypt");
+    }
+
+    public static void main(String[] args) {
+        if (args.length != 2) {
+            printUsage();
+            System.exit(1);
+        }
+
+        String encryptMethod = args[0];
+        String passwordTxt = args[1];
+        if ("AES".equalsIgnoreCase(encryptMethod)) {
+            // for encrypt password like LDAP password
+            System.out.println(encryptMethod + " encrypted password is: ");
+            System.out.println(encrypt(passwordTxt));
+        } else if ("BCrypt".equalsIgnoreCase(encryptMethod)) {
+            // for encrypt the predefined user password, like ADMIN, MODELER.
+            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
+            System.out.println(encryptMethod + " encrypted password is: ");
+            System.out.println(bCryptPasswordEncoder.encode(passwordTxt));
+        } else {
+            printUsage();
+            System.exit(1);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/security/RealAclHBaseStorage.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/RealAclHBaseStorage.java b/server-base/src/main/java/org/apache/kylin/rest/security/RealAclHBaseStorage.java
new file mode 100644
index 0000000..27d9720
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/security/RealAclHBaseStorage.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.security;
+
+import java.io.IOException;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.rest.service.AclService;
+import org.apache.kylin.rest.service.UserService;
+import org.apache.kylin.storage.hbase.HBaseConnection;
+
+/**
+ */
+public class RealAclHBaseStorage implements AclHBaseStorage {
+
+    private String hbaseUrl;
+    private String aclTableName;
+    private String userTableName;
+
+    @Override
+    public String prepareHBaseTable(Class<?> clazz) throws IOException {
+        String metadataUrl = KylinConfig.getInstanceFromEnv().getMetadataUrl();
+        int cut = metadataUrl.indexOf('@');
+        String tableNameBase = cut < 0 ? DEFAULT_TABLE_PREFIX : metadataUrl.substring(0, cut);
+        hbaseUrl = cut < 0 ? metadataUrl : metadataUrl.substring(cut + 1);
+
+        if (clazz == AclService.class) {
+            aclTableName = tableNameBase + ACL_TABLE_NAME;
+            HBaseConnection.createHTableIfNeeded(hbaseUrl, aclTableName, ACL_INFO_FAMILY, ACL_ACES_FAMILY);
+            return aclTableName;
+        } else if (clazz == UserService.class) {
+            userTableName = tableNameBase + USER_TABLE_NAME;
+            HBaseConnection.createHTableIfNeeded(hbaseUrl, userTableName, USER_AUTHORITY_FAMILY);
+            return userTableName;
+        } else {
+            throw new IllegalStateException("prepareHBaseTable for unknown class: " + clazz);
+        }
+    }
+
+    @Override
+    public HTableInterface getTable(String tableName) throws IOException {
+        if (StringUtils.equals(tableName, aclTableName)) {
+            return HBaseConnection.get(hbaseUrl).getTable(aclTableName);
+        } else if (StringUtils.equals(tableName, userTableName)) {
+            return HBaseConnection.get(hbaseUrl).getTable(userTableName);
+        } else {
+            throw new IllegalStateException("getTable failed" + tableName);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/security/SAMLUserDetailsService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/SAMLUserDetailsService.java b/server-base/src/main/java/org/apache/kylin/rest/security/SAMLUserDetailsService.java
new file mode 100644
index 0000000..24f8243
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/security/SAMLUserDetailsService.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.security;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.ldap.userdetails.LdapUserDetailsService;
+import org.springframework.security.saml.SAMLCredential;
+
+/**
+ * An implementation of SAMLUserDetailsService by delegating the query to LdapUserDetailsService.
+ */
+public class SAMLUserDetailsService implements org.springframework.security.saml.userdetails.SAMLUserDetailsService {
+
+    private static final Logger logger = LoggerFactory.getLogger(SAMLUserDetailsService.class);
+    private LdapUserDetailsService ldapUserDetailsService;
+
+    public SAMLUserDetailsService(LdapUserDetailsService ldapUserDetailsService) {
+        this.ldapUserDetailsService = ldapUserDetailsService;
+    }
+
+    @Override
+    public Object loadUserBySAML(SAMLCredential samlCredential) throws UsernameNotFoundException {
+        final String userEmail = samlCredential.getAttributeAsString("email");
+        logger.debug("samlCredential.email:" + userEmail);
+        final String userName = userEmail.substring(0, userEmail.indexOf("@"));
+
+        UserDetails userDetails = null;
+        try {
+            userDetails = ldapUserDetailsService.loadUserByUsername(userName);
+        } catch (org.springframework.security.core.userdetails.UsernameNotFoundException e) {
+            logger.error("User not found in LDAP, check whether he/she has been added to the groups.", e);
+        }
+        logger.debug("userDeail by search ldap with '" + userName + "' is: " + userDetails);
+        return userDetails;
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/security/UnauthorisedEntryPoint.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/security/UnauthorisedEntryPoint.java b/server-base/src/main/java/org/apache/kylin/rest/security/UnauthorisedEntryPoint.java
new file mode 100644
index 0000000..253bae3
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/security/UnauthorisedEntryPoint.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.security;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+/**
+ * Just return 401-unauthorized for every unauthorized request. The client side
+ * catches this and handles login.
+ * 
+ * @author xduo
+ */
+@Component(value = "unauthorisedEntryPoint")
+public class UnauthorisedEntryPoint implements AuthenticationEntryPoint {
+
+    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
+        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/service/AccessService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/AccessService.java b/server-base/src/main/java/org/apache/kylin/rest/service/AccessService.java
new file mode 100644
index 0000000..9561fbd
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/AccessService.java
@@ -0,0 +1,298 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.service;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.kylin.common.persistence.AclEntity;
+import org.apache.kylin.common.persistence.RootPersistentEntity;
+import org.apache.kylin.rest.constant.Constant;
+import org.apache.kylin.rest.exception.ForbiddenException;
+import org.apache.kylin.rest.response.AccessEntryResponse;
+import org.apache.kylin.rest.security.AclEntityFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.acls.domain.BasePermission;
+import org.springframework.security.acls.domain.GrantedAuthoritySid;
+import org.springframework.security.acls.domain.ObjectIdentityImpl;
+import org.springframework.security.acls.domain.PrincipalSid;
+import org.springframework.security.acls.model.AccessControlEntry;
+import org.springframework.security.acls.model.Acl;
+import org.springframework.security.acls.model.AlreadyExistsException;
+import org.springframework.security.acls.model.MutableAcl;
+import org.springframework.security.acls.model.NotFoundException;
+import org.springframework.security.acls.model.ObjectIdentity;
+import org.springframework.security.acls.model.Permission;
+import org.springframework.security.acls.model.Sid;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.Assert;
+
+/**
+ * @author xduo
+ * 
+ */
+@Component("accessService")
+public class AccessService {
+
+    @Autowired
+    private AclService aclService;
+
+    @Autowired
+    UserService userService;
+
+    // ~ Methods to manage acl life circle of domain objects ~
+
+    @Transactional
+    public Acl init(AclEntity ae, Permission initPermission) {
+        Acl acl = null;
+        ObjectIdentity objectIdentity = new ObjectIdentityImpl(ae.getClass(), ae.getId());
+
+        try {
+            // Create acl record for secured domain object.
+            acl = aclService.createAcl(objectIdentity);
+        } catch (AlreadyExistsException e) {
+            acl = (MutableAcl) aclService.readAclById(objectIdentity);
+        }
+
+        if (null != initPermission) {
+            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+            PrincipalSid sid = new PrincipalSid(auth);
+            acl = grant(ae, initPermission, sid);
+        }
+
+        return acl;
+    }
+
+    @Transactional
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#ae, 'ADMINISTRATION')")
+    public Acl grant(AclEntity ae, Permission permission, Sid sid) {
+        Assert.notNull(ae, "Acl domain object required");
+        Assert.notNull(permission, "Acl permission required");
+        Assert.notNull(sid, "Sid required");
+
+        ObjectIdentity objectIdentity = new ObjectIdentityImpl(ae.getClass(), ae.getId());
+        MutableAcl acl = null;
+
+        try {
+            acl = (MutableAcl) aclService.readAclById(objectIdentity);
+        } catch (NotFoundException e) {
+            acl = (MutableAcl) init(ae, null);
+        }
+
+        int indexOfAce = -1;
+        for (int i = 0; i < acl.getEntries().size(); i++) {
+            AccessControlEntry ace = acl.getEntries().get(i);
+
+            if (ace.getSid().equals(sid)) {
+                indexOfAce = i;
+            }
+        }
+
+        if (indexOfAce != -1) {
+            secureOwner(acl, indexOfAce);
+            acl.updateAce(indexOfAce, permission);
+        } else {
+            acl.insertAce(acl.getEntries().size(), permission, sid, true);
+        }
+
+        acl = aclService.updateAcl(acl);
+
+        return acl;
+    }
+
+    @Transactional
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#ae, 'ADMINISTRATION')")
+    public Acl update(AclEntity ae, Long accessEntryId, Permission newPermission) {
+        Assert.notNull(ae, "Acl domain object required");
+        Assert.notNull(accessEntryId, "Ace id required");
+        Assert.notNull(newPermission, "Acl permission required");
+
+        ObjectIdentity objectIdentity = new ObjectIdentityImpl(ae.getClass(), ae.getId());
+        MutableAcl acl = (MutableAcl) aclService.readAclById(objectIdentity);
+
+        int indexOfAce = -1;
+        for (int i = 0; i < acl.getEntries().size(); i++) {
+            AccessControlEntry ace = acl.getEntries().get(i);
+            if (ace.getId().equals(accessEntryId)) {
+                indexOfAce = i;
+                break;
+            }
+        }
+
+        if (indexOfAce != -1) {
+            secureOwner(acl, indexOfAce);
+
+            try {
+                acl.updateAce(indexOfAce, newPermission);
+                acl = aclService.updateAcl(acl);
+            } catch (NotFoundException e) {
+                //do nothing?
+            }
+        }
+
+        return acl;
+    }
+
+    @Transactional
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#ae, 'ADMINISTRATION')")
+    public Acl revoke(AclEntity ae, Long accessEntryId) {
+        Assert.notNull(ae, "Acl domain object required");
+        Assert.notNull(accessEntryId, "Ace id required");
+
+        ObjectIdentity objectIdentity = new ObjectIdentityImpl(ae.getClass(), ae.getId());
+        MutableAcl acl = (MutableAcl) aclService.readAclById(objectIdentity);
+        int indexOfAce = -1;
+
+        for (int i = 0; i < acl.getEntries().size(); i++) {
+            AccessControlEntry ace = acl.getEntries().get(i);
+            if (((Long) ace.getId()).equals(accessEntryId)) {
+                indexOfAce = i;
+                break;
+            }
+        }
+
+        if (indexOfAce != -1) {
+            secureOwner(acl, indexOfAce);
+
+            try {
+                acl.deleteAce(indexOfAce);
+                acl = aclService.updateAcl(acl);
+            } catch (NotFoundException e) {
+                //do nothing?
+            }
+        }
+
+        return acl;
+    }
+
+    @Transactional
+    public void inherit(AclEntity ae, AclEntity parentAe) {
+        Assert.notNull(ae, "Acl domain object required");
+        Assert.notNull(parentAe, "Parent acl required");
+
+        ObjectIdentity objectIdentity = new ObjectIdentityImpl(ae.getClass(), ae.getId());
+        MutableAcl acl = null;
+        try {
+            acl = (MutableAcl) aclService.readAclById(objectIdentity);
+        } catch (NotFoundException e) {
+            acl = (MutableAcl) init(ae, null);
+        }
+
+        ObjectIdentity parentObjectIdentity = new ObjectIdentityImpl(parentAe.getClass(), parentAe.getId());
+        MutableAcl parentAcl = null;
+        try {
+            parentAcl = (MutableAcl) aclService.readAclById(parentObjectIdentity);
+        } catch (NotFoundException e) {
+            parentAcl = (MutableAcl) init(parentAe, null);
+        }
+
+        if (null == acl || null == parentAcl) {
+            return;
+        }
+
+        acl.setEntriesInheriting(true);
+        acl.setParent(parentAcl);
+        aclService.updateAcl(acl);
+    }
+
+    @Transactional
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#ae, 'ADMINISTRATION')")
+    public void clean(AclEntity ae, boolean deleteChildren) {
+        Assert.notNull(ae, "Acl domain object required");
+
+        // For those may have null uuid, like DataModel, won't delete Acl.
+        if (ae.getId() == null)
+            return;
+
+        ObjectIdentity objectIdentity = new ObjectIdentityImpl(ae.getClass(), ae.getId());
+
+        try {
+            aclService.deleteAcl(objectIdentity, deleteChildren);
+        } catch (NotFoundException e) {
+            //do nothing?
+        }
+    }
+
+    // ~ Methods to get acl info of domain objects ~
+
+    public RootPersistentEntity getAclEntity(String entityType, String uuid) {
+        if (null == uuid) {
+            return null;
+        }
+
+        return AclEntityFactory.createAclEntity(entityType, uuid);
+    }
+
+    public Acl getAcl(AclEntity ae) {
+        if (null == ae) {
+            return null;
+        }
+        ObjectIdentity objectIdentity = new ObjectIdentityImpl(ae.getClass(), ae.getId());
+        Acl acl = null;
+
+        try {
+            acl = (MutableAcl) aclService.readAclById(objectIdentity);
+        } catch (NotFoundException e) {
+            //do nothing?
+        }
+
+        return acl;
+    }
+
+    public Sid getSid(String sid, boolean isPrincepal) {
+        if (isPrincepal) {
+            return new PrincipalSid(sid);
+        } else {
+            return new GrantedAuthoritySid(sid);
+        }
+    }
+
+    public List<AccessEntryResponse> generateAceResponses(Acl acl) {
+        if (null == acl) {
+            return Collections.emptyList();
+        }
+        List<AccessEntryResponse> accessControlEntities = new ArrayList<AccessEntryResponse>();
+
+        // Cause there is a circle reference in AccessControlEntry, it needs to
+        // set acl to null as a workaround.
+        for (AccessControlEntry ace : acl.getEntries()) {
+            accessControlEntities.add(new AccessEntryResponse(ace.getId(), ace.getSid(), ace.getPermission(), ace.isGranting()));
+        }
+
+        return accessControlEntities;
+    }
+
+    /**
+     * Protect admin permission granted to acl owner.
+     * 
+     * @param acl
+     * @param indexOfAce
+     */
+    private void secureOwner(MutableAcl acl, int indexOfAce) {
+        // Can't revoke admin permission from domain object owner
+        if (acl.getOwner().equals(acl.getEntries().get(indexOfAce).getSid()) && BasePermission.ADMINISTRATION.equals(acl.getEntries().get(indexOfAce).getPermission())) {
+            throw new ForbiddenException("Can't revoke admin permission of owner.");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/service/AclService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/AclService.java b/server-base/src/main/java/org/apache/kylin/rest/service/AclService.java
new file mode 100644
index 0000000..d693a67
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/AclService.java
@@ -0,0 +1,465 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.service;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.NavigableMap;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.hadoop.hbase.client.Delete;
+import org.apache.hadoop.hbase.client.Get;
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.ResultScanner;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
+import org.apache.kylin.common.util.Bytes;
+import org.apache.kylin.rest.security.AclHBaseStorage;
+import org.apache.kylin.rest.util.Serializer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.acls.domain.AccessControlEntryImpl;
+import org.springframework.security.acls.domain.AclAuthorizationStrategy;
+import org.springframework.security.acls.domain.AclImpl;
+import org.springframework.security.acls.domain.AuditLogger;
+import org.springframework.security.acls.domain.GrantedAuthoritySid;
+import org.springframework.security.acls.domain.ObjectIdentityImpl;
+import org.springframework.security.acls.domain.PermissionFactory;
+import org.springframework.security.acls.domain.PrincipalSid;
+import org.springframework.security.acls.model.AccessControlEntry;
+import org.springframework.security.acls.model.Acl;
+import org.springframework.security.acls.model.AlreadyExistsException;
+import org.springframework.security.acls.model.ChildrenExistException;
+import org.springframework.security.acls.model.MutableAcl;
+import org.springframework.security.acls.model.MutableAclService;
+import org.springframework.security.acls.model.NotFoundException;
+import org.springframework.security.acls.model.ObjectIdentity;
+import org.springframework.security.acls.model.PermissionGrantingStrategy;
+import org.springframework.security.acls.model.Sid;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.util.FieldUtils;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+
+/**
+ * @author xduo
+ * 
+ */
+@Component("aclService")
+public class AclService implements MutableAclService {
+
+    private static final Logger logger = LoggerFactory.getLogger(AclService.class);
+
+    private static String ACL_INFO_FAMILY_TYPE_COLUMN = "t";
+    private static String ACL_INFO_FAMILY_OWNER_COLUMN = "o";
+    private static String ACL_INFO_FAMILY_PARENT_COLUMN = "p";
+    private static String ACL_INFO_FAMILY_ENTRY_INHERIT_COLUMN = "i";
+
+    private Serializer<SidInfo> sidSerializer = new Serializer<SidInfo>(SidInfo.class);
+    private Serializer<DomainObjectInfo> domainObjSerializer = new Serializer<DomainObjectInfo>(DomainObjectInfo.class);
+    private Serializer<AceInfo> aceSerializer = new Serializer<AceInfo>(AceInfo.class);
+
+    private String aclTableName = null;
+
+    private final Field fieldAces = FieldUtils.getField(AclImpl.class, "aces");
+    private final Field fieldAcl = FieldUtils.getField(AccessControlEntryImpl.class, "acl");
+
+    @Autowired
+    protected PermissionGrantingStrategy permissionGrantingStrategy;
+
+    @Autowired
+    protected PermissionFactory aclPermissionFactory;
+
+    @Autowired
+    protected AclAuthorizationStrategy aclAuthorizationStrategy;
+
+    @Autowired
+    protected AuditLogger auditLogger;
+
+    @Autowired
+    protected AclHBaseStorage aclHBaseStorage;
+
+    public AclService() throws IOException {
+        fieldAces.setAccessible(true);
+        fieldAcl.setAccessible(true);
+    }
+
+    @PostConstruct
+    public void init() throws IOException {
+        aclTableName = aclHBaseStorage.prepareHBaseTable(AclService.class);
+    }
+
+    @Override
+    public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
+        List<ObjectIdentity> oids = new ArrayList<ObjectIdentity>();
+        HTableInterface htable = null;
+        try {
+            htable = aclHBaseStorage.getTable(aclTableName);
+
+            Scan scan = new Scan();
+            SingleColumnValueFilter parentFilter = new SingleColumnValueFilter(Bytes.toBytes(AclHBaseStorage.ACL_INFO_FAMILY), Bytes.toBytes(ACL_INFO_FAMILY_PARENT_COLUMN), CompareOp.EQUAL, domainObjSerializer.serialize(new DomainObjectInfo(parentIdentity)));
+            parentFilter.setFilterIfMissing(true);
+            scan.setFilter(parentFilter);
+
+            ResultScanner scanner = htable.getScanner(scan);
+            for (Result result = scanner.next(); result != null; result = scanner.next()) {
+                String id = Bytes.toString(result.getRow());
+                String type = Bytes.toString(result.getValue(Bytes.toBytes(AclHBaseStorage.ACL_INFO_FAMILY), Bytes.toBytes(ACL_INFO_FAMILY_TYPE_COLUMN)));
+
+                oids.add(new ObjectIdentityImpl(type, id));
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        } finally {
+            IOUtils.closeQuietly(htable);
+        }
+
+        return oids;
+    }
+
+    @Override
+    public Acl readAclById(ObjectIdentity object) throws NotFoundException {
+        Map<ObjectIdentity, Acl> aclsMap = readAclsById(Arrays.asList(object), null);
+        //        Assert.isTrue(aclsMap.containsKey(object), "There should have been an Acl entry for ObjectIdentity " + object);
+
+        return aclsMap.get(object);
+    }
+
+    @Override
+    public Acl readAclById(ObjectIdentity object, List<Sid> sids) throws NotFoundException {
+        Map<ObjectIdentity, Acl> aclsMap = readAclsById(Arrays.asList(object), sids);
+        Assert.isTrue(aclsMap.containsKey(object), "There should have been an Acl entry for ObjectIdentity " + object);
+
+        return aclsMap.get(object);
+    }
+
+    @Override
+    public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects) throws NotFoundException {
+        return readAclsById(objects, null);
+    }
+
+    @Override
+    public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> oids, List<Sid> sids) throws NotFoundException {
+        Map<ObjectIdentity, Acl> aclMaps = new HashMap<ObjectIdentity, Acl>();
+        HTableInterface htable = null;
+        Result result = null;
+        try {
+            htable = aclHBaseStorage.getTable(aclTableName);
+
+            for (ObjectIdentity oid : oids) {
+                result = htable.get(new Get(Bytes.toBytes(String.valueOf(oid.getIdentifier()))));
+
+                if (null != result && !result.isEmpty()) {
+                    SidInfo owner = sidSerializer.deserialize(result.getValue(Bytes.toBytes(AclHBaseStorage.ACL_INFO_FAMILY), Bytes.toBytes(ACL_INFO_FAMILY_OWNER_COLUMN)));
+                    Sid ownerSid = (null == owner) ? null : (owner.isPrincipal() ? new PrincipalSid(owner.getSid()) : new GrantedAuthoritySid(owner.getSid()));
+                    boolean entriesInheriting = Bytes.toBoolean(result.getValue(Bytes.toBytes(AclHBaseStorage.ACL_INFO_FAMILY), Bytes.toBytes(ACL_INFO_FAMILY_ENTRY_INHERIT_COLUMN)));
+
+                    Acl parentAcl = null;
+                    DomainObjectInfo parentInfo = domainObjSerializer.deserialize(result.getValue(Bytes.toBytes(AclHBaseStorage.ACL_INFO_FAMILY), Bytes.toBytes(ACL_INFO_FAMILY_PARENT_COLUMN)));
+                    if (null != parentInfo) {
+                        ObjectIdentity parentObj = new ObjectIdentityImpl(parentInfo.getType(), parentInfo.getId());
+                        parentAcl = readAclById(parentObj, null);
+                    }
+
+                    AclImpl acl = new AclImpl(oid, oid.getIdentifier(), aclAuthorizationStrategy, permissionGrantingStrategy, parentAcl, null, entriesInheriting, ownerSid);
+                    genAces(sids, result, acl);
+
+                    aclMaps.put(oid, acl);
+                } else {
+                    throw new NotFoundException("Unable to find ACL information for object identity '" + oid + "'");
+                }
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        } finally {
+            IOUtils.closeQuietly(htable);
+        }
+
+        return aclMaps;
+    }
+
+    @Override
+    public MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException {
+        Acl acl = null;
+
+        try {
+            acl = readAclById(objectIdentity);
+        } catch (NotFoundException e) {
+            //do nothing?
+        }
+        if (null != acl) {
+            throw new AlreadyExistsException("ACL of " + objectIdentity + " exists!");
+        }
+
+        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+        PrincipalSid sid = new PrincipalSid(auth);
+
+        HTableInterface htable = null;
+        try {
+            htable = aclHBaseStorage.getTable(aclTableName);
+
+            Put put = new Put(Bytes.toBytes(String.valueOf(objectIdentity.getIdentifier())));
+            put.add(Bytes.toBytes(AclHBaseStorage.ACL_INFO_FAMILY), Bytes.toBytes(ACL_INFO_FAMILY_TYPE_COLUMN), Bytes.toBytes(objectIdentity.getType()));
+            put.add(Bytes.toBytes(AclHBaseStorage.ACL_INFO_FAMILY), Bytes.toBytes(ACL_INFO_FAMILY_OWNER_COLUMN), sidSerializer.serialize(new SidInfo(sid)));
+            put.add(Bytes.toBytes(AclHBaseStorage.ACL_INFO_FAMILY), Bytes.toBytes(ACL_INFO_FAMILY_ENTRY_INHERIT_COLUMN), Bytes.toBytes(true));
+
+            htable.put(put);
+            htable.flushCommits();
+
+            logger.debug("ACL of " + objectIdentity + " created successfully.");
+        } catch (IOException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        } finally {
+            IOUtils.closeQuietly(htable);
+        }
+
+        return (MutableAcl) readAclById(objectIdentity);
+    }
+
+    @Override
+    public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws ChildrenExistException {
+        HTableInterface htable = null;
+        try {
+            htable = aclHBaseStorage.getTable(aclTableName);
+
+            Delete delete = new Delete(Bytes.toBytes(String.valueOf(objectIdentity.getIdentifier())));
+
+            List<ObjectIdentity> children = findChildren(objectIdentity);
+            if (!deleteChildren && children.size() > 0) {
+                throw new ChildrenExistException("Children exists for " + objectIdentity);
+            }
+
+            for (ObjectIdentity oid : children) {
+                deleteAcl(oid, deleteChildren);
+            }
+
+            htable.delete(delete);
+            htable.flushCommits();
+
+            logger.debug("ACL of " + objectIdentity + " deleted successfully.");
+        } catch (IOException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        } finally {
+            IOUtils.closeQuietly(htable);
+        }
+    }
+
+    @Override
+    public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException {
+        try {
+            readAclById(acl.getObjectIdentity());
+        } catch (NotFoundException e) {
+            throw e;
+        }
+
+        HTableInterface htable = null;
+        try {
+            htable = aclHBaseStorage.getTable(aclTableName);
+
+            Delete delete = new Delete(Bytes.toBytes(String.valueOf(acl.getObjectIdentity().getIdentifier())));
+            delete.deleteFamily(Bytes.toBytes(AclHBaseStorage.ACL_ACES_FAMILY));
+            htable.delete(delete);
+
+            Put put = new Put(Bytes.toBytes(String.valueOf(acl.getObjectIdentity().getIdentifier())));
+
+            if (null != acl.getParentAcl()) {
+                put.add(Bytes.toBytes(AclHBaseStorage.ACL_INFO_FAMILY), Bytes.toBytes(ACL_INFO_FAMILY_PARENT_COLUMN), domainObjSerializer.serialize(new DomainObjectInfo(acl.getParentAcl().getObjectIdentity())));
+            }
+
+            for (AccessControlEntry ace : acl.getEntries()) {
+                AceInfo aceInfo = new AceInfo(ace);
+                put.add(Bytes.toBytes(AclHBaseStorage.ACL_ACES_FAMILY), Bytes.toBytes(aceInfo.getSidInfo().getSid()), aceSerializer.serialize(aceInfo));
+            }
+
+            if (!put.isEmpty()) {
+                htable.put(put);
+                htable.flushCommits();
+
+                logger.debug("ACL of " + acl.getObjectIdentity() + " updated successfully.");
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        } finally {
+            IOUtils.closeQuietly(htable);
+        }
+
+        return (MutableAcl) readAclById(acl.getObjectIdentity());
+    }
+
+    private void genAces(List<Sid> sids, Result result, AclImpl acl) throws JsonParseException, JsonMappingException, IOException {
+        List<AceInfo> aceInfos = new ArrayList<AceInfo>();
+        if (null != sids) {
+            // Just return aces in sids
+            for (Sid sid : sids) {
+                String sidName = null;
+                if (sid instanceof PrincipalSid) {
+                    sidName = ((PrincipalSid) sid).getPrincipal();
+                } else if (sid instanceof GrantedAuthoritySid) {
+                    sidName = ((GrantedAuthoritySid) sid).getGrantedAuthority();
+                }
+
+                AceInfo aceInfo = aceSerializer.deserialize(result.getValue(Bytes.toBytes(AclHBaseStorage.ACL_ACES_FAMILY), Bytes.toBytes(sidName)));
+                if (null != aceInfo) {
+                    aceInfos.add(aceInfo);
+                }
+            }
+        } else {
+            NavigableMap<byte[], byte[]> familyMap = result.getFamilyMap(Bytes.toBytes(AclHBaseStorage.ACL_ACES_FAMILY));
+            for (byte[] qualifier : familyMap.keySet()) {
+                AceInfo aceInfo = aceSerializer.deserialize(familyMap.get(qualifier));
+
+                if (null != aceInfo) {
+                    aceInfos.add(aceInfo);
+                }
+            }
+        }
+
+        List<AccessControlEntry> newAces = new ArrayList<AccessControlEntry>();
+        for (int i = 0; i < aceInfos.size(); i++) {
+            AceInfo aceInfo = aceInfos.get(i);
+
+            if (null != aceInfo) {
+                Sid sid = aceInfo.getSidInfo().isPrincipal() ? new PrincipalSid(aceInfo.getSidInfo().getSid()) : new GrantedAuthoritySid(aceInfo.getSidInfo().getSid());
+                AccessControlEntry ace = new AccessControlEntryImpl(Long.valueOf(i), acl, sid, aclPermissionFactory.buildFromMask(aceInfo.getPermissionMask()), true, false, false);
+                newAces.add(ace);
+            }
+        }
+
+        this.setAces(acl, newAces);
+    }
+
+    private void setAces(AclImpl acl, List<AccessControlEntry> aces) {
+        try {
+            fieldAces.set(acl, aces);
+        } catch (IllegalAccessException e) {
+            throw new IllegalStateException("Could not set AclImpl entries", e);
+        }
+    }
+
+    protected static class DomainObjectInfo {
+        private String id;
+        private String type;
+
+        public DomainObjectInfo() {
+        }
+
+        public DomainObjectInfo(ObjectIdentity oid) {
+            super();
+            this.id = (String) oid.getIdentifier();
+            this.type = oid.getType();
+        }
+
+        public Serializable getId() {
+            return id;
+        }
+
+        public void setId(String id) {
+            this.id = id;
+        }
+
+        public String getType() {
+            return type;
+        }
+
+        public void setType(String type) {
+            this.type = type;
+        }
+    }
+
+    protected static class SidInfo {
+        private String sid;
+        private boolean isPrincipal;
+
+        public SidInfo() {
+        }
+
+        public SidInfo(Sid sid) {
+            if (sid instanceof PrincipalSid) {
+                this.sid = ((PrincipalSid) sid).getPrincipal();
+                this.isPrincipal = true;
+            } else if (sid instanceof GrantedAuthoritySid) {
+                this.sid = ((GrantedAuthoritySid) sid).getGrantedAuthority();
+                this.isPrincipal = false;
+            }
+        }
+
+        public String getSid() {
+            return sid;
+        }
+
+        public void setSid(String sid) {
+            this.sid = sid;
+        }
+
+        public boolean isPrincipal() {
+            return isPrincipal;
+        }
+
+        public void setPrincipal(boolean isPrincipal) {
+            this.isPrincipal = isPrincipal;
+        }
+    }
+
+    protected static class AceInfo {
+        private SidInfo sidInfo;
+        private int permissionMask;
+
+        public AceInfo() {
+        }
+
+        public AceInfo(AccessControlEntry ace) {
+            super();
+            this.sidInfo = new SidInfo(ace.getSid());
+            this.permissionMask = ace.getPermission().getMask();
+        }
+
+        public SidInfo getSidInfo() {
+            return sidInfo;
+        }
+
+        public void setSidInfo(SidInfo sidInfo) {
+            this.sidInfo = sidInfo;
+        }
+
+        public int getPermissionMask() {
+            return permissionMask;
+        }
+
+        public void setPermissionMask(int permissionMask) {
+            this.permissionMask = permissionMask;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/service/AdminService.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/AdminService.java b/server-base/src/main/java/org/apache/kylin/rest/service/AdminService.java
new file mode 100644
index 0000000..6c85898
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/AdminService.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.service;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.hadoop.util.ToolRunner;
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.rest.constant.Constant;
+import org.apache.kylin.rest.exception.InternalErrorException;
+import org.apache.kylin.storage.hbase.util.StorageCleanupJob;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author jianliu
+ */
+@Component("adminService")
+public class AdminService extends BasicService {
+    private static final Logger logger = LoggerFactory.getLogger(AdminService.class);
+
+    /**
+     * Get Java Env info as string
+     *
+     * @return
+     */
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
+    public String getEnv() {
+        logger.debug("Get Kylin Runtime environment");
+        PropertiesConfiguration tempConfig = new PropertiesConfiguration();
+
+        // Add Java Env
+
+        try {
+            String content = "";
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            // env
+            Map<String, String> env = System.getenv();
+
+            for (Map.Entry<String, String> entry : env.entrySet()) {
+                tempConfig.addProperty(entry.getKey(), entry.getValue());
+            }
+
+            // properties
+            Properties proterties = System.getProperties();
+
+            for (Map.Entry<Object, Object> entry : proterties.entrySet()) {
+                tempConfig.setProperty((String) entry.getKey(), entry.getValue());
+            }
+
+            // do save
+            tempConfig.save(baos);
+            content = baos.toString();
+            return content;
+        } catch (ConfigurationException e) {
+            throw new InternalErrorException("Failed to get Kylin env Config", e);
+        }
+    }
+
+    /**
+     * Get Java config info as String
+     *
+     * @return
+     */
+    // @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
+    public String getConfigAsString() {
+        logger.debug("Get Kylin Runtime Config");
+
+        try {
+            return KylinConfig.getInstanceFromEnv().getConfigAsString();
+        } catch (IOException e) {
+            throw new InternalErrorException("Failed to get Kylin Runtime Config", e);
+        }
+    }
+
+    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
+    public void cleanupStorage() {
+        StorageCleanupJob job = new StorageCleanupJob();
+        String[] args = new String[] { "-delete", "true" };
+        try {
+            ToolRunner.run(job, args);
+        } catch (Exception e) {
+            throw new InternalErrorException(e.getMessage(), e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/service/BadQueryDetector.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/service/BadQueryDetector.java b/server-base/src/main/java/org/apache/kylin/rest/service/BadQueryDetector.java
new file mode 100644
index 0000000..79e1d4a
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/service/BadQueryDetector.java
@@ -0,0 +1,248 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.service;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.NavigableSet;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.util.Pair;
+import org.apache.kylin.metadata.badquery.BadQueryHistoryManager;
+import org.apache.kylin.rest.request.SQLRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Maps;
+
+public class BadQueryDetector extends Thread {
+
+    private static final Logger logger = LoggerFactory.getLogger(BadQueryDetector.class);
+
+    private final ConcurrentMap<Thread, Entry> runningQueries = Maps.newConcurrentMap();
+    private final long detectionInterval;
+    private final int alertMB;
+    private final int alertRunningSec;
+    private KylinConfig kylinConfig;
+
+    private ArrayList<Notifier> notifiers = new ArrayList<Notifier>();
+
+    public BadQueryDetector() {
+        super("BadQueryDetector");
+        this.setDaemon(true);
+        this.kylinConfig = KylinConfig.getInstanceFromEnv();
+        this.detectionInterval = kylinConfig.getBadQueryDefaultDetectIntervalSeconds() * 1000;
+        this.alertMB = 100;
+        this.alertRunningSec = kylinConfig.getBadQueryDefaultAlertingSeconds();
+
+        initNotifiers();
+    }
+
+    public BadQueryDetector(long detectionInterval, int alertMB, int alertRunningSec) {
+        super("BadQueryDetector");
+        this.setDaemon(true);
+        this.detectionInterval = detectionInterval;
+        this.alertMB = alertMB;
+        this.alertRunningSec = alertRunningSec;
+        this.kylinConfig = KylinConfig.getInstanceFromEnv();
+
+        initNotifiers();
+    }
+
+    private void initNotifiers() {
+        this.notifiers.add(new LoggerNotifier());
+        if (kylinConfig.getBadQueryPersistentEnabled()) {
+            this.notifiers.add(new PersistenceNotifier());
+        }
+    }
+
+    public void registerNotifier(Notifier notifier) {
+        notifiers.add(notifier);
+    }
+
+    private void notify(String adj, float runningSec, long startTime, String project, String sql, Thread t) {
+        for (Notifier notifier : notifiers) {
+            try {
+                notifier.badQueryFound(adj, runningSec, startTime, project, sql, t);
+            } catch (Exception e) {
+                logger.error("", e);
+            }
+        }
+    }
+
+    public interface Notifier {
+        void badQueryFound(String adj, float runningSec, long startTime, String project, String sql, Thread t);
+    }
+
+    private class LoggerNotifier implements Notifier {
+        @Override
+        public void badQueryFound(String adj, float runningSec, long startTime, String project, String sql, Thread t) {
+            logger.info(adj + " query has been running " + runningSec + " seconds (project:" + project + ", thread: 0x" + Long.toHexString(t.getId()) + ") -- " + sql);
+        }
+    }
+
+    private class PersistenceNotifier implements Notifier {
+        BadQueryHistoryManager badQueryManager = BadQueryHistoryManager.getInstance(kylinConfig);
+        String serverHostname;
+        NavigableSet<Pair<Long, String>> cacheQueue = new TreeSet<>(new Comparator<Pair<Long, String>>() {
+            @Override
+            public int compare(Pair<Long, String> o1, Pair<Long, String> o2) {
+                if (o1.equals(o2)) {
+                    return 0;
+                } else if (o1.getFirst().equals(o2.getFirst())) {
+                    return o2.getSecond().compareTo(o2.getSecond());
+                } else {
+                    return (int) (o1.getFirst() - o2.getFirst());
+                }
+            }
+        });
+
+        public PersistenceNotifier() {
+            try {
+                serverHostname = InetAddress.getLocalHost().getHostName();
+            } catch (UnknownHostException e) {
+                serverHostname = "Unknow";
+                logger.warn("Error in get current hostname.", e);
+            }
+        }
+
+        @Override
+        public void badQueryFound(String adj, float runningSec, long startTime, String project, String sql, Thread t) {
+            try {
+                long cachingSeconds = (kylinConfig.getBadQueryDefaultAlertingSeconds() + 1) * 30;
+                Pair<Long, String> sqlPair = new Pair<>(startTime, sql);
+                if (!cacheQueue.contains(sqlPair)) {
+                    badQueryManager.addEntryToProject(sql, startTime, adj, runningSec, serverHostname, t.getName(), project);
+                    cacheQueue.add(sqlPair);
+                    while (!cacheQueue.isEmpty() && (System.currentTimeMillis() - cacheQueue.first().getFirst() > cachingSeconds * 1000 || cacheQueue.size() > kylinConfig.getBadQueryHistoryNum() * 3)) {
+                        cacheQueue.pollFirst();
+                    }
+                } else {
+                    badQueryManager.updateEntryToProject(sql, startTime, adj, runningSec, serverHostname, t.getName(), project);
+                }
+            } catch (IOException e) {
+                logger.error("Error in bad query persistence.", e);
+            }
+        }
+    }
+
+    public void queryStart(Thread thread, SQLRequest sqlRequest) {
+        runningQueries.put(thread, new Entry(sqlRequest, thread));
+    }
+
+    public void queryEnd(Thread thread) {
+        runningQueries.remove(thread);
+    }
+
+    private class Entry implements Comparable<Entry> {
+        final SQLRequest sqlRequest;
+        final long startTime;
+        final Thread thread;
+
+        Entry(SQLRequest sqlRequest, Thread thread) {
+            this.sqlRequest = sqlRequest;
+            this.startTime = System.currentTimeMillis();
+            this.thread = thread;
+        }
+
+        @Override
+        public int compareTo(Entry o) {
+            return (int) (this.startTime - o.startTime);
+        }
+    }
+
+    public void run() {
+        while (true) {
+            try {
+                Thread.sleep(detectionInterval);
+            } catch (InterruptedException e) {
+                // stop detection and exit
+                return;
+            }
+
+            try {
+                detectBadQuery();
+            } catch (Exception ex) {
+                logger.error("", ex);
+            }
+        }
+    }
+
+    private void detectBadQuery() {
+        long now = System.currentTimeMillis();
+        ArrayList<Entry> entries = new ArrayList<Entry>(runningQueries.values());
+        Collections.sort(entries);
+
+        // report if query running long
+        for (Entry e : entries) {
+            float runningSec = (float) (now - e.startTime) / 1000;
+            if (runningSec >= alertRunningSec) {
+                notify("Slow", runningSec, e.startTime, e.sqlRequest.getProject(), e.sqlRequest.getSql(), e.thread);
+                dumpStackTrace(e.thread);
+            } else {
+                break; // entries are sorted by startTime
+            }
+        }
+
+        // report if low memory
+        if (getSystemAvailMB() < alertMB) {
+            logger.info("System free memory less than " + alertMB + " MB. " + entries.size() + " queries running.");
+        }
+    }
+
+    // log the stack trace of bad query thread for further analysis
+    private void dumpStackTrace(Thread t) {
+        int maxStackTraceDepth = kylinConfig.getBadQueryStackTraceDepth();
+        int current = 0;
+
+        StackTraceElement[] stackTrace = t.getStackTrace();
+        StringBuilder buf = new StringBuilder("Problematic thread 0x" + Long.toHexString(t.getId()));
+        buf.append("\n");
+        for (StackTraceElement e : stackTrace) {
+            if (++current > maxStackTraceDepth) {
+                break;
+            }
+            buf.append("\t").append("at ").append(e.toString()).append("\n");
+        }
+        logger.info(buf.toString());
+    }
+
+    public static final int ONE_MB = 1024 * 1024;
+
+    public static long getSystemAvailBytes() {
+        Runtime runtime = Runtime.getRuntime();
+        long totalMemory = runtime.totalMemory(); // current heap allocated to the VM process
+        long freeMemory = runtime.freeMemory(); // out of the current heap, how much is free
+        long maxMemory = runtime.maxMemory(); // Max heap VM can use e.g. Xmx setting
+        long usedMemory = totalMemory - freeMemory; // how much of the current heap the VM is using
+        long availableMemory = maxMemory - usedMemory; // available memory i.e. Maximum heap size minus the current amount used
+        return availableMemory;
+    }
+
+    public static int getSystemAvailMB() {
+        return (int) (getSystemAvailBytes() / ONE_MB);
+    }
+
+}


[05/13] kylin git commit: KYLIN-1823 split code from kylin-server into kylin-server-base

Posted by li...@apache.org.
http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/controller/QueryController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/QueryController.java b/server/src/main/java/org/apache/kylin/rest/controller/QueryController.java
deleted file mode 100644
index 93b71ad..0000000
--- a/server/src/main/java/org/apache/kylin/rest/controller/QueryController.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.controller;
-
-import java.io.IOException;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.annotation.PostConstruct;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.common.debug.BackdoorToggles;
-import org.apache.kylin.cube.CubeInstance;
-import org.apache.kylin.rest.constant.Constant;
-import org.apache.kylin.rest.exception.InternalErrorException;
-import org.apache.kylin.rest.model.Query;
-import org.apache.kylin.rest.model.SelectedColumnMeta;
-import org.apache.kylin.rest.model.TableMeta;
-import org.apache.kylin.rest.request.MetaRequest;
-import org.apache.kylin.rest.request.PrepareSqlRequest;
-import org.apache.kylin.rest.request.SQLRequest;
-import org.apache.kylin.rest.request.SaveSqlRequest;
-import org.apache.kylin.rest.response.SQLResponse;
-import org.apache.kylin.rest.service.QueryService;
-import org.apache.kylin.rest.util.QueryUtil;
-import org.apache.kylin.storage.exception.ScanOutOfLimitException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.AccessDeniedException;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.supercsv.io.CsvListWriter;
-import org.supercsv.io.ICsvListWriter;
-import org.supercsv.prefs.CsvPreference;
-
-import com.google.common.base.Preconditions;
-
-import net.sf.ehcache.Cache;
-import net.sf.ehcache.CacheManager;
-import net.sf.ehcache.Element;
-
-/**
- * Handle query requests.
- * 
- * @author xduo
- */
-@Controller
-public class QueryController extends BasicController {
-
-    private static final Logger logger = LoggerFactory.getLogger(QueryController.class);
-
-    public static final String SUCCESS_QUERY_CACHE = "StorageCache";
-    public static final String EXCEPTION_QUERY_CACHE = "ExceptionQueryCache";
-
-    @Autowired
-    private QueryService queryService;
-
-    @Autowired
-    private CacheManager cacheManager;
-
-    @PostConstruct
-    public void init() throws IOException {
-        Preconditions.checkNotNull(cacheManager, "cacheManager is not injected yet");
-    }
-
-    @RequestMapping(value = "/query", method = RequestMethod.POST)
-    @ResponseBody
-    public SQLResponse query(@RequestBody SQLRequest sqlRequest) {
-        return doQueryWithCache(sqlRequest);
-    }
-
-    // TODO should be just "prepare" a statement, get back expected ResultSetMetaData
-    @RequestMapping(value = "/query/prestate", method = RequestMethod.POST, produces = "application/json")
-    @ResponseBody
-    public SQLResponse prepareQuery(@RequestBody PrepareSqlRequest sqlRequest) {
-        return doQueryWithCache(sqlRequest);
-    }
-
-    @RequestMapping(value = "/saved_queries", method = RequestMethod.POST)
-    @ResponseBody
-    public void saveQuery(@RequestBody SaveSqlRequest sqlRequest) throws IOException {
-        String creator = SecurityContextHolder.getContext().getAuthentication().getName();
-        Query newQuery = new Query(sqlRequest.getName(), sqlRequest.getProject(), sqlRequest.getSql(), sqlRequest.getDescription());
-
-        queryService.saveQuery(creator, newQuery);
-    }
-
-    @RequestMapping(value = "/saved_queries/{id}", method = RequestMethod.DELETE)
-    @ResponseBody
-    public void removeQuery(@PathVariable String id) throws IOException {
-        String creator = SecurityContextHolder.getContext().getAuthentication().getName();
-        queryService.removeQuery(creator, id);
-    }
-
-    @RequestMapping(value = "/saved_queries", method = RequestMethod.GET)
-    @ResponseBody
-    public List<Query> getQueries() throws IOException {
-        String creator = SecurityContextHolder.getContext().getAuthentication().getName();
-        return queryService.getQueries(creator);
-    }
-
-    @RequestMapping(value = "/query/format/{format}", method = RequestMethod.GET)
-    @ResponseBody
-    public void downloadQueryResult(@PathVariable String format, SQLRequest sqlRequest, HttpServletResponse response) {
-        SQLResponse result = doQueryWithCache(sqlRequest);
-        response.setContentType("text/" + format + ";charset=utf-8");
-        response.setHeader("Content-Disposition", "attachment; filename=\"result." + format + "\"");
-        ICsvListWriter csvWriter = null;
-
-        try {
-            csvWriter = new CsvListWriter(response.getWriter(), CsvPreference.STANDARD_PREFERENCE);
-
-            List<String> headerList = new ArrayList<String>();
-
-            for (SelectedColumnMeta column : result.getColumnMetas()) {
-                headerList.add(column.getName());
-            }
-
-            String[] headers = new String[headerList.size()];
-            csvWriter.writeHeader(headerList.toArray(headers));
-
-            for (List<String> row : result.getResults()) {
-                csvWriter.write(row);
-            }
-        } catch (IOException e) {
-            logger.error("", e);
-        } finally {
-            IOUtils.closeQuietly(csvWriter);
-        }
-    }
-
-    @RequestMapping(value = "/tables_and_columns", method = RequestMethod.GET)
-    @ResponseBody
-    public List<TableMeta> getMetadata(MetaRequest metaRequest) {
-        try {
-            return queryService.getMetadata(metaRequest.getProject());
-        } catch (SQLException e) {
-            logger.error(e.getLocalizedMessage(), e);
-            throw new InternalErrorException(e.getLocalizedMessage(), e);
-        }
-    }
-
-    private SQLResponse doQueryWithCache(SQLRequest sqlRequest) {
-        try {
-            BackdoorToggles.setToggles(sqlRequest.getBackdoorToggles());
-
-            String sql = sqlRequest.getSql();
-            String project = sqlRequest.getProject();
-            logger.info("Using project: " + project);
-            logger.info("The original query:  " + sql);
-
-            String serverMode = KylinConfig.getInstanceFromEnv().getServerMode();
-            if (!(Constant.SERVER_MODE_QUERY.equals(serverMode.toLowerCase()) || Constant.SERVER_MODE_ALL.equals(serverMode.toLowerCase()))) {
-                throw new InternalErrorException("Query is not allowed in " + serverMode + " mode.");
-            }
-
-            if (!sql.toLowerCase().contains("select")) {
-                logger.debug("Directly return exception as not supported");
-                throw new InternalErrorException("Not Supported SQL.");
-            }
-
-            long startTime = System.currentTimeMillis();
-
-            SQLResponse sqlResponse = searchQueryInCache(sqlRequest);
-            try {
-                if (null == sqlResponse) {
-                    sqlResponse = queryService.query(sqlRequest);
-
-                    long durationThreshold = KylinConfig.getInstanceFromEnv().getQueryDurationCacheThreshold();
-                    long scancountThreshold = KylinConfig.getInstanceFromEnv().getQueryScanCountCacheThreshold();
-                    sqlResponse.setDuration(System.currentTimeMillis() - startTime);
-                    logger.info("Stats of SQL response: isException: {}, duration: {}, total scan count {}", //
-                            new String[] { String.valueOf(sqlResponse.getIsException()), String.valueOf(sqlResponse.getDuration()), String.valueOf(sqlResponse.getTotalScanCount()) });
-                    if (!sqlResponse.getIsException() && (sqlResponse.getDuration() > durationThreshold || sqlResponse.getTotalScanCount() > scancountThreshold)) {
-                        cacheManager.getCache(SUCCESS_QUERY_CACHE).put(new Element(sqlRequest, sqlResponse));
-                    }
-                } else {
-                    sqlResponse.setDuration(System.currentTimeMillis() - startTime);
-                }
-
-                checkQueryAuth(sqlResponse);
-
-            } catch (Throwable e) { // calcite may throw AssertError
-                logger.error("Exception when execute sql", e);
-                String errMsg = QueryUtil.makeErrorMsgUserFriendly(e);
-
-                sqlResponse = new SQLResponse(null, null, 0, true, errMsg);
-
-                // for exception queries, only cache ScanOutOfLimitException
-                if (e instanceof ScanOutOfLimitException) {
-                    Cache exceptionCache = cacheManager.getCache(EXCEPTION_QUERY_CACHE);
-                    exceptionCache.put(new Element(sqlRequest, sqlResponse));
-                }
-            }
-
-            queryService.logQuery(sqlRequest, sqlResponse);
-
-            if (sqlResponse.getIsException())
-                throw new InternalErrorException(sqlResponse.getExceptionMessage());
-
-            return sqlResponse;
-
-        } finally {
-            BackdoorToggles.cleanToggles();
-        }
-    }
-
-    private SQLResponse searchQueryInCache(SQLRequest sqlRequest) {
-        SQLResponse response = null;
-        Cache exceptionCache = cacheManager.getCache(EXCEPTION_QUERY_CACHE);
-        Cache successCache = cacheManager.getCache(SUCCESS_QUERY_CACHE);
-
-        if (KylinConfig.getInstanceFromEnv().isQueryCacheEnabled() && !BackdoorToggles.getDisableCache()) {
-            if (exceptionCache.get(sqlRequest) != null) {
-                logger.info("The sqlResponse is found in EXCEPTION_QUERY_CACHE");
-                Element element = exceptionCache.get(sqlRequest);
-                response = (SQLResponse) element.getObjectValue();
-                response.setHitExceptionCache(true);
-            } else if (successCache.get(sqlRequest) != null) {
-                logger.info("The sqlResponse is found in SUCCESS_QUERY_CACHE");
-                Element element = successCache.get(sqlRequest);
-                response = (SQLResponse) element.getObjectValue();
-                response.setStorageCacheUsed(true);
-            }
-        }
-
-        return response;
-    }
-
-    private void checkQueryAuth(SQLResponse sqlResponse) throws AccessDeniedException {
-        if (!sqlResponse.getIsException() && KylinConfig.getInstanceFromEnv().isQuerySecureEnabled()) {
-            CubeInstance cubeInstance = this.queryService.getCubeManager().getCube(sqlResponse.getCube());
-            queryService.checkAuthorization(cubeInstance);
-        }
-    }
-
-    public void setQueryService(QueryService queryService) {
-        this.queryService = queryService;
-    }
-
-    public void setCacheManager(CacheManager cacheManager) {
-        this.cacheManager = cacheManager;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/controller/StreamingController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/StreamingController.java b/server/src/main/java/org/apache/kylin/rest/controller/StreamingController.java
deleted file mode 100644
index f3374c3..0000000
--- a/server/src/main/java/org/apache/kylin/rest/controller/StreamingController.java
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.controller;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.UUID;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.common.util.JsonUtil;
-import org.apache.kylin.engine.mr.HadoopUtil;
-import org.apache.kylin.engine.streaming.StreamingConfig;
-import org.apache.kylin.metadata.MetadataManager;
-import org.apache.kylin.metadata.model.TableDesc;
-import org.apache.kylin.rest.exception.BadRequestException;
-import org.apache.kylin.rest.exception.ForbiddenException;
-import org.apache.kylin.rest.exception.InternalErrorException;
-import org.apache.kylin.rest.exception.NotFoundException;
-import org.apache.kylin.rest.request.StreamingRequest;
-import org.apache.kylin.rest.service.CubeService;
-import org.apache.kylin.rest.service.KafkaConfigService;
-import org.apache.kylin.rest.service.StreamingService;
-import org.apache.kylin.source.kafka.config.KafkaConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.AccessDeniedException;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-
-/**
- * StreamingController is defined as Restful API entrance for UI.
- *
- * @author jiazhong
- */
-@Controller
-@RequestMapping(value = "/streaming")
-public class StreamingController extends BasicController {
-    private static final Logger logger = LoggerFactory.getLogger(StreamingController.class);
-
-    @Autowired
-    private StreamingService streamingService;
-    @Autowired
-    private KafkaConfigService kafkaConfigService;
-    @Autowired
-    private CubeService cubeMgmtService;
-
-    @RequestMapping(value = "/getConfig", method = { RequestMethod.GET })
-    @ResponseBody
-    public List<StreamingConfig> getStreamings(@RequestParam(value = "table", required = false) String table, @RequestParam(value = "limit", required = false) Integer limit, @RequestParam(value = "offset", required = false) Integer offset) {
-        try {
-            return streamingService.getStreamingConfigs(table, limit, offset);
-        } catch (IOException e) {
-            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
-            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
-        }
-    }
-
-    @RequestMapping(value = "/getKfkConfig", method = { RequestMethod.GET })
-    @ResponseBody
-    public List<KafkaConfig> getKafkaConfigs(@RequestParam(value = "kafkaConfigName", required = false) String kafkaConfigName, @RequestParam(value = "limit", required = false) Integer limit, @RequestParam(value = "offset", required = false) Integer offset) {
-        try {
-            return kafkaConfigService.getKafkaConfigs(kafkaConfigName, limit, offset);
-        } catch (IOException e) {
-            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
-            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
-        }
-    }
-
-    /**
-     *
-     * create Streaming Schema
-     * @throws java.io.IOException
-     */
-    @RequestMapping(value = "", method = { RequestMethod.POST })
-    @ResponseBody
-    public StreamingRequest saveStreamingConfig(@RequestBody StreamingRequest streamingRequest) {
-
-        String project = streamingRequest.getProject();
-        TableDesc tableDesc = deserializeTableDesc(streamingRequest);
-        StreamingConfig streamingConfig = deserializeSchemalDesc(streamingRequest);
-        KafkaConfig kafkaConfig = deserializeKafkaSchemalDesc(streamingRequest);
-        boolean saveStreamingSuccess = false, saveKafkaSuccess = false;
-
-        try {
-            tableDesc.setUuid(UUID.randomUUID().toString());
-            MetadataManager metaMgr = MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
-            metaMgr.saveSourceTable(tableDesc);
-            cubeMgmtService.syncTableToProject(new String[] { tableDesc.getIdentity() }, project);
-        } catch (IOException e) {
-            throw new BadRequestException("Failed to add streaming table.");
-        }
-
-        streamingConfig.setName(tableDesc.getIdentity());
-        kafkaConfig.setName(tableDesc.getIdentity());
-        try {
-            if (StringUtils.isEmpty(streamingConfig.getName())) {
-                logger.info("StreamingConfig should not be empty.");
-                throw new BadRequestException("StremingConfig name should not be empty.");
-            }
-            try {
-                streamingConfig.setUuid(UUID.randomUUID().toString());
-                streamingService.createStreamingConfig(streamingConfig);
-                saveStreamingSuccess = true;
-            } catch (IOException e) {
-                logger.error("Failed to save StreamingConfig:" + e.getLocalizedMessage(), e);
-                throw new InternalErrorException("Failed to save StreamingConfig: " + e.getLocalizedMessage());
-            }
-            try {
-                kafkaConfig.setUuid(UUID.randomUUID().toString());
-                kafkaConfigService.createKafkaConfig(kafkaConfig);
-                saveKafkaSuccess = true;
-            } catch (IOException e) {
-                try {
-                    streamingService.dropStreamingConfig(streamingConfig);
-                } catch (IOException e1) {
-                    throw new InternalErrorException("StreamingConfig is created, but failed to create KafkaConfig: " + e.getLocalizedMessage());
-                }
-                logger.error("Failed to save KafkaConfig:" + e.getLocalizedMessage(), e);
-                throw new InternalErrorException("Failed to save KafkaConfig: " + e.getLocalizedMessage());
-            }
-        } finally {
-            if (saveKafkaSuccess == false || saveStreamingSuccess == false) {
-
-                if (saveStreamingSuccess == true) {
-                    StreamingConfig sConfig = streamingService.getStreamingManager().getStreamingConfig(streamingConfig.getName());
-                    try {
-                        streamingService.dropStreamingConfig(sConfig);
-                    } catch (IOException e) {
-                        throw new InternalErrorException("Action failed and failed to rollback the created streaming config: " + e.getLocalizedMessage());
-                    }
-                }
-                if (saveKafkaSuccess == true) {
-                    try {
-                        KafkaConfig kConfig = kafkaConfigService.getKafkaConfig(kafkaConfig.getName());
-                        kafkaConfigService.dropKafkaConfig(kConfig);
-                    } catch (IOException e) {
-                        throw new InternalErrorException("Action failed and failed to rollback the created kafka config: " + e.getLocalizedMessage());
-                    }
-                }
-            }
-
-        }
-        streamingRequest.setSuccessful(true);
-        return streamingRequest;
-    }
-
-    @RequestMapping(value = "", method = { RequestMethod.PUT })
-    @ResponseBody
-    public StreamingRequest updateStreamingConfig(@RequestBody StreamingRequest streamingRequest) throws JsonProcessingException {
-        StreamingConfig streamingConfig = deserializeSchemalDesc(streamingRequest);
-        KafkaConfig kafkaConfig = deserializeKafkaSchemalDesc(streamingRequest);
-
-        if (streamingConfig == null) {
-            return streamingRequest;
-        }
-        try {
-            streamingConfig = streamingService.updateStreamingConfig(streamingConfig);
-        } catch (AccessDeniedException accessDeniedException) {
-            throw new ForbiddenException("You don't have right to update this StreamingConfig.");
-        } catch (Exception e) {
-            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
-            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
-        }
-        try {
-            kafkaConfig = kafkaConfigService.updateKafkaConfig(kafkaConfig);
-        } catch (AccessDeniedException accessDeniedException) {
-            throw new ForbiddenException("You don't have right to update this KafkaConfig.");
-        } catch (Exception e) {
-            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
-            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
-        }
-
-        streamingRequest.setSuccessful(true);
-
-        return streamingRequest;
-    }
-
-    @RequestMapping(value = "/{configName}", method = { RequestMethod.DELETE })
-    @ResponseBody
-    public void deleteConfig(@PathVariable String configName) throws IOException {
-        StreamingConfig config = streamingService.getStreamingManager().getStreamingConfig(configName);
-        KafkaConfig kafkaConfig = kafkaConfigService.getKafkaConfig(configName);
-        if (null == config) {
-            throw new NotFoundException("StreamingConfig with name " + configName + " not found..");
-        }
-        try {
-            streamingService.dropStreamingConfig(config);
-            kafkaConfigService.dropKafkaConfig(kafkaConfig);
-        } catch (Exception e) {
-            logger.error(e.getLocalizedMessage(), e);
-            throw new InternalErrorException("Failed to delete StreamingConfig. " + " Caused by: " + e.getMessage(), e);
-        }
-    }
-
-    private TableDesc deserializeTableDesc(StreamingRequest streamingRequest) {
-        TableDesc desc = null;
-        try {
-            logger.debug("Saving TableDesc " + streamingRequest.getTableData());
-            desc = JsonUtil.readValue(streamingRequest.getTableData(), TableDesc.class);
-        } catch (JsonParseException e) {
-            logger.error("The TableDesc definition is invalid.", e);
-            updateRequest(streamingRequest, false, e.getMessage());
-        } catch (JsonMappingException e) {
-            logger.error("The data TableDesc definition is invalid.", e);
-            updateRequest(streamingRequest, false, e.getMessage());
-        } catch (IOException e) {
-            logger.error("Failed to deal with the request.", e);
-            throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
-        }
-
-        String[] dbTable = HadoopUtil.parseHiveTableName(desc.getName());
-        desc.setName(dbTable[1]);
-        desc.setDatabase(dbTable[0]);
-        desc.getIdentity();
-        return desc;
-    }
-
-    private StreamingConfig deserializeSchemalDesc(StreamingRequest streamingRequest) {
-        StreamingConfig desc = null;
-        try {
-            logger.debug("Saving StreamingConfig " + streamingRequest.getStreamingConfig());
-            desc = JsonUtil.readValue(streamingRequest.getStreamingConfig(), StreamingConfig.class);
-        } catch (JsonParseException e) {
-            logger.error("The StreamingConfig definition is invalid.", e);
-            updateRequest(streamingRequest, false, e.getMessage());
-        } catch (JsonMappingException e) {
-            logger.error("The data StreamingConfig definition is invalid.", e);
-            updateRequest(streamingRequest, false, e.getMessage());
-        } catch (IOException e) {
-            logger.error("Failed to deal with the request.", e);
-            throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
-        }
-        return desc;
-    }
-
-    private KafkaConfig deserializeKafkaSchemalDesc(StreamingRequest streamingRequest) {
-        KafkaConfig desc = null;
-        try {
-            logger.debug("Saving KafkaConfig " + streamingRequest.getKafkaConfig());
-            desc = JsonUtil.readValue(streamingRequest.getKafkaConfig(), KafkaConfig.class);
-        } catch (JsonParseException e) {
-            logger.error("The KafkaConfig definition is invalid.", e);
-            updateRequest(streamingRequest, false, e.getMessage());
-        } catch (JsonMappingException e) {
-            logger.error("The data KafkaConfig definition is invalid.", e);
-            updateRequest(streamingRequest, false, e.getMessage());
-        } catch (IOException e) {
-            logger.error("Failed to deal with the request.", e);
-            throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
-        }
-        return desc;
-    }
-
-    private void updateRequest(StreamingRequest request, boolean success, String message) {
-        request.setSuccessful(success);
-        request.setMessage(message);
-    }
-
-    public void setStreamingService(StreamingService streamingService) {
-        this.streamingService = streamingService;
-    }
-
-    public void setKafkaConfigService(KafkaConfigService kafkaConfigService) {
-        this.kafkaConfigService = kafkaConfigService;
-    }
-
-    public void setCubeService(CubeService cubeService) {
-        this.cubeMgmtService = cubeService;
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/controller/TableController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/TableController.java b/server/src/main/java/org/apache/kylin/rest/controller/TableController.java
deleted file mode 100644
index 1c3377b..0000000
--- a/server/src/main/java/org/apache/kylin/rest/controller/TableController.java
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.controller;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.common.util.JsonUtil;
-import org.apache.kylin.engine.mr.HadoopUtil;
-import org.apache.kylin.engine.streaming.StreamingConfig;
-import org.apache.kylin.metadata.MetadataConstants;
-import org.apache.kylin.metadata.MetadataManager;
-import org.apache.kylin.metadata.model.ColumnDesc;
-import org.apache.kylin.metadata.model.TableDesc;
-import org.apache.kylin.rest.exception.InternalErrorException;
-import org.apache.kylin.rest.request.CardinalityRequest;
-import org.apache.kylin.rest.request.HiveTableRequest;
-import org.apache.kylin.rest.request.StreamingRequest;
-import org.apache.kylin.rest.response.TableDescResponse;
-import org.apache.kylin.rest.service.CubeService;
-import org.apache.kylin.rest.service.KafkaConfigService;
-import org.apache.kylin.rest.service.ModelService;
-import org.apache.kylin.rest.service.ProjectService;
-import org.apache.kylin.rest.service.StreamingService;
-import org.apache.kylin.source.hive.HiveClient;
-import org.apache.kylin.source.kafka.config.KafkaConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-import com.google.common.collect.Sets;
-
-/**
- * @author xduo
- */
-@Controller
-@RequestMapping(value = "/tables")
-public class TableController extends BasicController {
-    private static final Logger logger = LoggerFactory.getLogger(TableController.class);
-
-    @Autowired
-    private CubeService cubeMgmtService;
-    @Autowired
-    private ProjectService projectService;
-    @Autowired
-    private StreamingService streamingService;
-    @Autowired
-    private KafkaConfigService kafkaConfigService;
-    @Autowired
-    private ModelService modelService;
-
-    /**
-     * Get available table list of the input database
-     *
-     * @return Table metadata array
-     * @throws IOException
-     */
-    @RequestMapping(value = "", method = { RequestMethod.GET })
-    @ResponseBody
-    public List<TableDesc> getHiveTables(@RequestParam(value = "ext", required = false) boolean withExt, @RequestParam(value = "project", required = false) String project) {
-        long start = System.currentTimeMillis();
-        List<TableDesc> tables = null;
-        try {
-            tables = cubeMgmtService.getProjectManager().listDefinedTables(project);
-        } catch (Exception e) {
-            logger.error("Failed to deal with the request.", e);
-            throw new InternalErrorException(e.getLocalizedMessage());
-        }
-
-        if (withExt) {
-            tables = cloneTableDesc(tables);
-        }
-        long end = System.currentTimeMillis();
-        logger.info("Return all table metadata in " + (end - start) + " seconds");
-
-        return tables;
-    }
-
-    /**
-     * Get available table list of the input database
-     *
-     * @return Table metadata array
-     * @throws IOException
-     */
-    @RequestMapping(value = "/{tableName:.+}", method = { RequestMethod.GET })
-    @ResponseBody
-    public TableDesc getHiveTable(@PathVariable String tableName) {
-        return cubeMgmtService.getMetadataManager().getTableDesc(tableName);
-    }
-
-    /**
-     * Get available table list of the input database
-     *
-     * @return Table metadata array
-     * @throws IOException
-     */
-    @RequestMapping(value = "/{tableName}/exd-map", method = { RequestMethod.GET })
-    @ResponseBody
-    public Map<String, String> getHiveTableExd(@PathVariable String tableName) {
-        Map<String, String> tableExd = cubeMgmtService.getMetadataManager().getTableDescExd(tableName);
-        return tableExd;
-    }
-
-    @RequestMapping(value = "/reload", method = { RequestMethod.PUT })
-    @ResponseBody
-    public String reloadSourceTable() {
-        cubeMgmtService.getMetadataManager().reload();
-        return "ok";
-    }
-
-    @RequestMapping(value = "/{tables}/{project}", method = { RequestMethod.POST })
-    @ResponseBody
-    public Map<String, String[]> loadHiveTable(@PathVariable String tables, @PathVariable String project, @RequestBody HiveTableRequest request) throws IOException {
-        String submitter = SecurityContextHolder.getContext().getAuthentication().getName();
-        String[] loaded = cubeMgmtService.reloadHiveTable(tables);
-        if (request.isCalculate()) {
-            cubeMgmtService.calculateCardinalityIfNotPresent(loaded, submitter);
-        }
-        cubeMgmtService.syncTableToProject(loaded, project);
-        Map<String, String[]> result = new HashMap<String, String[]>();
-        result.put("result.loaded", loaded);
-        result.put("result.unloaded", new String[] {});
-        return result;
-    }
-
-    @RequestMapping(value = "/{tables}/{project}", method = { RequestMethod.DELETE })
-    @ResponseBody
-    public Map<String, String[]> unLoadHiveTables(@PathVariable String tables, @PathVariable String project) {
-        Set<String> unLoadSuccess = Sets.newHashSet();
-        Set<String> unLoadFail = Sets.newHashSet();
-        Map<String, String[]> result = new HashMap<String, String[]>();
-        for (String tableName : tables.split(",")) {
-            if (unLoadHiveTable(tableName, project)) {
-                unLoadSuccess.add(tableName);
-            } else {
-                unLoadFail.add(tableName);
-            }
-        }
-        result.put("result.unload.success", (String[]) unLoadSuccess.toArray(new String[unLoadSuccess.size()]));
-        result.put("result.unload.fail", (String[]) unLoadFail.toArray(new String[unLoadFail.size()]));
-        return result;
-    }
-
-    /**
-     * table may referenced by several projects, and kylin only keep one copy of meta for each table,
-     * that's why we have two if statement here.
-     * @param tableName
-     * @param project
-     * @return
-     */
-    private boolean unLoadHiveTable(String tableName, String project) {
-        boolean rtn = false;
-        int tableType = 0;
-
-        //remove streaming info
-        String[] dbTableName = HadoopUtil.parseHiveTableName(tableName);
-        tableName = dbTableName[0] + "." + dbTableName[1];
-        TableDesc desc = cubeMgmtService.getMetadataManager().getTableDesc(tableName);
-        tableType = desc.getSourceType();
-
-        try {
-            if (!modelService.isTableInModel(tableName, project)) {
-                cubeMgmtService.removeTableFromProject(tableName, project);
-                rtn = true;
-            }
-        } catch (IOException e) {
-            logger.error(e.getMessage(), e);
-        }
-        if (!projectService.isTableInAnyProject(tableName) && !modelService.isTableInAnyModel(tableName)) {
-            try {
-                cubeMgmtService.unLoadHiveTable(tableName);
-                rtn = true;
-            } catch (IOException e) {
-                logger.error(e.getMessage(), e);
-                rtn = false;
-            }
-        }
-
-        if (tableType == 1 && !projectService.isTableInAnyProject(tableName) && !modelService.isTableInAnyModel(tableName)) {
-            StreamingConfig config = null;
-            KafkaConfig kafkaConfig = null;
-            try {
-                config = streamingService.getStreamingManager().getStreamingConfig(tableName);
-                kafkaConfig = kafkaConfigService.getKafkaConfig(tableName);
-                streamingService.dropStreamingConfig(config);
-                kafkaConfigService.dropKafkaConfig(kafkaConfig);
-                rtn = true;
-            } catch (Exception e) {
-                rtn = false;
-                logger.error(e.getLocalizedMessage(), e);
-            }
-        }
-        return rtn;
-    }
-
-    @RequestMapping(value = "/addStreamingSrc", method = { RequestMethod.POST })
-    @ResponseBody
-    public Map<String, String> addStreamingTable(@RequestBody StreamingRequest request) throws IOException {
-        Map<String, String> result = new HashMap<String, String>();
-        String project = request.getProject();
-        TableDesc desc = JsonUtil.readValue(request.getTableData(), TableDesc.class);
-        desc.setUuid(UUID.randomUUID().toString());
-        MetadataManager metaMgr = MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
-        metaMgr.saveSourceTable(desc);
-        cubeMgmtService.syncTableToProject(new String[] { desc.getName() }, project);
-        result.put("success", "true");
-        return result;
-    }
-
-    /**
-     * Regenerate table cardinality
-     *
-     * @return Table metadata array
-     * @throws IOException
-     */
-    @RequestMapping(value = "/{tableNames}/cardinality", method = { RequestMethod.PUT })
-    @ResponseBody
-    public CardinalityRequest generateCardinality(@PathVariable String tableNames, @RequestBody CardinalityRequest request) {
-        String submitter = SecurityContextHolder.getContext().getAuthentication().getName();
-        String[] tables = tableNames.split(",");
-        for (String table : tables) {
-            cubeMgmtService.calculateCardinality(table.trim().toUpperCase(), submitter);
-        }
-        return request;
-    }
-
-    /**
-     * @param tables
-     * @return
-     */
-    private List<TableDesc> cloneTableDesc(List<TableDesc> tables) {
-        if (null == tables) {
-            return Collections.emptyList();
-        }
-
-        List<TableDesc> descs = new ArrayList<TableDesc>();
-        Iterator<TableDesc> it = tables.iterator();
-        while (it.hasNext()) {
-            TableDesc table = it.next();
-            Map<String, String> exd = cubeMgmtService.getMetadataManager().getTableDescExd(table.getIdentity());
-            if (exd == null) {
-                descs.add(table);
-            } else {
-                // Clone TableDesc
-                TableDescResponse rtableDesc = new TableDescResponse(table);
-                rtableDesc.setDescExd(exd);
-                if (exd.containsKey(MetadataConstants.TABLE_EXD_CARDINALITY)) {
-                    Map<String, Long> cardinality = new HashMap<String, Long>();
-                    String scard = exd.get(MetadataConstants.TABLE_EXD_CARDINALITY);
-                    if (!StringUtils.isEmpty(scard)) {
-                        String[] cards = StringUtils.split(scard, ",");
-                        ColumnDesc[] cdescs = rtableDesc.getColumns();
-                        for (int i = 0; i < cdescs.length; i++) {
-                            ColumnDesc columnDesc = cdescs[i];
-                            if (cards.length > i) {
-                                cardinality.put(columnDesc.getName(), Long.parseLong(cards[i]));
-                            } else {
-                                logger.error("The result cardinality is not identical with hive table metadata, cardinaly : " + scard + " column array length: " + cdescs.length);
-                                break;
-                            }
-                        }
-                        rtableDesc.setCardinality(cardinality);
-                    }
-                }
-                descs.add(rtableDesc);
-            }
-        }
-        return descs;
-    }
-
-    /**
-     * Show all databases in Hive
-     *
-     * @return Hive databases list
-     * @throws IOException
-     */
-    @RequestMapping(value = "/hive", method = { RequestMethod.GET })
-    @ResponseBody
-    private static List<String> showHiveDatabases() throws IOException {
-        HiveClient hiveClient = new HiveClient();
-        List<String> results = null;
-
-        try {
-            results = hiveClient.getHiveDbNames();
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw new IOException(e);
-        }
-        return results;
-    }
-
-    /**
-     * Show all tables in a Hive database
-     *
-     * @return Hive table list
-     * @throws IOException
-     */
-    @RequestMapping(value = "/hive/{database}", method = { RequestMethod.GET })
-    @ResponseBody
-    private static List<String> showHiveTables(@PathVariable String database) throws IOException {
-        HiveClient hiveClient = new HiveClient();
-        List<String> results = null;
-
-        try {
-            results = hiveClient.getHiveTableNames(database);
-        } catch (Exception e) {
-            e.printStackTrace();
-            throw new IOException(e);
-        }
-        return results;
-    }
-
-    public void setCubeService(CubeService cubeService) {
-        this.cubeMgmtService = cubeService;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/controller/UserController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/UserController.java b/server/src/main/java/org/apache/kylin/rest/controller/UserController.java
deleted file mode 100644
index bccfed4..0000000
--- a/server/src/main/java/org/apache/kylin/rest/controller/UserController.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.controller;
-
-import java.util.List;
-
-import org.apache.kylin.rest.service.UserService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-
-/**
- * Handle user authentication request to protected kylin rest resources by
- * spring security.
- * 
- * @author xduo
- * 
- */
-@Controller
-@RequestMapping(value = "/user")
-public class UserController {
-
-    private static final Logger logger = LoggerFactory.getLogger(UserController.class);
-    @Autowired
-    UserService userService;
-
-    @RequestMapping(value = "/authentication", method = RequestMethod.POST, produces = "application/json")
-    public UserDetails authenticate() {
-        return authenticatedUser();
-    }
-
-    @RequestMapping(value = "/authentication", method = RequestMethod.GET, produces = "application/json")
-    public UserDetails authenticatedUser() {
-        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
-
-        if (authentication == null) {
-            logger.debug("authentication is null.");
-            return null;
-        }
-
-        if (authentication.getPrincipal() instanceof UserDetails) {
-            logger.debug("authentication.getPrincipal() is " + authentication.getPrincipal());
-            return (UserDetails) authentication.getPrincipal();
-        }
-
-        if (authentication.getDetails() instanceof UserDetails) {
-            logger.debug("authentication.getDetails() is " + authentication.getDetails());
-            return (UserDetails) authentication.getDetails();
-        }
-
-        return null;
-    }
-
-    @RequestMapping(value = "/authentication/authorities", method = RequestMethod.GET, produces = "application/json")
-    public List<String> getAuthorities() {
-        return userService.listUserAuthorities();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/exception/BadRequestException.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/exception/BadRequestException.java b/server/src/main/java/org/apache/kylin/rest/exception/BadRequestException.java
deleted file mode 100644
index 42b671b..0000000
--- a/server/src/main/java/org/apache/kylin/rest/exception/BadRequestException.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.exception;
-
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.ResponseStatus;
-
-/**
- * @author xduo
- *
- */
-@ResponseStatus(value = HttpStatus.BAD_REQUEST)
-public class BadRequestException extends RuntimeException {
-    /**
-     * 
-     */
-    private static final long serialVersionUID = -6798154278095441848L;
-
-    public BadRequestException(String s) {
-        super(s);
-    }
-
-    /**
-     * 
-     */
-    public BadRequestException() {
-        super();
-    }
-
-    /**
-     * @param arg0
-     * @param arg1
-     */
-    public BadRequestException(String arg0, Throwable arg1) {
-        super(arg0, arg1);
-    }
-
-    /**
-     * @param arg0
-     */
-    public BadRequestException(Throwable arg0) {
-        super(arg0);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/exception/ForbiddenException.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/exception/ForbiddenException.java b/server/src/main/java/org/apache/kylin/rest/exception/ForbiddenException.java
deleted file mode 100644
index 6a2ed7c..0000000
--- a/server/src/main/java/org/apache/kylin/rest/exception/ForbiddenException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.exception;
-
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.ResponseStatus;
-
-/**
- * @author xduo
- * 
- */
-@ResponseStatus(value = HttpStatus.FORBIDDEN)
-public class ForbiddenException extends RuntimeException {
-
-    private static final long serialVersionUID = 2741885728370162194L;
-
-    public ForbiddenException() {
-        super();
-    }
-
-    public ForbiddenException(String message) {
-        super(message);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/exception/InternalErrorException.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/exception/InternalErrorException.java b/server/src/main/java/org/apache/kylin/rest/exception/InternalErrorException.java
deleted file mode 100644
index 6d7586f..0000000
--- a/server/src/main/java/org/apache/kylin/rest/exception/InternalErrorException.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.exception;
-
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.ResponseStatus;
-
-/**
- * Class to wrap backend exception
- * 
- * @author jianliu
- * 
- */
-@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
-public class InternalErrorException extends RuntimeException {
-    /**
-     * 
-     */
-    private static final long serialVersionUID = -6798154278095441848L;
-
-    public InternalErrorException(String s) {
-        super(s);
-    }
-
-    /**
-     * 
-     */
-    public InternalErrorException() {
-        super();
-    }
-
-    /**
-     * @param arg0
-     * @param arg1
-     */
-    public InternalErrorException(String arg0, Throwable arg1) {
-        super(arg0, arg1);
-    }
-
-    /**
-     * @param arg0
-     */
-    public InternalErrorException(Throwable arg0) {
-        super(arg0);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/exception/NotFoundException.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/exception/NotFoundException.java b/server/src/main/java/org/apache/kylin/rest/exception/NotFoundException.java
deleted file mode 100644
index 0ed898c..0000000
--- a/server/src/main/java/org/apache/kylin/rest/exception/NotFoundException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.exception;
-
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.ResponseStatus;
-
-/**
- * @author xduo
- *
- */
-@ResponseStatus(value = HttpStatus.NOT_FOUND)
-public class NotFoundException extends RuntimeException {
-    private static final long serialVersionUID = 1L;
-
-    public NotFoundException(String s) {
-        super(s);
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/init/ClientInfoTask.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/init/ClientInfoTask.java b/server/src/main/java/org/apache/kylin/rest/init/ClientInfoTask.java
deleted file mode 100644
index 301a9df..0000000
--- a/server/src/main/java/org/apache/kylin/rest/init/ClientInfoTask.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.init;
-
-import java.io.File;
-
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.common.KylinVersion;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ClientInfoTask extends InitialTask {
-
-    private static final Logger logger = LoggerFactory.getLogger(ClientInfoTask.class);
-
-    @Override
-    public void execute() {
-        logger.info(getClientDetailInformation());
-    }
-
-    public static String getClientDetailInformation() {
-        StringBuilder buf = new StringBuilder();
-
-        buf.append("kylin.home: ").append(new File(KylinConfig.getKylinHome()).getAbsolutePath()).append("\n");
-        buf.append("kylin.version:").append(KylinVersion.getCurrentVersion()).append("\n");
-        buf.append("commit:").append(KylinVersion.getGitCommitInfo()).append("\n");
-        buf.append("os.name:").append(System.getProperty("os.name")).append("\n");
-        buf.append("os.arch:").append(System.getProperty("os.arch")).append("\n");
-        buf.append("os.version:").append(System.getProperty("os.version")).append("\n");
-        buf.append("java.version:").append(System.getProperty("java.version")).append("\n");
-        buf.append("java.vendor:").append(System.getProperty("java.vendor"));
-
-        return buf.toString();
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/init/InitialTask.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/init/InitialTask.java b/server/src/main/java/org/apache/kylin/rest/init/InitialTask.java
deleted file mode 100644
index 24691b1..0000000
--- a/server/src/main/java/org/apache/kylin/rest/init/InitialTask.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.init;
-
-/**
- * Created by dongli on 3/16/16.
- */
-public abstract class InitialTask {
-    public abstract void execute();
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/init/InitialTaskManager.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/init/InitialTaskManager.java b/server/src/main/java/org/apache/kylin/rest/init/InitialTaskManager.java
deleted file mode 100644
index 8912968..0000000
--- a/server/src/main/java/org/apache/kylin/rest/init/InitialTaskManager.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.init;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.kylin.common.KylinConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.InitializingBean;
-
-/**
- * Created by dongli on 3/16/16.
- */
-public class InitialTaskManager implements InitializingBean {
-
-    private static final Logger logger = LoggerFactory.getLogger(InitialTaskManager.class);
-
-    @Override
-    public void afterPropertiesSet() throws Exception {
-        logger.info("Kylin service is starting.....");
-
-        runInitialTasks();
-    }
-
-    private void runInitialTasks() {
-        KylinConfig kylinConfig = KylinConfig.getInstanceFromEnv();
-        String initTasks = kylinConfig.getInitTasks();
-        if (!StringUtils.isEmpty(initTasks)) {
-            String[] taskClasses = initTasks.split(",");
-            for (String taskClass : taskClasses) {
-                try {
-                    InitialTask task = (InitialTask) Class.forName(taskClass).newInstance();
-                    logger.info("Running task: " + taskClass);
-                    task.execute();
-                } catch (Exception e) {
-                    logger.error("Initial task failed: " + taskClass, e);
-                }
-            }
-            logger.info("All initial tasks finished.");
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/model/ColumnMeta.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/model/ColumnMeta.java b/server/src/main/java/org/apache/kylin/rest/model/ColumnMeta.java
deleted file mode 100644
index 7ffea38..0000000
--- a/server/src/main/java/org/apache/kylin/rest/model/ColumnMeta.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.model;
-
-import java.io.Serializable;
-
-/**
- */
-public class ColumnMeta implements Serializable {
-    private static final long serialVersionUID = 1L;
-    private String TABLE_CAT;
-    private String TABLE_SCHEM;
-    private String TABLE_NAME;
-    private String COLUMN_NAME;
-    private int DATA_TYPE;
-    private String TYPE_NAME;
-    private int COLUMN_SIZE;
-    private int BUFFER_LENGTH;
-    private int DECIMAL_DIGITS;
-    private int NUM_PREC_RADIX;
-    private int NULLABLE;
-    private String REMARKS;
-    private String COLUMN_DEF;
-    private int SQL_DATA_TYPE;
-    private int SQL_DATETIME_SUB;
-    private int CHAR_OCTET_LENGTH;
-    private int ORDINAL_POSITION;
-    private String IS_NULLABLE;
-    private String SCOPE_CATLOG;
-    private String SCOPE_SCHEMA;
-    private String SCOPE_TABLE;
-    private short SOURCE_DATA_TYPE;
-    private String IS_AUTOINCREMENT;
-
-    public ColumnMeta() {
-    }
-
-    public ColumnMeta(String tABLE_CAT, String tABLE_SCHEM, String tABLE_NAME, String cOLUMN_NAME, int dATA_TYPE, String tYPE_NAME, int cOLUMN_SIZE, int bUFFER_LENGTH, int dECIMAL_DIGITS, int nUM_PREC_RADIX, int nULLABLE, String rEMARKS, String cOLUMN_DEF, int sQL_DATA_TYPE, int sQL_DATETIME_SUB, int cHAR_OCTET_LENGTH, int oRDINAL_POSITION, String iS_NULLABLE, String sCOPE_CATLOG, String sCOPE_SCHEMA, String sCOPE_TABLE, short sOURCE_DATA_TYPE, String iS_AUTOINCREMENT) {
-        super();
-        TABLE_CAT = tABLE_CAT;
-        TABLE_SCHEM = tABLE_SCHEM;
-        TABLE_NAME = tABLE_NAME;
-        COLUMN_NAME = cOLUMN_NAME;
-        DATA_TYPE = dATA_TYPE;
-        TYPE_NAME = tYPE_NAME;
-        COLUMN_SIZE = cOLUMN_SIZE;
-        BUFFER_LENGTH = bUFFER_LENGTH;
-        DECIMAL_DIGITS = dECIMAL_DIGITS;
-        NUM_PREC_RADIX = nUM_PREC_RADIX;
-        NULLABLE = nULLABLE;
-        REMARKS = rEMARKS;
-        COLUMN_DEF = cOLUMN_DEF;
-        SQL_DATA_TYPE = sQL_DATA_TYPE;
-        SQL_DATETIME_SUB = sQL_DATETIME_SUB;
-        CHAR_OCTET_LENGTH = cHAR_OCTET_LENGTH;
-        ORDINAL_POSITION = oRDINAL_POSITION;
-        IS_NULLABLE = iS_NULLABLE;
-        SCOPE_CATLOG = sCOPE_CATLOG;
-        SCOPE_SCHEMA = sCOPE_SCHEMA;
-        SCOPE_TABLE = sCOPE_TABLE;
-        SOURCE_DATA_TYPE = sOURCE_DATA_TYPE;
-        IS_AUTOINCREMENT = iS_AUTOINCREMENT;
-    }
-
-    public String getTABLE_CAT() {
-        return TABLE_CAT;
-    }
-
-    public void setTABLE_CAT(String tABLE_CAT) {
-        TABLE_CAT = tABLE_CAT;
-    }
-
-    public String getTABLE_SCHEM() {
-        return TABLE_SCHEM;
-    }
-
-    public void setTABLE_SCHEM(String tABLE_SCHEM) {
-        TABLE_SCHEM = tABLE_SCHEM;
-    }
-
-    public String getTABLE_NAME() {
-        return TABLE_NAME;
-    }
-
-    public void setTABLE_NAME(String tABLE_NAME) {
-        TABLE_NAME = tABLE_NAME;
-    }
-
-    public String getCOLUMN_NAME() {
-        return COLUMN_NAME;
-    }
-
-    public void setCOLUMN_NAME(String cOLUMN_NAME) {
-        COLUMN_NAME = cOLUMN_NAME;
-    }
-
-    public int getDATA_TYPE() {
-        return DATA_TYPE;
-    }
-
-    public void setDATA_TYPE(int dATA_TYPE) {
-        DATA_TYPE = dATA_TYPE;
-    }
-
-    public String getTYPE_NAME() {
-        return TYPE_NAME;
-    }
-
-    public void setTYPE_NAME(String tYPE_NAME) {
-        TYPE_NAME = tYPE_NAME;
-    }
-
-    public int getCOLUMN_SIZE() {
-        return COLUMN_SIZE;
-    }
-
-    public void setCOLUMN_SIZE(int cOLUMN_SIZE) {
-        COLUMN_SIZE = cOLUMN_SIZE;
-    }
-
-    public int getBUFFER_LENGTH() {
-        return BUFFER_LENGTH;
-    }
-
-    public void setBUFFER_LENGTH(int bUFFER_LENGTH) {
-        BUFFER_LENGTH = bUFFER_LENGTH;
-    }
-
-    public int getDECIMAL_DIGITS() {
-        return DECIMAL_DIGITS;
-    }
-
-    public void setDECIMAL_DIGITS(int dECIMAL_DIGITS) {
-        DECIMAL_DIGITS = dECIMAL_DIGITS;
-    }
-
-    public int getNUM_PREC_RADIX() {
-        return NUM_PREC_RADIX;
-    }
-
-    public void setNUM_PREC_RADIX(int nUM_PREC_RADIX) {
-        NUM_PREC_RADIX = nUM_PREC_RADIX;
-    }
-
-    public int getNULLABLE() {
-        return NULLABLE;
-    }
-
-    public void setNULLABLE(int nULLABLE) {
-        NULLABLE = nULLABLE;
-    }
-
-    public String getREMARKS() {
-        return REMARKS;
-    }
-
-    public void setREMARKS(String rEMARKS) {
-        REMARKS = rEMARKS;
-    }
-
-    public String getCOLUMN_DEF() {
-        return COLUMN_DEF;
-    }
-
-    public void setCOLUMN_DEF(String cOLUMN_DEF) {
-        COLUMN_DEF = cOLUMN_DEF;
-    }
-
-    public int getSQL_DATA_TYPE() {
-        return SQL_DATA_TYPE;
-    }
-
-    public void setSQL_DATA_TYPE(int sQL_DATA_TYPE) {
-        SQL_DATA_TYPE = sQL_DATA_TYPE;
-    }
-
-    public int getSQL_DATETIME_SUB() {
-        return SQL_DATETIME_SUB;
-    }
-
-    public void setSQL_DATETIME_SUB(int sQL_DATETIME_SUB) {
-        SQL_DATETIME_SUB = sQL_DATETIME_SUB;
-    }
-
-    public int getCHAR_OCTET_LENGTH() {
-        return CHAR_OCTET_LENGTH;
-    }
-
-    public void setCHAR_OCTET_LENGTH(int cHAR_OCTET_LENGTH) {
-        CHAR_OCTET_LENGTH = cHAR_OCTET_LENGTH;
-    }
-
-    public int getORDINAL_POSITION() {
-        return ORDINAL_POSITION;
-    }
-
-    public void setORDINAL_POSITION(int oRDINAL_POSITION) {
-        ORDINAL_POSITION = oRDINAL_POSITION;
-    }
-
-    public String getIS_NULLABLE() {
-        return IS_NULLABLE;
-    }
-
-    public void setIS_NULLABLE(String iS_NULLABLE) {
-        IS_NULLABLE = iS_NULLABLE;
-    }
-
-    public String getSCOPE_CATLOG() {
-        return SCOPE_CATLOG;
-    }
-
-    public void setSCOPE_CATLOG(String sCOPE_CATLOG) {
-        SCOPE_CATLOG = sCOPE_CATLOG;
-    }
-
-    public String getSCOPE_SCHEMA() {
-        return SCOPE_SCHEMA;
-    }
-
-    public void setSCOPE_SCHEMA(String sCOPE_SCHEMA) {
-        SCOPE_SCHEMA = sCOPE_SCHEMA;
-    }
-
-    public String getSCOPE_TABLE() {
-        return SCOPE_TABLE;
-    }
-
-    public void setSCOPE_TABLE(String sCOPE_TABLE) {
-        SCOPE_TABLE = sCOPE_TABLE;
-    }
-
-    public short getSOURCE_DATA_TYPE() {
-        return SOURCE_DATA_TYPE;
-    }
-
-    public void setSOURCE_DATA_TYPE(short sOURCE_DATA_TYPE) {
-        SOURCE_DATA_TYPE = sOURCE_DATA_TYPE;
-    }
-
-    public String getIS_AUTOINCREMENT() {
-        return IS_AUTOINCREMENT;
-    }
-
-    public void setIS_AUTOINCREMENT(String iS_AUTOINCREMENT) {
-        this.IS_AUTOINCREMENT = iS_AUTOINCREMENT;
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/model/Query.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/model/Query.java b/server/src/main/java/org/apache/kylin/rest/model/Query.java
deleted file mode 100644
index 6b2ef5e..0000000
--- a/server/src/main/java/org/apache/kylin/rest/model/Query.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.model;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-
-@JsonIgnoreProperties(ignoreUnknown = true)
-public class Query {
-
-    private String name;
-    private String project;
-    private String sql;
-    private String description;
-
-    public Query() {
-    }
-
-    public Query(String name, String project, String sql, String description) {
-        super();
-        this.name = name;
-        this.project = project;
-        this.sql = sql;
-        this.description = description;
-    }
-
-    public String getId() {
-        return String.valueOf(this.hashCode());
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getProject() {
-        return project;
-    }
-
-    public void setProject(String project) {
-        this.project = project;
-    }
-
-    public String getSql() {
-        return sql;
-    }
-
-    public void setSql(String sql) {
-        this.sql = sql;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((description == null) ? 0 : description.hashCode());
-        result = prime * result + ((name == null) ? 0 : name.hashCode());
-        result = prime * result + ((project == null) ? 0 : project.hashCode());
-        result = prime * result + ((sql == null) ? 0 : sql.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        Query other = (Query) obj;
-        if (description == null) {
-            if (other.description != null)
-                return false;
-        } else if (!description.equals(other.description))
-            return false;
-        if (name == null) {
-            if (other.name != null)
-                return false;
-        } else if (!name.equals(other.name))
-            return false;
-        if (project == null) {
-            if (other.project != null)
-                return false;
-        } else if (!project.equals(other.project))
-            return false;
-        if (sql == null) {
-            if (other.sql != null)
-                return false;
-        } else if (!sql.equals(other.sql))
-            return false;
-        return true;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/model/SelectedColumnMeta.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/model/SelectedColumnMeta.java b/server/src/main/java/org/apache/kylin/rest/model/SelectedColumnMeta.java
deleted file mode 100644
index 95582e4..0000000
--- a/server/src/main/java/org/apache/kylin/rest/model/SelectedColumnMeta.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.model;
-
-import java.io.Serializable;
-
-/**
- */
-public class SelectedColumnMeta implements Serializable {
-    public SelectedColumnMeta(boolean isAutoIncrement, boolean isCaseSensitive, boolean isSearchable, boolean isCurrency, int isNullalbe, boolean isSigned, int displaySize, String label, String name, String schemaName, String catelogName, String tableName, int precision, int scale, int columnType, String columnTypeName, boolean isReadOnly, boolean isWritable, boolean isDefinitelyWritable) {
-        super();
-        this.isAutoIncrement = isAutoIncrement;
-        this.isCaseSensitive = isCaseSensitive;
-        this.isSearchable = isSearchable;
-        this.isCurrency = isCurrency;
-        this.isNullable = isNullalbe;
-        this.isSigned = isSigned;
-        this.displaySize = displaySize;
-        this.label = label;
-        this.name = name;
-        this.schemaName = schemaName;
-        this.catelogName = catelogName;
-        this.tableName = tableName;
-        this.precision = precision;
-        this.scale = scale;
-        this.columnType = columnType;
-        this.columnTypeName = columnTypeName;
-        this.isReadOnly = isReadOnly;
-        this.isWritable = isWritable;
-        this.isDefinitelyWritable = isDefinitelyWritable;
-    }
-
-    public boolean isAutoIncrement() {
-        return isAutoIncrement;
-    }
-
-    public boolean isCaseSensitive() {
-        return isCaseSensitive;
-    }
-
-    public boolean isSearchable() {
-        return isSearchable;
-    }
-
-    public boolean isCurrency() {
-        return isCurrency;
-    }
-
-    public int getIsNullable() {
-        return isNullable;
-    }
-
-    public boolean isSigned() {
-        return isSigned;
-    }
-
-    public int getDisplaySize() {
-        return displaySize;
-    }
-
-    public String getLabel() {
-        return label;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public String getSchemaName() {
-        return schemaName;
-    }
-
-    public String getCatelogName() {
-        return catelogName;
-    }
-
-    public String getTableName() {
-        return tableName;
-    }
-
-    public int getPrecision() {
-        return precision;
-    }
-
-    public int getScale() {
-        return scale;
-    }
-
-    public int getColumnType() {
-        return columnType;
-    }
-
-    public String getColumnTypeName() {
-        return columnTypeName;
-    }
-
-    public boolean isReadOnly() {
-        return isReadOnly;
-    }
-
-    public boolean isWritable() {
-        return isWritable;
-    }
-
-    public boolean isDefinitelyWritable() {
-        return isDefinitelyWritable;
-    }
-
-    private final boolean isAutoIncrement;
-    private final boolean isCaseSensitive;
-    private final boolean isSearchable;
-    private final boolean isCurrency;
-    private final int isNullable;// 0:nonull, 1:nullable, 2: nullableunknown
-    private final boolean isSigned;
-    private final int displaySize;
-    private final String label;// AS keyword
-    private final String name;
-    private final String schemaName;
-    private final String catelogName;
-    private final String tableName;
-    private final int precision;
-    private final int scale;
-    private final int columnType;// as defined in java.sql.Types
-    private final String columnTypeName;
-    private final boolean isReadOnly;
-    private final boolean isWritable;
-    private final boolean isDefinitelyWritable;
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/model/TableMeta.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/model/TableMeta.java b/server/src/main/java/org/apache/kylin/rest/model/TableMeta.java
deleted file mode 100644
index 485e745..0000000
--- a/server/src/main/java/org/apache/kylin/rest/model/TableMeta.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.model;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- */
-public class TableMeta implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-    private String TABLE_CAT;
-    private String TABLE_SCHEM;
-    private String TABLE_NAME;
-    private String TABLE_TYPE;
-    private String REMARKS;
-    private String TYPE_CAT;
-    private String TYPE_SCHEM;
-    private String TYPE_NAME;
-    private String SELF_REFERENCING_COL_NAME;
-    private String REF_GENERATION;
-    private List<ColumnMeta> columns = new ArrayList<ColumnMeta>();
-
-    public TableMeta() {
-    }
-
-    public TableMeta(String tABLE_CAT, String tABLE_SCHEM, String tABLE_NAME, String tABLE_TYPE, String rEMARKS, String tYPE_CAT, String tYPE_SCHEM, String tYPE_NAME, String sELF_REFERENCING_COL_NAME, String rEF_GENERATION) {
-        super();
-        TABLE_CAT = tABLE_CAT;
-        TABLE_SCHEM = tABLE_SCHEM;
-        TABLE_NAME = tABLE_NAME;
-        TABLE_TYPE = tABLE_TYPE;
-        REMARKS = rEMARKS;
-        TYPE_CAT = tYPE_CAT;
-        TYPE_SCHEM = tYPE_SCHEM;
-        TYPE_NAME = tYPE_NAME;
-        SELF_REFERENCING_COL_NAME = sELF_REFERENCING_COL_NAME;
-        REF_GENERATION = rEF_GENERATION;
-    }
-
-    public String getTABLE_CAT() {
-        return TABLE_CAT;
-    }
-
-    public void setTABLE_CAT(String tABLE_CAT) {
-        TABLE_CAT = tABLE_CAT;
-    }
-
-    public String getTABLE_SCHEM() {
-        return TABLE_SCHEM;
-    }
-
-    public void setTABLE_SCHEM(String tABLE_SCHEM) {
-        TABLE_SCHEM = tABLE_SCHEM;
-    }
-
-    public String getTABLE_NAME() {
-        return TABLE_NAME;
-    }
-
-    public void setTABLE_NAME(String tABLE_NAME) {
-        TABLE_NAME = tABLE_NAME;
-    }
-
-    public String getTABLE_TYPE() {
-        return TABLE_TYPE;
-    }
-
-    public void setTABLE_TYPE(String tABLE_TYPE) {
-        TABLE_TYPE = tABLE_TYPE;
-    }
-
-    public String getREMARKS() {
-        return REMARKS;
-    }
-
-    public void setREMARKS(String rEMARKS) {
-        REMARKS = rEMARKS;
-    }
-
-    public String getTYPE_CAT() {
-        return TYPE_CAT;
-    }
-
-    public void setTYPE_CAT(String tYPE_CAT) {
-        TYPE_CAT = tYPE_CAT;
-    }
-
-    public String getTYPE_SCHEM() {
-        return TYPE_SCHEM;
-    }
-
-    public void setTYPE_SCHEM(String tYPE_SCHEM) {
-        TYPE_SCHEM = tYPE_SCHEM;
-    }
-
-    public String getTYPE_NAME() {
-        return TYPE_NAME;
-    }
-
-    public void setTYPE_NAME(String tYPE_NAME) {
-        TYPE_NAME = tYPE_NAME;
-    }
-
-    public String getSELF_REFERENCING_COL_NAME() {
-        return SELF_REFERENCING_COL_NAME;
-    }
-
-    public void setSELF_REFERENCING_COL_NAME(String sELF_REFERENCING_COL_NAME) {
-        SELF_REFERENCING_COL_NAME = sELF_REFERENCING_COL_NAME;
-    }
-
-    public String getREF_GENERATION() {
-        return REF_GENERATION;
-    }
-
-    public void setREF_GENERATION(String rEF_GENERATION) {
-        REF_GENERATION = rEF_GENERATION;
-    }
-
-    public List<ColumnMeta> getColumns() {
-        return columns;
-    }
-
-    public void setColumns(List<ColumnMeta> columns) {
-        this.columns = columns;
-    }
-
-    public void addColumn(ColumnMeta column) {
-        this.columns.add(column);
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/AccessRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/AccessRequest.java b/server/src/main/java/org/apache/kylin/rest/request/AccessRequest.java
deleted file mode 100644
index 0ff57b2..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/AccessRequest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.request;
-
-/**
- * @author xduo
- * 
- */
-public class AccessRequest {
-
-    private Long accessEntryId;
-    private String permission;
-    private String sid;
-    private boolean principal;
-
-    public AccessRequest() {
-    }
-
-    public Long getAccessEntryId() {
-        return accessEntryId;
-    }
-
-    public void setAccessEntryId(Long accessEntryId) {
-        this.accessEntryId = accessEntryId;
-    }
-
-    public String getPermission() {
-        return permission;
-    }
-
-    public void setPermission(String permission) {
-        this.permission = permission;
-    }
-
-    public String getSid() {
-        return sid;
-    }
-
-    public void setSid(String sid) {
-        this.sid = sid;
-    }
-
-    public boolean isPrincipal() {
-        return principal;
-    }
-
-    public void setPrincipal(boolean principal) {
-        this.principal = principal;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/CardinalityRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/CardinalityRequest.java b/server/src/main/java/org/apache/kylin/rest/request/CardinalityRequest.java
deleted file mode 100644
index 9eadcb7..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/CardinalityRequest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.request;
-
-/**
- * @author jianliu
- * 
- */
-public class CardinalityRequest {
-    private int delimiter;
-
-    private int format;
-
-    /**
-     * @return the delimiter
-     */
-    public String getDelimiter() {
-        switch (delimiter) {
-        case 0:
-            return null;
-        case 1:
-            return "177";
-        case 2:
-            return "t";
-        default:
-            return null;
-        }
-    }
-
-    /**
-     * @param delimiter
-     *            the delimiter to set
-     */
-    public void setDelimiter(int delimiter) {
-        this.delimiter = delimiter;
-    }
-
-    /**
-     * @return the format
-     */
-    public String getFormat() {
-        switch (format) {
-        case 0:
-            return null;
-        case 1:
-            return "text";
-        case 2:
-            return "sequence";
-        default:
-            return null;
-        }
-    }
-
-    /**
-     * @param format
-     *            the format to set
-     */
-    public void setFormat(int format) {
-        this.format = format;
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java b/server/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java
deleted file mode 100644
index 71cd1c4..0000000
--- a/server/src/main/java/org/apache/kylin/rest/request/CreateProjectRequest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.request;
-
-/**
- */
-public class CreateProjectRequest {
-    private String name;
-    private String description;
-
-    public CreateProjectRequest() {
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getDescription() {
-        return description;
-    }
-
-    public void setDescription(String description) {
-        this.description = description;
-    }
-
-}


[02/13] kylin git commit: KYLIN-1823 split code from kylin-server into kylin-server-base

Posted by li...@apache.org.
http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/service/BasicService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/BasicService.java b/server/src/main/java/org/apache/kylin/rest/service/BasicService.java
deleted file mode 100644
index 7197f03..0000000
--- a/server/src/main/java/org/apache/kylin/rest/service/BasicService.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.service;
-
-import java.io.IOException;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.cube.CubeDescManager;
-import org.apache.kylin.cube.CubeManager;
-import org.apache.kylin.engine.mr.CubingJob;
-import org.apache.kylin.engine.mr.steps.CubingExecutableUtil;
-import org.apache.kylin.engine.streaming.StreamingManager;
-import org.apache.kylin.invertedindex.IIDescManager;
-import org.apache.kylin.invertedindex.IIManager;
-import org.apache.kylin.job.execution.AbstractExecutable;
-import org.apache.kylin.job.execution.ExecutableState;
-import org.apache.kylin.job.execution.Output;
-import org.apache.kylin.job.manager.ExecutableManager;
-import org.apache.kylin.metadata.MetadataManager;
-import org.apache.kylin.metadata.badquery.BadQueryHistoryManager;
-import org.apache.kylin.metadata.project.ProjectInstance;
-import org.apache.kylin.metadata.project.ProjectManager;
-import org.apache.kylin.metadata.realization.RealizationType;
-import org.apache.kylin.source.kafka.KafkaConfigManager;
-import org.apache.kylin.storage.hybrid.HybridManager;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.Lists;
-
-public abstract class BasicService {
-
-    public KylinConfig getConfig() {
-        KylinConfig kylinConfig = KylinConfig.getInstanceFromEnv();
-
-        if (kylinConfig == null) {
-            throw new IllegalArgumentException("Failed to load kylin config instance");
-        }
-
-        return kylinConfig;
-    }
-
-    public MetadataManager getMetadataManager() {
-        return MetadataManager.getInstance(getConfig());
-    }
-
-    public CubeManager getCubeManager() {
-        return CubeManager.getInstance(getConfig());
-    }
-
-    public StreamingManager getStreamingManager() {
-        return StreamingManager.getInstance(getConfig());
-    }
-
-    public KafkaConfigManager getKafkaManager() throws IOException {
-        return KafkaConfigManager.getInstance(getConfig());
-    }
-
-    public CubeDescManager getCubeDescManager() {
-        return CubeDescManager.getInstance(getConfig());
-    }
-
-    public ProjectManager getProjectManager() {
-        return ProjectManager.getInstance(getConfig());
-    }
-
-    public HybridManager getHybridManager() {
-        return HybridManager.getInstance(getConfig());
-    }
-
-    public ExecutableManager getExecutableManager() {
-        return ExecutableManager.getInstance(getConfig());
-    }
-
-    public IIDescManager getIIDescManager() {
-        return IIDescManager.getInstance(getConfig());
-    }
-
-    public IIManager getIIManager() {
-        return IIManager.getInstance(getConfig());
-    }
-
-    public BadQueryHistoryManager getBadQueryHistoryManager() {
-        return BadQueryHistoryManager.getInstance(getConfig());
-    }
-
-    protected List<CubingJob> listAllCubingJobs(final String cubeName, final String projectName, final Set<ExecutableState> statusList, final Map<String, Output> allOutputs) {
-        return listAllCubingJobs(cubeName, projectName, statusList, -1L, -1L, allOutputs);
-    }
-
-    protected List<CubingJob> listAllCubingJobs(final String cubeName, final String projectName, final Set<ExecutableState> statusList, long timeStartInMillis, long timeEndInMillis, final Map<String, Output> allOutputs) {
-        List<CubingJob> results = Lists.newArrayList(FluentIterable.from(getExecutableManager().getAllExecutables(timeStartInMillis, timeEndInMillis)).filter(new Predicate<AbstractExecutable>() {
-            @Override
-            public boolean apply(AbstractExecutable executable) {
-                if (executable instanceof CubingJob) {
-                    if (cubeName == null) {
-                        return true;
-                    }
-                    return CubingExecutableUtil.getCubeName(executable.getParams()).equalsIgnoreCase(cubeName);
-                } else {
-                    return false;
-                }
-            }
-        }).transform(new Function<AbstractExecutable, CubingJob>() {
-            @Override
-            public CubingJob apply(AbstractExecutable executable) {
-                return (CubingJob) executable;
-            }
-        }).filter(Predicates.and(new Predicate<CubingJob>() {
-            @Override
-            public boolean apply(CubingJob executable) {
-                if (null == projectName || null == getProjectManager().getProject(projectName)) {
-                    return true;
-                } else {
-                    ProjectInstance project = getProjectManager().getProject(projectName);
-                    return project.containsRealization(RealizationType.CUBE, CubingExecutableUtil.getCubeName(executable.getParams()));
-                }
-            }
-        }, new Predicate<CubingJob>() {
-            @Override
-            public boolean apply(CubingJob executable) {
-                return statusList.contains(allOutputs.get(executable.getId()).getState());
-            }
-        })));
-        return results;
-    }
-
-    protected List<CubingJob> listAllCubingJobs(final String cubeName, final String projectName, final Set<ExecutableState> statusList) {
-        return listAllCubingJobs(cubeName, projectName, statusList, getExecutableManager().getAllOutputs());
-    }
-
-    protected List<CubingJob> listAllCubingJobs(final String cubeName, final String projectName) {
-        return listAllCubingJobs(cubeName, projectName, EnumSet.allOf(ExecutableState.class), getExecutableManager().getAllOutputs());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/service/CacheService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/CacheService.java b/server/src/main/java/org/apache/kylin/rest/service/CacheService.java
deleted file mode 100644
index 9185544..0000000
--- a/server/src/main/java/org/apache/kylin/rest/service/CacheService.java
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.service;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-import java.util.Properties;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import javax.annotation.PostConstruct;
-import javax.sql.DataSource;
-
-import org.apache.calcite.jdbc.Driver;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.common.restclient.Broadcaster;
-import org.apache.kylin.cube.CubeDescManager;
-import org.apache.kylin.cube.CubeInstance;
-import org.apache.kylin.cube.CubeManager;
-import org.apache.kylin.dict.DictionaryManager;
-import org.apache.kylin.engine.streaming.StreamingManager;
-import org.apache.kylin.invertedindex.IIDescManager;
-import org.apache.kylin.invertedindex.IIManager;
-import org.apache.kylin.metadata.MetadataManager;
-import org.apache.kylin.metadata.project.ProjectInstance;
-import org.apache.kylin.metadata.project.ProjectManager;
-import org.apache.kylin.metadata.realization.RealizationRegistry;
-import org.apache.kylin.metadata.realization.RealizationType;
-import org.apache.kylin.query.enumerator.OLAPQuery;
-import org.apache.kylin.query.schema.OLAPSchemaFactory;
-import org.apache.kylin.rest.controller.QueryController;
-import org.apache.kylin.source.kafka.KafkaConfigManager;
-import org.apache.kylin.storage.hbase.HBaseConnection;
-import org.apache.kylin.storage.hybrid.HybridManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.datasource.DriverManagerDataSource;
-import org.springframework.stereotype.Component;
-
-import net.sf.ehcache.CacheManager;
-
-/**
- */
-@Component("cacheService")
-public class CacheService extends BasicService {
-
-    private static final Logger logger = LoggerFactory.getLogger(CacheService.class);
-
-    private static ConcurrentMap<String, DataSource> olapDataSources = new ConcurrentHashMap<String, DataSource>();
-
-    @Autowired
-    private CubeService cubeService;
-
-    @Autowired
-    private CacheManager cacheManager;
-
-    @PostConstruct
-    public void initCubeChangeListener() throws IOException {
-        CubeManager cubeMgr = CubeManager.getInstance(getConfig());
-        cubeMgr.setCubeChangeListener(new CubeManager.CubeChangeListener() {
-
-            @Override
-            public void afterCubeCreate(CubeInstance cube) {
-                // no cache need change
-            }
-
-            @Override
-            public void afterCubeUpdate(CubeInstance cube) {
-                rebuildCubeCache(cube.getName());
-            }
-
-            @Override
-            public void afterCubeDelete(CubeInstance cube) {
-                removeCubeCache(cube.getName(), cube);
-            }
-        });
-    }
-
-    // for test
-    public void setCubeService(CubeService cubeService) {
-        this.cubeService = cubeService;
-    }
-
-    protected void cleanDataCache(String storageUUID) {
-        if (cacheManager != null) {
-            logger.info("cleaning cache for " + storageUUID + " (currently remove all entries)");
-            cacheManager.getCache(QueryController.SUCCESS_QUERY_CACHE).removeAll();
-            cacheManager.getCache(QueryController.EXCEPTION_QUERY_CACHE).removeAll();
-        } else {
-            logger.warn("skip cleaning cache for " + storageUUID);
-        }
-    }
-
-    protected void cleanAllDataCache() {
-        if (cacheManager != null) {
-            logger.warn("cleaning all storage cache");
-            cacheManager.clearAll();
-        } else {
-            logger.warn("skip cleaning all storage cache");
-        }
-    }
-
-    private static void removeOLAPDataSource(String project) {
-        logger.info("removeOLAPDataSource is called for project " + project);
-        if (StringUtils.isEmpty(project))
-            throw new IllegalArgumentException("removeOLAPDataSource: project name not given");
-
-        project = ProjectInstance.getNormalizedProjectName(project);
-        olapDataSources.remove(project);
-    }
-
-    public static void removeAllOLAPDataSources() {
-        // brutal, yet simplest way
-        logger.info("removeAllOLAPDataSources is called.");
-        olapDataSources.clear();
-    }
-
-    public DataSource getOLAPDataSource(String project) {
-
-        project = ProjectInstance.getNormalizedProjectName(project);
-
-        DataSource ret = olapDataSources.get(project);
-        if (ret == null) {
-            logger.debug("Creating a new data source, OLAP data source pointing to " + getConfig());
-            File modelJson = OLAPSchemaFactory.createTempOLAPJson(project, getConfig());
-
-            try {
-                String text = FileUtils.readFileToString(modelJson);
-                logger.debug("The new temp olap json is :" + text);
-            } catch (IOException e) {
-                e.printStackTrace(); // logging failure is not critical
-            }
-
-            DriverManagerDataSource ds = new DriverManagerDataSource();
-            Properties props = new Properties();
-            props.setProperty(OLAPQuery.PROP_SCAN_THRESHOLD, String.valueOf(KylinConfig.getInstanceFromEnv().getScanThreshold()));
-            ds.setConnectionProperties(props);
-            ds.setDriverClassName(Driver.class.getName());
-            ds.setUrl("jdbc:calcite:model=" + modelJson.getAbsolutePath());
-
-            ret = olapDataSources.putIfAbsent(project, ds);
-            if (ret == null) {
-                ret = ds;
-            }
-        }
-        return ret;
-    }
-
-    public void rebuildCache(Broadcaster.TYPE cacheType, String cacheKey) {
-        final String log = "rebuild cache type: " + cacheType + " name:" + cacheKey;
-        logger.info(log);
-        try {
-            switch (cacheType) {
-            case CUBE:
-                rebuildCubeCache(cacheKey);
-                break;
-            case STREAMING:
-                getStreamingManager().reloadStreamingConfigLocal(cacheKey);
-                break;
-            case KAFKA:
-                getKafkaManager().reloadKafkaConfigLocal(cacheKey);
-                break;
-            case CUBE_DESC:
-                getCubeDescManager().reloadCubeDescLocal(cacheKey);
-                break;
-            case PROJECT:
-                reloadProjectCache(cacheKey);
-                break;
-            case INVERTED_INDEX:
-                //II update does not need to update storage cache because it is dynamic already
-                getIIManager().reloadIILocal(cacheKey);
-                getHybridManager().reloadHybridInstanceByChild(RealizationType.INVERTED_INDEX, cacheKey);
-                getProjectManager().clearL2Cache();
-                break;
-            case INVERTED_INDEX_DESC:
-                getIIDescManager().reloadIIDescLocal(cacheKey);
-                break;
-            case TABLE:
-                getMetadataManager().reloadTableCache(cacheKey);
-                IIDescManager.clearCache();
-                CubeDescManager.clearCache();
-                break;
-            case EXTERNAL_FILTER:
-                getMetadataManager().reloadExtFilter(cacheKey);
-                IIDescManager.clearCache();
-                CubeDescManager.clearCache();
-                break;
-            case DATA_MODEL:
-                getMetadataManager().reloadDataModelDesc(cacheKey);
-                IIDescManager.clearCache();
-                CubeDescManager.clearCache();
-                break;
-            case ALL:
-                DictionaryManager.clearCache();
-                MetadataManager.clearCache();
-                CubeDescManager.clearCache();
-                CubeManager.clearCache();
-                IIDescManager.clearCache();
-                IIManager.clearCache();
-                HybridManager.clearCache();
-                RealizationRegistry.clearCache();
-                ProjectManager.clearCache();
-                KafkaConfigManager.clearCache();
-                StreamingManager.clearCache();
-                HBaseConnection.clearConnCache();
-
-                cleanAllDataCache();
-                removeAllOLAPDataSources();
-                break;
-            default:
-                throw new RuntimeException("invalid cacheType:" + cacheType);
-            }
-        } catch (IOException e) {
-            throw new RuntimeException("error " + log, e);
-        }
-    }
-
-    private void rebuildCubeCache(String cubeName) {
-        CubeInstance cube = getCubeManager().reloadCubeLocal(cubeName);
-        getHybridManager().reloadHybridInstanceByChild(RealizationType.CUBE, cubeName);
-        reloadProjectCache(getProjectManager().findProjects(RealizationType.CUBE, cubeName));
-        //clean query related cache first
-        if (cube != null) {
-            cleanDataCache(cube.getUuid());
-        }
-        cubeService.updateOnNewSegmentReady(cubeName);
-    }
-
-    public void removeCache(Broadcaster.TYPE cacheType, String cacheKey) {
-        final String log = "remove cache type: " + cacheType + " name:" + cacheKey;
-        try {
-            switch (cacheType) {
-            case CUBE:
-                removeCubeCache(cacheKey, null);
-                break;
-            case CUBE_DESC:
-                getCubeDescManager().removeLocalCubeDesc(cacheKey);
-                break;
-            case PROJECT:
-                ProjectManager.clearCache();
-                break;
-            case INVERTED_INDEX:
-                getIIManager().removeIILocal(cacheKey);
-                break;
-            case INVERTED_INDEX_DESC:
-                getIIDescManager().removeIIDescLocal(cacheKey);
-                break;
-            case TABLE:
-                throw new UnsupportedOperationException(log);
-            case EXTERNAL_FILTER:
-                throw new UnsupportedOperationException(log);
-            case DATA_MODEL:
-                getMetadataManager().removeModelCache(cacheKey);
-                break;
-            default:
-                throw new RuntimeException("invalid cacheType:" + cacheType);
-            }
-        } catch (IOException e) {
-            throw new RuntimeException("error " + log, e);
-        }
-    }
-
-    private void removeCubeCache(String cubeName, CubeInstance cube) {
-        // you may not get the cube instance if it's already removed from metadata
-        if (cube == null) {
-            cube = getCubeManager().getCube(cubeName);
-        }
-
-        getCubeManager().removeCubeLocal(cubeName);
-        getHybridManager().reloadHybridInstanceByChild(RealizationType.CUBE, cubeName);
-        reloadProjectCache(getProjectManager().findProjects(RealizationType.CUBE, cubeName));
-
-        if (cube != null) {
-            cleanDataCache(cube.getUuid());
-        }
-    }
-
-    private void reloadProjectCache(List<ProjectInstance> projects) {
-        for (ProjectInstance prj : projects) {
-            reloadProjectCache(prj.getName());
-        }
-    }
-
-    private void reloadProjectCache(String projectName) {
-        try {
-            getProjectManager().reloadProjectLocal(projectName);
-        } catch (IOException ex) {
-            logger.warn("Failed to reset project cache", ex);
-        }
-        removeOLAPDataSource(projectName);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/CubeService.java b/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
deleted file mode 100644
index a9d4bfc..0000000
--- a/server/src/main/java/org/apache/kylin/rest/service/CubeService.java
+++ /dev/null
@@ -1,676 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.service;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.WeakHashMap;
-
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hbase.client.HTable;
-import org.apache.kylin.common.KylinConfig;
-import org.apache.kylin.common.util.Pair;
-import org.apache.kylin.cube.CubeInstance;
-import org.apache.kylin.cube.CubeManager;
-import org.apache.kylin.cube.CubeSegment;
-import org.apache.kylin.cube.CubeUpdate;
-import org.apache.kylin.cube.cuboid.CuboidCLI;
-import org.apache.kylin.cube.model.CubeDesc;
-import org.apache.kylin.engine.EngineFactory;
-import org.apache.kylin.engine.mr.CubingJob;
-import org.apache.kylin.engine.mr.HadoopUtil;
-import org.apache.kylin.engine.mr.common.HadoopShellExecutable;
-import org.apache.kylin.engine.mr.common.MapReduceExecutable;
-import org.apache.kylin.job.exception.JobException;
-import org.apache.kylin.job.execution.DefaultChainedExecutable;
-import org.apache.kylin.job.execution.ExecutableState;
-import org.apache.kylin.metadata.MetadataConstants;
-import org.apache.kylin.metadata.MetadataManager;
-import org.apache.kylin.metadata.model.SegmentStatusEnum;
-import org.apache.kylin.metadata.model.TableDesc;
-import org.apache.kylin.metadata.project.ProjectInstance;
-import org.apache.kylin.metadata.project.ProjectManager;
-import org.apache.kylin.metadata.project.RealizationEntry;
-import org.apache.kylin.metadata.realization.RealizationStatusEnum;
-import org.apache.kylin.metadata.realization.RealizationType;
-import org.apache.kylin.rest.constant.Constant;
-import org.apache.kylin.rest.exception.InternalErrorException;
-import org.apache.kylin.rest.request.MetricsRequest;
-import org.apache.kylin.rest.response.HBaseResponse;
-import org.apache.kylin.rest.response.MetricsResponse;
-import org.apache.kylin.rest.security.AclPermission;
-import org.apache.kylin.source.hive.HiveSourceTableLoader;
-import org.apache.kylin.source.hive.cardinality.HiveColumnCardinalityJob;
-import org.apache.kylin.source.hive.cardinality.HiveColumnCardinalityUpdateJob;
-import org.apache.kylin.storage.hbase.HBaseConnection;
-import org.apache.kylin.storage.hbase.util.HBaseRegionSizeCalculator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PostFilter;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.stereotype.Component;
-
-import com.google.common.collect.Lists;
-
-/**
- * Stateless & lightweight service facade of cube management functions.
- *
- * @author yangli9
- */
-@Component("cubeMgmtService")
-public class CubeService extends BasicService {
-    private static final String DESC_SUFFIX = "_desc";
-
-    private static final Logger logger = LoggerFactory.getLogger(CubeService.class);
-
-    private WeakHashMap<String, HBaseResponse> htableInfoCache = new WeakHashMap<>();
-
-    @Autowired
-    private AccessService accessService;
-
-    @PostFilter(Constant.ACCESS_POST_FILTER_READ)
-    public List<CubeInstance> listAllCubes(final String cubeName, final String projectName, final String modelName) {
-        List<CubeInstance> cubeInstances = null;
-        ProjectInstance project = (null != projectName) ? getProjectManager().getProject(projectName) : null;
-
-        if (null == project) {
-            cubeInstances = getCubeManager().listAllCubes();
-        } else {
-            cubeInstances = listAllCubes(projectName);
-        }
-
-        List<CubeInstance> filterModelCubes = new ArrayList<CubeInstance>();
-
-        if (modelName != null) {
-            for (CubeInstance cubeInstance : cubeInstances) {
-                boolean isCubeMatch = cubeInstance.getDescriptor().getModelName().toLowerCase().equals(modelName.toLowerCase());
-                if (isCubeMatch) {
-                    filterModelCubes.add(cubeInstance);
-                }
-            }
-        } else {
-            filterModelCubes = cubeInstances;
-        }
-
-        List<CubeInstance> filterCubes = new ArrayList<CubeInstance>();
-        for (CubeInstance cubeInstance : filterModelCubes) {
-            boolean isCubeMatch = (null == cubeName) || cubeInstance.getName().toLowerCase().contains(cubeName.toLowerCase());
-
-            if (isCubeMatch) {
-                filterCubes.add(cubeInstance);
-            }
-        }
-
-        return filterCubes;
-    }
-
-    public List<CubeInstance> getCubes(final String cubeName, final String projectName, final String modelName, final Integer limit, final Integer offset) {
-
-        List<CubeInstance> cubes;
-        cubes = listAllCubes(cubeName, projectName, modelName);
-
-        int climit = (null == limit) ? cubes.size() : limit;
-        int coffset = (null == offset) ? 0 : offset;
-
-        if (cubes.size() <= coffset) {
-            return Collections.emptyList();
-        }
-
-        if ((cubes.size() - coffset) < climit) {
-            return cubes.subList(coffset, cubes.size());
-        }
-
-        return cubes.subList(coffset, coffset + climit);
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
-    public CubeInstance updateCubeCost(String cubeName, int cost) throws IOException {
-        CubeInstance cube = getCubeManager().getCube(cubeName);
-        if (cube == null) {
-            throw new IOException("Cannot find cube " + cubeName);
-        }
-        if (cube.getCost() == cost) {
-            // Do nothing
-            return cube;
-        }
-        cube.setCost(cost);
-
-        String owner = SecurityContextHolder.getContext().getAuthentication().getName();
-        cube.setOwner(owner);
-
-        CubeUpdate cubeBuilder = new CubeUpdate(cube).setOwner(owner).setCost(cost);
-
-        return getCubeManager().updateCube(cubeBuilder);
-    }
-
-    public CubeInstance createCubeAndDesc(String cubeName, String projectName, CubeDesc desc) throws IOException {
-        if (getCubeManager().getCube(cubeName) != null) {
-            throw new InternalErrorException("The cube named " + cubeName + " already exists");
-        }
-
-        if (getCubeDescManager().getCubeDesc(desc.getName()) != null) {
-            throw new InternalErrorException("The cube desc named " + desc.getName() + " already exists");
-        }
-
-        String owner = SecurityContextHolder.getContext().getAuthentication().getName();
-        CubeDesc createdDesc;
-        CubeInstance createdCube;
-
-        createdDesc = getCubeDescManager().createCubeDesc(desc);
-
-        if (!createdDesc.getError().isEmpty()) {
-            getCubeDescManager().removeCubeDesc(createdDesc);
-            throw new InternalErrorException(createdDesc.getError().get(0));
-        }
-
-        try {
-            int cuboidCount = CuboidCLI.simulateCuboidGeneration(createdDesc, false);
-            logger.info("New cube " + cubeName + " has " + cuboidCount + " cuboids");
-        } catch (Exception e) {
-            getCubeDescManager().removeCubeDesc(createdDesc);
-            throw new InternalErrorException("Failed to deal with the request.", e);
-        }
-
-        createdCube = getCubeManager().createCube(cubeName, projectName, createdDesc, owner);
-        accessService.init(createdCube, AclPermission.ADMINISTRATION);
-
-        ProjectInstance project = getProjectManager().getProject(projectName);
-        accessService.inherit(createdCube, project);
-
-        return createdCube;
-    }
-
-    public List<CubeInstance> listAllCubes(String projectName) {
-        ProjectManager projectManager = getProjectManager();
-        ProjectInstance project = projectManager.getProject(projectName);
-        if (project == null) {
-            return Collections.emptyList();
-        }
-        ArrayList<CubeInstance> result = new ArrayList<CubeInstance>();
-        for (RealizationEntry projectDataModel : project.getRealizationEntries()) {
-            if (projectDataModel.getType() == RealizationType.CUBE) {
-                CubeInstance cube = getCubeManager().getCube(projectDataModel.getRealization());
-                if (cube != null)
-                    result.add(cube);
-                else
-                    logger.error("Cube instance " + projectDataModel.getRealization() + " is failed to load");
-            }
-        }
-        return result;
-    }
-
-    private boolean isCubeInProject(String projectName, CubeInstance target) {
-        ProjectManager projectManager = getProjectManager();
-        ProjectInstance project = projectManager.getProject(projectName);
-        if (project == null) {
-            return false;
-        }
-        for (RealizationEntry projectDataModel : project.getRealizationEntries()) {
-            if (projectDataModel.getType() == RealizationType.CUBE) {
-                CubeInstance cube = getCubeManager().getCube(projectDataModel.getRealization());
-                if (cube == null) {
-                    logger.error("Project " + projectName + " contains realization " + projectDataModel.getRealization() + " which is not found by CubeManager");
-                    continue;
-                }
-                if (cube.equals(target)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'MANAGEMENT')")
-    public CubeDesc updateCubeAndDesc(CubeInstance cube, CubeDesc desc, String newProjectName, boolean forceUpdate) throws IOException, JobException {
-
-        final List<CubingJob> cubingJobs = listAllCubingJobs(cube.getName(), null, EnumSet.of(ExecutableState.READY, ExecutableState.RUNNING));
-        if (!cubingJobs.isEmpty()) {
-            throw new JobException("Cube schema shouldn't be changed with running job.");
-        }
-
-        try {
-            //double check again
-            if (!forceUpdate && !cube.getDescriptor().consistentWith(desc)) {
-                throw new IllegalStateException("cube's desc is not consistent with the new desc");
-            }
-
-            CubeDesc updatedCubeDesc = getCubeDescManager().updateCubeDesc(desc);
-            int cuboidCount = CuboidCLI.simulateCuboidGeneration(updatedCubeDesc, false);
-            logger.info("Updated cube " + cube.getName() + " has " + cuboidCount + " cuboids");
-
-            ProjectManager projectManager = getProjectManager();
-            if (!isCubeInProject(newProjectName, cube)) {
-                String owner = SecurityContextHolder.getContext().getAuthentication().getName();
-                ProjectInstance newProject = projectManager.moveRealizationToProject(RealizationType.CUBE, cube.getName(), newProjectName, owner);
-                accessService.inherit(cube, newProject);
-            }
-
-            return updatedCubeDesc;
-        } catch (IOException e) {
-            throw new InternalErrorException("Failed to deal with the request.", e);
-        }
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'MANAGEMENT')")
-    public void deleteCube(CubeInstance cube) throws IOException, JobException {
-        final List<CubingJob> cubingJobs = listAllCubingJobs(cube.getName(), null, EnumSet.of(ExecutableState.READY, ExecutableState.RUNNING));
-        if (!cubingJobs.isEmpty()) {
-            throw new JobException("The cube " + cube.getName() + " has running job, please discard it and try again.");
-        }
-
-        this.releaseAllSegments(cube);
-        getCubeManager().dropCube(cube.getName(), true);
-        accessService.clean(cube, true);
-    }
-
-    public boolean isCubeDescFreeEditable(CubeDesc cd) {
-        List<CubeInstance> cubes = getCubeManager().getCubesByDesc(cd.getName());
-        for (CubeInstance cube : cubes) {
-            if (cube.getSegments().size() != 0) {
-                logger.debug("cube '" + cube.getName() + " has " + cube.getSegments().size() + " segments, couldn't edit cube desc.");
-                return false;
-            }
-        }
-        return true;
-    }
-
-    public static String getCubeDescNameFromCube(String cubeName) {
-        return cubeName + DESC_SUFFIX;
-    }
-
-    public static String getCubeNameFromDesc(String descName) {
-        if (descName.toLowerCase().endsWith(DESC_SUFFIX)) {
-            return descName.substring(0, descName.toLowerCase().indexOf(DESC_SUFFIX));
-        } else {
-            return descName;
-        }
-    }
-
-    /**
-     * Stop all jobs belonging to this cube and clean out all segments
-     *
-     * @param cube
-     * @return
-     * @throws IOException
-     * @throws JobException
-     */
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'OPERATION') or hasPermission(#cube, 'MANAGEMENT')")
-    public CubeInstance purgeCube(CubeInstance cube) throws IOException, JobException {
-
-        String cubeName = cube.getName();
-        RealizationStatusEnum ostatus = cube.getStatus();
-        if (null != ostatus && !RealizationStatusEnum.DISABLED.equals(ostatus)) {
-            throw new InternalErrorException("Only disabled cube can be purged, status of " + cubeName + " is " + ostatus);
-        }
-
-        try {
-            this.releaseAllSegments(cube);
-            return cube;
-        } catch (IOException e) {
-            throw e;
-        }
-
-    }
-
-    /**
-     * Update a cube status from ready to disabled.
-     *
-     * @return
-     * @throws IOException
-     * @throws JobException
-     */
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'OPERATION') or hasPermission(#cube, 'MANAGEMENT')")
-    public CubeInstance disableCube(CubeInstance cube) throws IOException, JobException {
-
-        String cubeName = cube.getName();
-
-        RealizationStatusEnum ostatus = cube.getStatus();
-        if (null != ostatus && !RealizationStatusEnum.READY.equals(ostatus)) {
-            throw new InternalErrorException("Only ready cube can be disabled, status of " + cubeName + " is " + ostatus);
-        }
-
-        cube.setStatus(RealizationStatusEnum.DISABLED);
-
-        try {
-            CubeUpdate cubeBuilder = new CubeUpdate(cube);
-            cubeBuilder.setStatus(RealizationStatusEnum.DISABLED);
-            return getCubeManager().updateCube(cubeBuilder);
-        } catch (IOException e) {
-            cube.setStatus(ostatus);
-            throw e;
-        }
-    }
-
-    /**
-     * Update a cube status from disable to ready.
-     *
-     * @return
-     * @throws IOException
-     * @throws JobException
-     */
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'OPERATION')  or hasPermission(#cube, 'MANAGEMENT')")
-    public CubeInstance enableCube(CubeInstance cube) throws IOException, JobException {
-        String cubeName = cube.getName();
-
-        RealizationStatusEnum ostatus = cube.getStatus();
-        if (!cube.getStatus().equals(RealizationStatusEnum.DISABLED)) {
-            throw new InternalErrorException("Only disabled cube can be enabled, status of " + cubeName + " is " + ostatus);
-        }
-
-        if (cube.getSegments(SegmentStatusEnum.READY).size() == 0) {
-            throw new InternalErrorException("Cube " + cubeName + " dosen't contain any READY segment");
-        }
-
-        final List<CubingJob> cubingJobs = listAllCubingJobs(cube.getName(), null, EnumSet.of(ExecutableState.READY, ExecutableState.RUNNING));
-        if (!cubingJobs.isEmpty()) {
-            throw new JobException("Enable is not allowed with a running job.");
-        }
-        if (!cube.getDescriptor().checkSignature()) {
-            throw new IllegalStateException("Inconsistent cube desc signature for " + cube.getDescriptor());
-        }
-
-        try {
-            CubeUpdate cubeBuilder = new CubeUpdate(cube);
-            cubeBuilder.setStatus(RealizationStatusEnum.READY);
-            return getCubeManager().updateCube(cubeBuilder);
-        } catch (IOException e) {
-            cube.setStatus(ostatus);
-            throw e;
-        }
-    }
-
-    public MetricsResponse calculateMetrics(MetricsRequest request) {
-        List<CubeInstance> cubes = this.getCubeManager().listAllCubes();
-        MetricsResponse metrics = new MetricsResponse();
-        Date startTime = (null == request.getStartTime()) ? new Date(-1) : request.getStartTime();
-        Date endTime = (null == request.getEndTime()) ? new Date() : request.getEndTime();
-        metrics.increase("totalCubes", (float) 0);
-        metrics.increase("totalStorage", (float) 0);
-
-        for (CubeInstance cube : cubes) {
-            Date createdDate = new Date(-1);
-            createdDate = (cube.getCreateTimeUTC() == 0) ? createdDate : new Date(cube.getCreateTimeUTC());
-
-            if (createdDate.getTime() > startTime.getTime() && createdDate.getTime() < endTime.getTime()) {
-                metrics.increase("totalCubes");
-            }
-        }
-
-        metrics.increase("aveStorage", (metrics.get("totalCubes") == 0) ? 0 : metrics.get("totalStorage") / metrics.get("totalCubes"));
-
-        return metrics;
-    }
-
-    /**
-     * Calculate size of each region for given table and other info of the
-     * table.
-     *
-     * @param tableName The table name.
-     * @return The HBaseResponse object contains table size, region count. null
-     * if error happens.
-     * @throws IOException Exception when HTable resource is not closed correctly.
-     */
-    public HBaseResponse getHTableInfo(String tableName) throws IOException {
-        if (htableInfoCache.containsKey(tableName)) {
-            return htableInfoCache.get(tableName);
-        }
-
-        Configuration hconf = HBaseConnection.getCurrentHBaseConfiguration();
-        HTable table = null;
-        HBaseResponse hr = null;
-        long tableSize = 0;
-        int regionCount = 0;
-
-        try {
-            table = new HTable(hconf, tableName);
-
-            HBaseRegionSizeCalculator cal = new HBaseRegionSizeCalculator(table);
-            Map<byte[], Long> sizeMap = cal.getRegionSizeMap();
-
-            for (long s : sizeMap.values()) {
-                tableSize += s;
-            }
-
-            regionCount = sizeMap.size();
-
-            // Set response.
-            hr = new HBaseResponse();
-            hr.setTableSize(tableSize);
-            hr.setRegionCount(regionCount);
-        } finally {
-            if (null != table) {
-                table.close();
-            }
-        }
-
-        htableInfoCache.put(tableName, hr);
-
-        return hr;
-    }
-
-    /**
-     * Generate cardinality for table This will trigger a hadoop job
-     * The result will be merged into table exd info
-     *
-     * @param tableName
-     */
-    public void calculateCardinality(String tableName, String submitter) {
-        String[] dbTableName = HadoopUtil.parseHiveTableName(tableName);
-        tableName = dbTableName[0] + "." + dbTableName[1];
-        TableDesc table = getMetadataManager().getTableDesc(tableName);
-        final Map<String, String> tableExd = getMetadataManager().getTableDescExd(tableName);
-        if (tableExd == null || table == null) {
-            IllegalArgumentException e = new IllegalArgumentException("Cannot find table descirptor " + tableName);
-            logger.error("Cannot find table descirptor " + tableName, e);
-            throw e;
-        }
-
-        DefaultChainedExecutable job = new DefaultChainedExecutable();
-        job.setName("Hive Column Cardinality calculation for table '" + tableName + "'");
-        job.setSubmitter(submitter);
-
-        String outPath = HiveColumnCardinalityJob.OUTPUT_PATH + "/" + tableName;
-        String param = "-table " + tableName + " -output " + outPath;
-
-        MapReduceExecutable step1 = new MapReduceExecutable();
-
-        step1.setMapReduceJobClass(HiveColumnCardinalityJob.class);
-        step1.setMapReduceParams(param);
-
-        job.addTask(step1);
-
-        HadoopShellExecutable step2 = new HadoopShellExecutable();
-
-        step2.setJobClass(HiveColumnCardinalityUpdateJob.class);
-        step2.setJobParams(param);
-        job.addTask(step2);
-
-        getExecutableManager().addJob(job);
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'OPERATION')  or hasPermission(#cube, 'MANAGEMENT')")
-    public void updateCubeNotifyList(CubeInstance cube, List<String> notifyList) throws IOException {
-        CubeDesc desc = cube.getDescriptor();
-        desc.setNotifyList(notifyList);
-        getCubeDescManager().updateCubeDesc(desc);
-    }
-
-    public CubeInstance rebuildLookupSnapshot(String cubeName, String segmentName, String lookupTable) throws IOException {
-        CubeManager cubeMgr = getCubeManager();
-        CubeInstance cube = cubeMgr.getCube(cubeName);
-        CubeSegment seg = cube.getSegment(segmentName, SegmentStatusEnum.READY);
-        cubeMgr.buildSnapshotTable(seg, lookupTable);
-
-        return cube;
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'OPERATION')  or hasPermission(#cube, 'MANAGEMENT')")
-    public CubeInstance deleteSegment(CubeInstance cube, String segmentName) throws IOException {
-
-        if (!segmentName.equals(cube.getSegments().get(0).getName()) && !segmentName.equals(cube.getSegments().get(cube.getSegments().size() - 1).getName())) {
-            throw new IllegalArgumentException("Cannot delete segment '" + segmentName + "' as it is neither the first nor the last segment.");
-        }
-        CubeSegment toDelete = null;
-        for (CubeSegment seg : cube.getSegments()) {
-            if (seg.getName().equals(segmentName)) {
-                toDelete = seg;
-            }
-        }
-
-        if (toDelete.getStatus() != SegmentStatusEnum.READY) {
-            throw new IllegalArgumentException("Cannot delete segment '" + segmentName + "' as its status is not READY. Discard the on-going job for it.");
-        }
-
-        CubeUpdate update = new CubeUpdate(cube);
-        update.setToRemoveSegs(new CubeSegment[] { toDelete });
-        return CubeManager.getInstance(getConfig()).updateCube(update);
-    }
-
-    /**
-     * purge the cube
-     *
-     * @throws IOException
-     * @throws JobException
-     */
-    private CubeInstance releaseAllSegments(CubeInstance cube) throws IOException, JobException {
-        final List<CubingJob> cubingJobs = listAllCubingJobs(cube.getName(), null);
-        for (CubingJob cubingJob : cubingJobs) {
-            final ExecutableState status = cubingJob.getStatus();
-            if (status != ExecutableState.SUCCEED && status != ExecutableState.STOPPED && status != ExecutableState.DISCARDED) {
-                getExecutableManager().discardJob(cubingJob.getId());
-            }
-        }
-        CubeUpdate update = new CubeUpdate(cube);
-        update.setToRemoveSegs(cube.getSegments().toArray(new CubeSegment[cube.getSegments().size()]));
-        return CubeManager.getInstance(getConfig()).updateCube(update);
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_MODELER + " or " + Constant.ACCESS_HAS_ROLE_ADMIN)
-    public String[] reloadHiveTable(String tables) throws IOException {
-        Set<String> loaded = HiveSourceTableLoader.reloadHiveTables(tables.split(","), getConfig());
-        return (String[]) loaded.toArray(new String[loaded.size()]);
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
-    public void unLoadHiveTable(String tableName) throws IOException {
-        String[] dbTableName = HadoopUtil.parseHiveTableName(tableName);
-        tableName = dbTableName[0] + "." + dbTableName[1];
-        HiveSourceTableLoader.unLoadHiveTable(tableName.toUpperCase());
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
-    public void syncTableToProject(String[] tables, String project) throws IOException {
-        getProjectManager().addTableDescToProject(tables, project);
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
-    public void removeTableFromProject(String tableName, String projectName) throws IOException {
-        String[] dbTableName = HadoopUtil.parseHiveTableName(tableName);
-        tableName = dbTableName[0] + "." + dbTableName[1];
-        getProjectManager().removeTableDescFromProject(tableName, projectName);
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_MODELER + " or " + Constant.ACCESS_HAS_ROLE_ADMIN)
-    public void calculateCardinalityIfNotPresent(String[] tables, String submitter) throws IOException {
-        MetadataManager metaMgr = getMetadataManager();
-        for (String table : tables) {
-            Map<String, String> exdMap = metaMgr.getTableDescExd(table);
-            if (exdMap == null || !exdMap.containsKey(MetadataConstants.TABLE_EXD_CARDINALITY)) {
-                calculateCardinality(table, submitter);
-            }
-        }
-    }
-
-    public void updateOnNewSegmentReady(String cubeName) {
-        logger.debug("on updateOnNewSegmentReady: " + cubeName);
-        final KylinConfig kylinConfig = KylinConfig.getInstanceFromEnv();
-        String serverMode = kylinConfig.getServerMode();
-        logger.debug("server mode: " + serverMode);
-        if (Constant.SERVER_MODE_JOB.equals(serverMode.toLowerCase()) || Constant.SERVER_MODE_ALL.equals(serverMode.toLowerCase())) {
-            keepCubeRetention(cubeName);
-            mergeCubeSegment(cubeName);
-        }
-
-    }
-
-    private void keepCubeRetention(String cubeName) {
-        logger.info("checking keepCubeRetention");
-        CubeInstance cube = getCubeManager().getCube(cubeName);
-        CubeDesc desc = cube.getDescriptor();
-        if (desc.getRetentionRange() <= 0)
-            return;
-
-        synchronized (CubeService.class) {
-            cube = getCubeManager().getCube(cubeName);
-            List<CubeSegment> readySegs = cube.getSegments(SegmentStatusEnum.READY);
-            if (readySegs.isEmpty())
-                return;
-
-            List<CubeSegment> toRemoveSegs = Lists.newArrayList();
-            long tail = readySegs.get(readySegs.size() - 1).getDateRangeEnd();
-            long head = tail - desc.getRetentionRange();
-            for (CubeSegment seg : readySegs) {
-                if (seg.getDateRangeEnd() <= head)
-                    toRemoveSegs.add(seg);
-            }
-
-            if (toRemoveSegs.size() > 0) {
-                CubeUpdate cubeBuilder = new CubeUpdate(cube);
-                cubeBuilder.setToRemoveSegs(toRemoveSegs.toArray(new CubeSegment[toRemoveSegs.size()]));
-                try {
-                    this.getCubeManager().updateCube(cubeBuilder);
-                } catch (IOException e) {
-                    logger.error("Failed to remove old segment from cube " + cubeName, e);
-                }
-            }
-        }
-    }
-
-    private void mergeCubeSegment(String cubeName) {
-        CubeInstance cube = getCubeManager().getCube(cubeName);
-        if (!cube.needAutoMerge())
-            return;
-
-        synchronized (CubeService.class) {
-            try {
-                cube = getCubeManager().getCube(cubeName);
-                Pair<Long, Long> offsets = getCubeManager().autoMergeCubeSegments(cube);
-                if (offsets != null) {
-                    CubeSegment newSeg = getCubeManager().mergeSegments(cube, 0, 0, offsets.getFirst(), offsets.getSecond(), true);
-                    logger.debug("Will submit merge job on " + newSeg);
-                    DefaultChainedExecutable job = EngineFactory.createBatchMergeJob(newSeg, "SYSTEM");
-                    getExecutableManager().addJob(job);
-                } else {
-                    logger.debug("Not ready for merge on cube " + cubeName);
-                }
-            } catch (IOException e) {
-                logger.error("Failed to auto merge cube " + cubeName, e);
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/service/DiagnosisService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/DiagnosisService.java b/server/src/main/java/org/apache/kylin/rest/service/DiagnosisService.java
deleted file mode 100644
index ba51ea1..0000000
--- a/server/src/main/java/org/apache/kylin/rest/service/DiagnosisService.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.service;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-
-import org.apache.kylin.metadata.badquery.BadQueryHistory;
-import org.apache.kylin.rest.constant.Constant;
-import org.apache.kylin.tool.DiagnosisInfoCLI;
-import org.apache.kylin.tool.JobDiagnosisInfoCLI;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.stereotype.Component;
-
-import com.google.common.io.Files;
-
-@Component("diagnosisService")
-public class DiagnosisService extends BasicService {
-
-    private static final Logger logger = LoggerFactory.getLogger(DiagnosisService.class);
-
-    private File getDumpDir() {
-        return Files.createTempDir();
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
-    public BadQueryHistory getProjectBadQueryHistory(String project) throws IOException {
-        return getBadQueryHistoryManager().getBadQueriesForProject(project);
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
-    public String dumpProjectDiagnosisInfo(String project) throws IOException {
-        String[] args = { "-project", "-all", "-destDir", getDumpDir().getAbsolutePath() };
-        logger.info("DiagnosisInfoCLI args: " + Arrays.toString(args));
-        DiagnosisInfoCLI diagnosisInfoCli = new DiagnosisInfoCLI();
-        diagnosisInfoCli.execute(args);
-        return diagnosisInfoCli.getExportDest();
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
-    public String dumpJobDiagnosisInfo(String jobId) throws IOException {
-        String[] args = { "-jobId", jobId, "-destDir", getDumpDir().getAbsolutePath() };
-        logger.info("JobDiagnosisInfoCLI args: " + Arrays.toString(args));
-        JobDiagnosisInfoCLI jobInfoExtractor = new JobDiagnosisInfoCLI();
-        jobInfoExtractor.execute(args);
-        return jobInfoExtractor.getExportDest();
-    }
-
-    public static void main(String[] args1) {
-        String[] args = { "-project", "-all", "-destDir", Files.createTempDir().getAbsolutePath() };
-        logger.info("DiagnosisInfoCLI args: " + Arrays.toString(args));
-        DiagnosisInfoCLI diagnosisInfoCli = new DiagnosisInfoCLI();
-        diagnosisInfoCli.execute(args);
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/service/ExtFilterService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/ExtFilterService.java b/server/src/main/java/org/apache/kylin/rest/service/ExtFilterService.java
deleted file mode 100644
index 0c98965..0000000
--- a/server/src/main/java/org/apache/kylin/rest/service/ExtFilterService.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.service;
-
-import java.io.IOException;
-import java.util.List;
-
-import org.apache.kylin.metadata.model.ExternalFilterDesc;
-import org.apache.kylin.rest.constant.Constant;
-import org.apache.kylin.rest.exception.InternalErrorException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.stereotype.Component;
-
-@Component("extFilterService")
-public class ExtFilterService extends BasicService {
-    private static final Logger logger = LoggerFactory.getLogger(ExtFilterService.class);
-
-    @Autowired
-    private AccessService accessService;
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
-    public void saveExternalFilter(ExternalFilterDesc desc) throws IOException {
-        if (getMetadataManager().getExtFilterDesc(desc.getName()) != null) {
-            throw new InternalErrorException("The filter named " + desc.getName() + " already exists");
-        }
-        getMetadataManager().saveExternalFilter(desc);
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
-    public void updateExternalFilter(ExternalFilterDesc desc) throws IOException {
-        if (getMetadataManager().getExtFilterDesc(desc.getName()) == null) {
-            throw new InternalErrorException("The filter named " + desc.getName() + " does not exists");
-        }
-        getMetadataManager().saveExternalFilter(desc);
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
-    public void removeExternalFilter(String name) throws IOException {
-        getMetadataManager().removeExternalFilter(name);
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
-    public void syncExtFilterToProject(String[] filters, String project) throws IOException {
-        getProjectManager().addExtFilterToProject(filters, project);
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
-    public void removeExtFilterFromProject(String filterName, String projectName) throws IOException {
-        getProjectManager().removeExtFilterFromProject(filterName, projectName);
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN)
-    public List<ExternalFilterDesc> listAllExternalFilters() {
-        return getMetadataManager().listAllExternalFilters();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/service/JobService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/JobService.java b/server/src/main/java/org/apache/kylin/rest/service/JobService.java
deleted file mode 100644
index c868264..0000000
--- a/server/src/main/java/org/apache/kylin/rest/service/JobService.java
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.service;
-
-import java.io.IOException;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.Date;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.kylin.cube.CubeInstance;
-import org.apache.kylin.cube.CubeSegment;
-import org.apache.kylin.cube.CubeUpdate;
-import org.apache.kylin.cube.model.CubeBuildTypeEnum;
-import org.apache.kylin.engine.EngineFactory;
-import org.apache.kylin.engine.mr.CubingJob;
-import org.apache.kylin.engine.mr.common.HadoopShellExecutable;
-import org.apache.kylin.engine.mr.common.MapReduceExecutable;
-import org.apache.kylin.engine.mr.steps.CubingExecutableUtil;
-import org.apache.kylin.job.JobInstance;
-import org.apache.kylin.job.common.ShellExecutable;
-import org.apache.kylin.job.constant.JobStatusEnum;
-import org.apache.kylin.job.constant.JobStepStatusEnum;
-import org.apache.kylin.job.constant.JobTimeFilterEnum;
-import org.apache.kylin.job.exception.JobException;
-import org.apache.kylin.job.execution.AbstractExecutable;
-import org.apache.kylin.job.execution.DefaultChainedExecutable;
-import org.apache.kylin.job.execution.ExecutableState;
-import org.apache.kylin.job.execution.Output;
-import org.apache.kylin.metadata.model.SegmentStatusEnum;
-import org.apache.kylin.rest.constant.Constant;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.stereotype.Component;
-
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-/**
- * @author ysong1
- */
-@Component("jobService")
-public class JobService extends BasicService {
-
-    @SuppressWarnings("unused")
-    private static final Logger logger = LoggerFactory.getLogger(JobService.class);
-
-    @Autowired
-    private AccessService accessService;
-
-    public List<JobInstance> listAllJobs(final String cubeName, final String projectName, final List<JobStatusEnum> statusList, final Integer limitValue, final Integer offsetValue, final JobTimeFilterEnum timeFilter) throws IOException, JobException {
-        Integer limit = (null == limitValue) ? 30 : limitValue;
-        Integer offset = (null == offsetValue) ? 0 : offsetValue;
-        List<JobInstance> jobs = listAllJobs(cubeName, projectName, statusList, timeFilter);
-        Collections.sort(jobs);
-
-        if (jobs.size() <= offset) {
-            return Collections.emptyList();
-        }
-
-        if ((jobs.size() - offset) < limit) {
-            return jobs.subList(offset, jobs.size());
-        }
-
-        return jobs.subList(offset, offset + limit);
-    }
-
-    public List<JobInstance> listAllJobs(final String cubeName, final String projectName, final List<JobStatusEnum> statusList, final JobTimeFilterEnum timeFilter) {
-        Calendar calendar = Calendar.getInstance();
-        calendar.setTime(new Date());
-        long currentTimeMillis = calendar.getTimeInMillis();
-        long timeStartInMillis = getTimeStartInMillis(calendar, timeFilter);
-        return listCubeJobInstance(cubeName, projectName, statusList, timeStartInMillis, currentTimeMillis);
-    }
-
-    @Deprecated
-    public List<JobInstance> listAllJobs(final String cubeName, final String projectName, final List<JobStatusEnum> statusList, final Integer limitValue, final Integer offsetValue) throws IOException, JobException {
-        Integer limit = (null == limitValue) ? 30 : limitValue;
-        Integer offset = (null == offsetValue) ? 0 : offsetValue;
-        List<JobInstance> jobs = listAllJobs(cubeName, projectName, statusList);
-        Collections.sort(jobs);
-
-        if (jobs.size() <= offset) {
-            return Collections.emptyList();
-        }
-
-        if ((jobs.size() - offset) < limit) {
-            return jobs.subList(offset, jobs.size());
-        }
-
-        return jobs.subList(offset, offset + limit);
-    }
-
-    public List<JobInstance> listAllJobs(final String cubeName, final String projectName, final List<JobStatusEnum> statusList) {
-        return listCubeJobInstance(cubeName, projectName, statusList);
-    }
-
-    private List<JobInstance> listCubeJobInstance(final String cubeName, final String projectName, List<JobStatusEnum> statusList, final long timeStartInMillis, final long timeEndInMillis) {
-        Set<ExecutableState> states = convertStatusEnumToStates(statusList);
-        final Map<String, Output> allOutputs = getExecutableManager().getAllOutputs(timeStartInMillis, timeEndInMillis);
-        return Lists.newArrayList(FluentIterable.from(listAllCubingJobs(cubeName, projectName, states, timeStartInMillis, timeEndInMillis, allOutputs)).transform(new Function<CubingJob, JobInstance>() {
-            @Override
-            public JobInstance apply(CubingJob cubingJob) {
-                return parseToJobInstance(cubingJob, allOutputs);
-            }
-        }));
-    }
-
-    private List<JobInstance> listCubeJobInstance(final String cubeName, final String projectName, List<JobStatusEnum> statusList) {
-        Set<ExecutableState> states = convertStatusEnumToStates(statusList);
-        final Map<String, Output> allOutputs = getExecutableManager().getAllOutputs();
-        return Lists.newArrayList(FluentIterable.from(listAllCubingJobs(cubeName, projectName, states, allOutputs)).transform(new Function<CubingJob, JobInstance>() {
-            @Override
-            public JobInstance apply(CubingJob cubingJob) {
-                return parseToJobInstance(cubingJob, allOutputs);
-            }
-        }));
-    }
-
-    private Set<ExecutableState> convertStatusEnumToStates(List<JobStatusEnum> statusList) {
-        Set<ExecutableState> states;
-        if (statusList == null || statusList.isEmpty()) {
-            states = EnumSet.allOf(ExecutableState.class);
-        } else {
-            states = Sets.newHashSet();
-            for (JobStatusEnum status : statusList) {
-                states.add(parseToExecutableState(status));
-            }
-        }
-        return states;
-    }
-
-    private long getTimeStartInMillis(Calendar calendar, JobTimeFilterEnum timeFilter) {
-        switch (timeFilter) {
-        case LAST_ONE_DAY:
-            calendar.add(Calendar.DAY_OF_MONTH, -1);
-            return calendar.getTimeInMillis();
-        case LAST_ONE_WEEK:
-            calendar.add(Calendar.WEEK_OF_MONTH, -1);
-            return calendar.getTimeInMillis();
-        case LAST_ONE_MONTH:
-            calendar.add(Calendar.MONTH, -1);
-            return calendar.getTimeInMillis();
-        case LAST_ONE_YEAR:
-            calendar.add(Calendar.YEAR, -1);
-            return calendar.getTimeInMillis();
-        case ALL:
-            return 0;
-        default:
-            throw new RuntimeException("illegal timeFilter for job history:" + timeFilter);
-        }
-    }
-
-    private ExecutableState parseToExecutableState(JobStatusEnum status) {
-        switch (status) {
-        case DISCARDED:
-            return ExecutableState.DISCARDED;
-        case ERROR:
-            return ExecutableState.ERROR;
-        case FINISHED:
-            return ExecutableState.SUCCEED;
-        case NEW:
-            return ExecutableState.READY;
-        case PENDING:
-            return ExecutableState.READY;
-        case RUNNING:
-            return ExecutableState.RUNNING;
-        default:
-            throw new RuntimeException("illegal status:" + status);
-        }
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'OPERATION') or hasPermission(#cube, 'MANAGEMENT')")
-    public JobInstance submitJob(CubeInstance cube, long startDate, long endDate, long startOffset, long endOffset, //
-            CubeBuildTypeEnum buildType, boolean force, String submitter) throws IOException, JobException {
-
-        checkCubeDescSignature(cube);
-        checkNoRunningJob(cube);
-
-        DefaultChainedExecutable job;
-
-        if (buildType == CubeBuildTypeEnum.BUILD) {
-            CubeSegment newSeg = getCubeManager().appendSegment(cube, startDate, endDate, startOffset, endOffset);
-            job = EngineFactory.createBatchCubingJob(newSeg, submitter);
-        } else if (buildType == CubeBuildTypeEnum.MERGE) {
-            CubeSegment newSeg = getCubeManager().mergeSegments(cube, startDate, endDate, startOffset, endOffset, force);
-            job = EngineFactory.createBatchMergeJob(newSeg, submitter);
-        } else if (buildType == CubeBuildTypeEnum.REFRESH) {
-            CubeSegment refreshSeg = getCubeManager().refreshSegment(cube, startDate, endDate, startOffset, endOffset);
-            job = EngineFactory.createBatchCubingJob(refreshSeg, submitter);
-        } else {
-            throw new JobException("invalid build type:" + buildType);
-        }
-        getExecutableManager().addJob(job);
-        JobInstance jobInstance = getSingleJobInstance(job);
-
-        accessService.init(jobInstance, null);
-        accessService.inherit(jobInstance, cube);
-
-        return jobInstance;
-    }
-
-    private void checkCubeDescSignature(CubeInstance cube) {
-        if (!cube.getDescriptor().checkSignature())
-            throw new IllegalStateException("Inconsistent cube desc signature for " + cube.getDescriptor());
-    }
-
-    private void checkNoRunningJob(CubeInstance cube) throws JobException {
-        final List<CubingJob> cubingJobs = listAllCubingJobs(cube.getName(), null, EnumSet.allOf(ExecutableState.class));
-        for (CubingJob job : cubingJobs) {
-            if (job.getStatus() == ExecutableState.READY || job.getStatus() == ExecutableState.RUNNING || job.getStatus() == ExecutableState.ERROR) {
-                throw new JobException("The cube " + cube.getName() + " has running job(" + job.getId() + ") please discard it and try again.");
-            }
-        }
-    }
-
-    public JobInstance getJobInstance(String uuid) throws IOException, JobException {
-        return getSingleJobInstance(getExecutableManager().getJob(uuid));
-    }
-
-    public Output getOutput(String id) {
-        return getExecutableManager().getOutput(id);
-    }
-
-    private JobInstance getSingleJobInstance(AbstractExecutable job) {
-        if (job == null) {
-            return null;
-        }
-        Preconditions.checkState(job instanceof CubingJob, "illegal job type, id:" + job.getId());
-        CubingJob cubeJob = (CubingJob) job;
-        final JobInstance result = new JobInstance();
-        result.setName(job.getName());
-        result.setRelatedCube(CubingExecutableUtil.getCubeName(cubeJob.getParams()));
-        result.setRelatedSegment(CubingExecutableUtil.getSegmentId(cubeJob.getParams()));
-        result.setLastModified(cubeJob.getLastModified());
-        result.setSubmitter(cubeJob.getSubmitter());
-        result.setUuid(cubeJob.getId());
-        result.setType(CubeBuildTypeEnum.BUILD);
-        result.setStatus(parseToJobStatus(job.getStatus()));
-        result.setMrWaiting(cubeJob.getMapReduceWaitTime() / 1000);
-        result.setDuration(cubeJob.getDuration() / 1000);
-        for (int i = 0; i < cubeJob.getTasks().size(); ++i) {
-            AbstractExecutable task = cubeJob.getTasks().get(i);
-            result.addStep(parseToJobStep(task, i, getExecutableManager().getOutput(task.getId())));
-        }
-        return result;
-    }
-
-    private JobInstance parseToJobInstance(AbstractExecutable job, Map<String, Output> outputs) {
-        if (job == null) {
-            return null;
-        }
-        Preconditions.checkState(job instanceof CubingJob, "illegal job type, id:" + job.getId());
-        CubingJob cubeJob = (CubingJob) job;
-        Output output = outputs.get(job.getId());
-        final JobInstance result = new JobInstance();
-        result.setName(job.getName());
-        result.setRelatedCube(CubingExecutableUtil.getCubeName(cubeJob.getParams()));
-        result.setRelatedSegment(CubingExecutableUtil.getSegmentId(cubeJob.getParams()));
-        result.setLastModified(output.getLastModified());
-        result.setSubmitter(cubeJob.getSubmitter());
-        result.setUuid(cubeJob.getId());
-        result.setType(CubeBuildTypeEnum.BUILD);
-        result.setStatus(parseToJobStatus(output.getState()));
-        result.setMrWaiting(AbstractExecutable.getExtraInfoAsLong(output, CubingJob.MAP_REDUCE_WAIT_TIME, 0L) / 1000);
-        result.setDuration(AbstractExecutable.getDuration(AbstractExecutable.getStartTime(output), AbstractExecutable.getEndTime(output)) / 1000);
-        for (int i = 0; i < cubeJob.getTasks().size(); ++i) {
-            AbstractExecutable task = cubeJob.getTasks().get(i);
-            result.addStep(parseToJobStep(task, i, outputs.get(task.getId())));
-        }
-        return result;
-    }
-
-    private JobInstance.JobStep parseToJobStep(AbstractExecutable task, int i, Output stepOutput) {
-        Preconditions.checkNotNull(stepOutput);
-        JobInstance.JobStep result = new JobInstance.JobStep();
-        result.setId(task.getId());
-        result.setName(task.getName());
-        result.setSequenceID(i);
-        result.setStatus(parseToJobStepStatus(stepOutput.getState()));
-        for (Map.Entry<String, String> entry : stepOutput.getExtra().entrySet()) {
-            if (entry.getKey() != null && entry.getValue() != null) {
-                result.putInfo(entry.getKey(), entry.getValue());
-            }
-        }
-        result.setExecStartTime(AbstractExecutable.getStartTime(stepOutput));
-        result.setExecEndTime(AbstractExecutable.getEndTime(stepOutput));
-        if (task instanceof ShellExecutable) {
-            result.setExecCmd(((ShellExecutable) task).getCmd());
-        }
-        if (task instanceof MapReduceExecutable) {
-            result.setExecCmd(((MapReduceExecutable) task).getMapReduceParams());
-            result.setExecWaitTime(AbstractExecutable.getExtraInfoAsLong(stepOutput, MapReduceExecutable.MAP_REDUCE_WAIT_TIME, 0L) / 1000);
-        }
-        if (task instanceof HadoopShellExecutable) {
-            result.setExecCmd(((HadoopShellExecutable) task).getJobParams());
-        }
-        return result;
-    }
-
-    private JobStatusEnum parseToJobStatus(ExecutableState state) {
-        switch (state) {
-        case READY:
-            return JobStatusEnum.PENDING;
-        case RUNNING:
-            return JobStatusEnum.RUNNING;
-        case ERROR:
-            return JobStatusEnum.ERROR;
-        case DISCARDED:
-            return JobStatusEnum.DISCARDED;
-        case SUCCEED:
-            return JobStatusEnum.FINISHED;
-        case STOPPED:
-        default:
-            throw new RuntimeException("invalid state:" + state);
-        }
-    }
-
-    private JobStepStatusEnum parseToJobStepStatus(ExecutableState state) {
-        switch (state) {
-        case READY:
-            return JobStepStatusEnum.PENDING;
-        case RUNNING:
-            return JobStepStatusEnum.RUNNING;
-        case ERROR:
-            return JobStepStatusEnum.ERROR;
-        case DISCARDED:
-            return JobStepStatusEnum.DISCARDED;
-        case SUCCEED:
-            return JobStepStatusEnum.FINISHED;
-        case STOPPED:
-        default:
-            throw new RuntimeException("invalid state:" + state);
-        }
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#job, 'ADMINISTRATION') or hasPermission(#job, 'OPERATION') or hasPermission(#job, 'MANAGEMENT')")
-    public void resumeJob(JobInstance job) throws IOException, JobException {
-        getExecutableManager().resumeJob(job.getId());
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#job, 'ADMINISTRATION') or hasPermission(#job, 'OPERATION') or hasPermission(#job, 'MANAGEMENT')")
-    public JobInstance cancelJob(JobInstance job) throws IOException, JobException {
-        //        CubeInstance cube = this.getCubeManager().getCube(job.getRelatedCube());
-        //        for (BuildCubeJob cubeJob: listAllCubingJobs(cube.getName(), null, EnumSet.of(ExecutableState.READY, ExecutableState.RUNNING))) {
-        //            getExecutableManager().stopJob(cubeJob.getId());
-        //        }
-        CubeInstance cubeInstance = getCubeManager().getCube(job.getRelatedCube());
-        final String segmentIds = job.getRelatedSegment();
-        for (String segmentId : StringUtils.split(segmentIds)) {
-            final CubeSegment segment = cubeInstance.getSegmentById(segmentId);
-            if (segment != null && segment.getStatus() == SegmentStatusEnum.NEW) {
-                // Remove this segments
-                CubeUpdate cubeBuilder = new CubeUpdate(cubeInstance);
-                cubeBuilder.setToRemoveSegs(segment);
-                getCubeManager().updateCube(cubeBuilder);
-            }
-        }
-        getExecutableManager().discardJob(job.getId());
-        return job;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/service/KafkaConfigService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/KafkaConfigService.java b/server/src/main/java/org/apache/kylin/rest/service/KafkaConfigService.java
deleted file mode 100644
index 1f286e3..0000000
--- a/server/src/main/java/org/apache/kylin/rest/service/KafkaConfigService.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.service;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.kylin.rest.constant.Constant;
-import org.apache.kylin.rest.exception.InternalErrorException;
-import org.apache.kylin.source.kafka.config.KafkaConfig;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PostFilter;
-import org.springframework.stereotype.Component;
-
-@Component("kafkaMgmtService")
-public class KafkaConfigService extends BasicService {
-
-    @Autowired
-    private AccessService accessService;
-
-    @PostFilter(Constant.ACCESS_POST_FILTER_READ)
-    public List<KafkaConfig> listAllKafkaConfigs(final String kafkaConfigName) throws IOException {
-        List<KafkaConfig> kafkaConfigs = new ArrayList<KafkaConfig>();
-        //        CubeInstance cubeInstance = (null != cubeName) ? getCubeManager().getCube(cubeName) : null;
-        if (null == kafkaConfigName) {
-            kafkaConfigs = getKafkaManager().listAllKafkaConfigs();
-        } else {
-            List<KafkaConfig> configs = getKafkaManager().listAllKafkaConfigs();
-            for (KafkaConfig config : configs) {
-                if (kafkaConfigName.equals(config.getName())) {
-                    kafkaConfigs.add(config);
-                }
-            }
-        }
-
-        return kafkaConfigs;
-    }
-
-    public List<KafkaConfig> getKafkaConfigs(final String kafkaConfigName, final Integer limit, final Integer offset) throws IOException {
-
-        List<KafkaConfig> kafkaConfigs;
-        kafkaConfigs = listAllKafkaConfigs(kafkaConfigName);
-
-        if (limit == null || offset == null) {
-            return kafkaConfigs;
-        }
-
-        if ((kafkaConfigs.size() - offset) < limit) {
-            return kafkaConfigs.subList(offset, kafkaConfigs.size());
-        }
-
-        return kafkaConfigs.subList(offset, offset + limit);
-    }
-
-    public KafkaConfig createKafkaConfig(KafkaConfig config) throws IOException {
-        if (getKafkaManager().getKafkaConfig(config.getName()) != null) {
-            throw new InternalErrorException("The kafkaConfig named " + config.getName() + " already exists");
-        }
-        getKafkaManager().createKafkaConfig(config.getName(), config);
-        return config;
-    }
-
-    //    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
-    public KafkaConfig updateKafkaConfig(KafkaConfig config) throws IOException {
-        return getKafkaManager().updateKafkaConfig(config);
-    }
-
-    public KafkaConfig getKafkaConfig(String configName) throws IOException {
-        return getKafkaManager().getKafkaConfig(configName);
-    }
-
-    //    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
-    public void dropKafkaConfig(KafkaConfig config) throws IOException {
-        getKafkaManager().removeKafkaConfig(config);
-    }
-}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
deleted file mode 100644
index 9d8ccfb..0000000
--- a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.apache.kylin.rest.service;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.kylin.cube.model.CubeDesc;
-import org.apache.kylin.engine.mr.HadoopUtil;
-import org.apache.kylin.invertedindex.model.IIDesc;
-import org.apache.kylin.metadata.model.DataModelDesc;
-import org.apache.kylin.metadata.project.ProjectInstance;
-import org.apache.kylin.rest.constant.Constant;
-import org.apache.kylin.rest.exception.InternalErrorException;
-import org.apache.kylin.rest.security.AclPermission;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PostFilter;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.stereotype.Component;
-
-/**
- * @author jiazhong
- */
-@Component("modelMgmtService")
-public class ModelService extends BasicService {
-
-    @Autowired
-    private AccessService accessService;
-
-    @PostFilter(Constant.ACCESS_POST_FILTER_READ)
-    public List<DataModelDesc> listAllModels(final String modelName, final String projectName) throws IOException {
-        List<DataModelDesc> models = null;
-        ProjectInstance project = (null != projectName) ? getProjectManager().getProject(projectName) : null;
-
-        if (null == project) {
-            models = getMetadataManager().getModels();
-        } else {
-            models = getMetadataManager().getModels(projectName);
-            project.getModels();
-        }
-
-        List<DataModelDesc> filterModels = new ArrayList<DataModelDesc>();
-        for (DataModelDesc modelDesc : models) {
-            boolean isModelMatch = (null == modelName) || modelDesc.getName().toLowerCase().contains(modelName.toLowerCase());
-
-            if (isModelMatch) {
-                filterModels.add(modelDesc);
-            }
-        }
-
-        return filterModels;
-    }
-
-    public List<DataModelDesc> getModels(final String modelName, final String projectName, final Integer limit, final Integer offset) throws IOException {
-
-        List<DataModelDesc> modelDescs;
-        modelDescs = listAllModels(modelName, projectName);
-
-        if (limit == null || offset == null) {
-            return modelDescs;
-        }
-
-        if ((modelDescs.size() - offset) < limit) {
-            return modelDescs.subList(offset, modelDescs.size());
-        }
-
-        return modelDescs.subList(offset, offset + limit);
-    }
-
-    public DataModelDesc createModelDesc(String projectName, DataModelDesc desc) throws IOException {
-        if (getMetadataManager().getDataModelDesc(desc.getName()) != null) {
-            throw new InternalErrorException("The model named " + desc.getName() + " already exists");
-        }
-        DataModelDesc createdDesc = null;
-        String owner = SecurityContextHolder.getContext().getAuthentication().getName();
-        createdDesc = getMetadataManager().createDataModelDesc(desc, projectName, owner);
-
-        accessService.init(createdDesc, AclPermission.ADMINISTRATION);
-        ProjectInstance project = getProjectManager().getProject(projectName);
-        accessService.inherit(createdDesc, project);
-        return createdDesc;
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
-    public DataModelDesc updateModelAndDesc(DataModelDesc desc) throws IOException {
-
-        getMetadataManager().updateDataModelDesc(desc);
-        return desc;
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
-    public void dropModel(DataModelDesc desc) throws IOException {
-
-        //check cube desc exist
-        List<CubeDesc> cubeDescs = getCubeDescManager().listAllDesc();
-        for (CubeDesc cubeDesc : cubeDescs) {
-            if (cubeDesc.getModelName().equals(desc.getName())) {
-                throw new InternalErrorException("Model referenced by cube,drop cubes under model and try again.");
-            }
-        }
-
-        //check II desc exist
-        List<IIDesc> iiDescs = getIIDescManager().listAllDesc();
-        for (IIDesc iidesc : iiDescs) {
-            if (iidesc.getModelName().equals(desc.getName())) {
-                throw new InternalErrorException("Model referenced by IIDesc.");
-            }
-        }
-
-        getMetadataManager().dropModel(desc);
-
-        accessService.clean(desc, true);
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
-    public boolean isTableInAnyModel(String tableName) {
-        String[] dbTableName = HadoopUtil.parseHiveTableName(tableName);
-        tableName = dbTableName[0] + "." + dbTableName[1];
-        return getMetadataManager().isTableInAnyModel(tableName);
-    }
-
-    @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#desc, 'ADMINISTRATION') or hasPermission(#desc, 'MANAGEMENT')")
-    public boolean isTableInModel(String tableName, String projectName) throws IOException {
-        String[] dbTableName = HadoopUtil.parseHiveTableName(tableName);
-        tableName = dbTableName[0] + "." + dbTableName[1];
-        return getMetadataManager().isTableInModel(tableName, projectName);
-    }
-}


[12/13] kylin git commit: KYLIN-1823 split code from kylin-server into kylin-server-base

Posted by li...@apache.org.
http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java
new file mode 100644
index 0000000..9315a20
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/controller/CubeController.java
@@ -0,0 +1,615 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.controller;
+
+import java.io.IOException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.kylin.common.util.JsonUtil;
+import org.apache.kylin.cube.CubeInstance;
+import org.apache.kylin.cube.CubeSegment;
+import org.apache.kylin.cube.model.CubeBuildTypeEnum;
+import org.apache.kylin.cube.model.CubeDesc;
+import org.apache.kylin.cube.model.CubeJoinedFlatTableDesc;
+import org.apache.kylin.dimension.DimensionEncodingFactory;
+import org.apache.kylin.engine.streaming.StreamingConfig;
+import org.apache.kylin.job.JobInstance;
+import org.apache.kylin.job.JoinedFlatTable;
+import org.apache.kylin.metadata.model.SegmentStatusEnum;
+import org.apache.kylin.metadata.project.ProjectInstance;
+import org.apache.kylin.rest.exception.BadRequestException;
+import org.apache.kylin.rest.exception.ForbiddenException;
+import org.apache.kylin.rest.exception.InternalErrorException;
+import org.apache.kylin.rest.exception.NotFoundException;
+import org.apache.kylin.rest.request.CubeRequest;
+import org.apache.kylin.rest.request.JobBuildRequest;
+import org.apache.kylin.rest.request.JobBuildRequest2;
+import org.apache.kylin.rest.response.GeneralResponse;
+import org.apache.kylin.rest.response.HBaseResponse;
+import org.apache.kylin.rest.service.CubeService;
+import org.apache.kylin.rest.service.JobService;
+import org.apache.kylin.rest.service.KafkaConfigService;
+import org.apache.kylin.rest.service.StreamingService;
+import org.apache.kylin.source.kafka.config.KafkaConfig;
+import org.apache.kylin.storage.hbase.cube.v1.coprocessor.observer.ObserverEnabler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+
+import com.google.common.collect.Sets;
+
+/**
+ * CubeController is defined as Restful API entrance for UI.
+ */
+@Controller
+@RequestMapping(value = "/cubes")
+public class CubeController extends BasicController {
+    private static final Logger logger = LoggerFactory.getLogger(CubeController.class);
+
+    @Autowired
+    private StreamingService streamingService;
+
+    @Autowired
+    private KafkaConfigService kafkaConfigService;
+
+    @Autowired
+    private CubeService cubeService;
+
+    @Autowired
+    private JobService jobService;
+
+    @RequestMapping(value = "", method = { RequestMethod.GET })
+    @ResponseBody
+    public List<CubeInstance> getCubes(@RequestParam(value = "cubeName", required = false) String cubeName, @RequestParam(value = "modelName", required = false) String modelName, @RequestParam(value = "projectName", required = false) String projectName, @RequestParam(value = "limit", required = false) Integer limit, @RequestParam(value = "offset", required = false) Integer offset) {
+        return cubeService.getCubes(cubeName, projectName, modelName, limit, offset);
+    }
+
+    @RequestMapping(value = "validEncodings", method = { RequestMethod.GET })
+    @ResponseBody
+    public Set<String> getValidEncodings() {
+        Set<String> encodings;
+        try {
+            encodings = DimensionEncodingFactory.getValidEncodings();
+        } catch (Exception e) {
+            return Sets.newTreeSet();
+        }
+        return encodings;
+    }
+
+    @RequestMapping(value = "/{cubeName}", method = { RequestMethod.GET })
+    @ResponseBody
+    public CubeInstance getCube(@PathVariable String cubeName) {
+        CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
+        if (cube == null) {
+            throw new InternalErrorException("Cannot find cube " + cubeName);
+        }
+        return cube;
+    }
+
+    /**
+     * Get hive SQL of the cube
+     *
+     * @param cubeName Cube Name
+     * @return
+     * @throws UnknownHostException
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{cubeName}/segs/{segmentName}/sql", method = { RequestMethod.GET })
+    @ResponseBody
+    public GeneralResponse getSql(@PathVariable String cubeName, @PathVariable String segmentName) {
+        CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
+        CubeDesc cubeDesc = cube.getDescriptor();
+        CubeSegment cubeSegment = cube.getSegment(segmentName, SegmentStatusEnum.READY);
+        CubeJoinedFlatTableDesc flatTableDesc = new CubeJoinedFlatTableDesc(cubeDesc, cubeSegment);
+        String sql = JoinedFlatTable.generateSelectDataStatement(flatTableDesc);
+
+        GeneralResponse repsonse = new GeneralResponse();
+        repsonse.setProperty("sql", sql);
+
+        return repsonse;
+    }
+
+    /**
+     * Update cube notify list
+     *
+     * @param cubeName
+     * @param notifyList
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{cubeName}/notify_list", method = { RequestMethod.PUT })
+    @ResponseBody
+    public void updateNotifyList(@PathVariable String cubeName, @RequestBody List<String> notifyList) {
+        CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
+
+        if (cube == null) {
+            throw new InternalErrorException("Cannot find cube " + cubeName);
+        }
+
+        try {
+            cubeService.updateCubeNotifyList(cube, notifyList);
+        } catch (Exception e) {
+            logger.error(e.getLocalizedMessage(), e);
+            throw new InternalErrorException(e.getLocalizedMessage());
+        }
+
+    }
+
+    @RequestMapping(value = "/{cubeName}/cost", method = { RequestMethod.PUT })
+    @ResponseBody
+    public CubeInstance updateCubeCost(@PathVariable String cubeName, @RequestParam(value = "cost") int cost) {
+        try {
+            return cubeService.updateCubeCost(cubeName, cost);
+        } catch (Exception e) {
+            String message = "Failed to update cube cost: " + cubeName + " : " + cost;
+            logger.error(message, e);
+            throw new InternalErrorException(message + " Caused by: " + e.getMessage(), e);
+        }
+    }
+
+    @RequestMapping(value = "/{cubeName}/coprocessor", method = { RequestMethod.PUT })
+    @ResponseBody
+    public Map<String, Boolean> updateCubeCoprocessor(@PathVariable String cubeName, @RequestParam(value = "force") String force) {
+        try {
+            ObserverEnabler.updateCubeOverride(cubeName, force);
+            return ObserverEnabler.getCubeOverrides();
+        } catch (Exception e) {
+            String message = "Failed to update cube coprocessor: " + cubeName + " : " + force;
+            logger.error(message, e);
+            throw new InternalErrorException(message + " Caused by: " + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * Force rebuild a cube's lookup table snapshot
+     *
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{cubeName}/segs/{segmentName}/refresh_lookup", method = { RequestMethod.PUT })
+    @ResponseBody
+    public CubeInstance rebuildLookupSnapshot(@PathVariable String cubeName, @PathVariable String segmentName, @RequestParam(value = "lookupTable") String lookupTable) {
+        try {
+            return cubeService.rebuildLookupSnapshot(cubeName, segmentName, lookupTable);
+        } catch (IOException e) {
+            logger.error(e.getLocalizedMessage(), e);
+            throw new InternalErrorException(e.getLocalizedMessage());
+        }
+    }
+
+    /**
+     * Delete a cube segment
+     *
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{cubeName}/segs/{segmentName}", method = { RequestMethod.DELETE })
+    @ResponseBody
+    public CubeInstance deleteSegment(@PathVariable String cubeName, @PathVariable String segmentName) {
+        CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
+
+        if (cube == null) {
+            throw new InternalErrorException("Cannot find cube " + cubeName);
+        }
+
+        CubeSegment segment = cube.getSegment(segmentName, null);
+        if (segment == null) {
+            throw new InternalErrorException("Cannot find segment '" + segmentName + "'");
+        }
+
+        try {
+            return cubeService.deleteSegment(cube, segmentName);
+        } catch (Exception e) {
+            logger.error(e.getLocalizedMessage(), e);
+            throw new InternalErrorException(e.getLocalizedMessage());
+        }
+    }
+
+    /** Build/Rebuild a cube segment */
+    @RequestMapping(value = "/{cubeName}/build", method = { RequestMethod.PUT })
+    @ResponseBody
+    public JobInstance build(@PathVariable String cubeName, @RequestBody JobBuildRequest req) {
+        return rebuild(cubeName, req);
+    }
+
+    /** Build/Rebuild a cube segment */
+    @RequestMapping(value = "/{cubeName}/rebuild", method = { RequestMethod.PUT })
+    @ResponseBody
+    public JobInstance rebuild(@PathVariable String cubeName, @RequestBody JobBuildRequest req) {
+        return buildInternal(cubeName, req.getStartTime(), req.getEndTime(), 0, 0, req.getBuildType(), req.isForce() || req.isForceMergeEmptySegment());
+    }
+
+    /** Build/Rebuild a cube segment by source offset */
+    @RequestMapping(value = "/{cubeName}/build2", method = { RequestMethod.PUT })
+    @ResponseBody
+    public JobInstance build(@PathVariable String cubeName, @RequestBody JobBuildRequest2 req) {
+        return rebuild(cubeName, req);
+    }
+
+    /** Build/Rebuild a cube segment by source offset */
+    @RequestMapping(value = "/{cubeName}/rebuild2", method = { RequestMethod.PUT })
+    @ResponseBody
+    public JobInstance rebuild(@PathVariable String cubeName, @RequestBody JobBuildRequest2 req) {
+        return buildInternal(cubeName, 0, 0, req.getStartSourceOffset(), req.getEndSourceOffset(), req.getBuildType(), req.isForce());
+    }
+
+    private JobInstance buildInternal(String cubeName, long startTime, long endTime, //
+            long startOffset, long endOffset, String buildType, boolean force) {
+        try {
+            String submitter = SecurityContextHolder.getContext().getAuthentication().getName();
+            CubeInstance cube = jobService.getCubeManager().getCube(cubeName);
+            return jobService.submitJob(cube, startTime, endTime, startOffset, endOffset, //
+                    CubeBuildTypeEnum.valueOf(buildType), force, submitter);
+        } catch (Exception e) {
+            logger.error(e.getLocalizedMessage(), e);
+            throw new InternalErrorException(e.getLocalizedMessage());
+        }
+    }
+
+    @RequestMapping(value = "/{cubeName}/disable", method = { RequestMethod.PUT })
+    @ResponseBody
+    public CubeInstance disableCube(@PathVariable String cubeName) {
+        try {
+            CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
+
+            if (cube == null) {
+                throw new InternalErrorException("Cannot find cube " + cubeName);
+            }
+
+            return cubeService.disableCube(cube);
+        } catch (Exception e) {
+            String message = "Failed to disable cube: " + cubeName;
+            logger.error(message, e);
+            throw new InternalErrorException(message + " Caused by: " + e.getMessage(), e);
+        }
+    }
+
+    @RequestMapping(value = "/{cubeName}/purge", method = { RequestMethod.PUT })
+    @ResponseBody
+    public CubeInstance purgeCube(@PathVariable String cubeName) {
+        try {
+            CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
+
+            if (cube == null) {
+                throw new InternalErrorException("Cannot find cube " + cubeName);
+            }
+
+            return cubeService.purgeCube(cube);
+        } catch (Exception e) {
+            String message = "Failed to purge cube: " + cubeName;
+            logger.error(message, e);
+            throw new InternalErrorException(message + " Caused by: " + e.getMessage(), e);
+        }
+    }
+
+    @RequestMapping(value = "/{cubeName}/clone", method = { RequestMethod.PUT })
+    @ResponseBody
+    public CubeInstance cloneCube(@PathVariable String cubeName, @RequestBody CubeRequest cubeRequest) {
+        String newCubeName = cubeRequest.getCubeName();
+        String project = cubeRequest.getProject();
+
+        CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
+        if (cube == null) {
+            throw new InternalErrorException("Cannot find cube " + cubeName);
+        }
+        CubeDesc cubeDesc = cube.getDescriptor();
+        CubeDesc newCubeDesc = CubeDesc.getCopyOf(cubeDesc);
+        newCubeDesc.setName(newCubeName);
+
+        CubeInstance newCube;
+        try {
+            newCube = cubeService.createCubeAndDesc(newCubeName, project, newCubeDesc);
+
+            //reload to avoid shallow clone
+            cubeService.getCubeDescManager().reloadCubeDescLocal(newCubeName);
+        } catch (IOException e) {
+            throw new InternalErrorException("Failed to clone cube ", e);
+        }
+
+        return newCube;
+
+    }
+
+    @RequestMapping(value = "/{cubeName}/enable", method = { RequestMethod.PUT })
+    @ResponseBody
+    public CubeInstance enableCube(@PathVariable String cubeName) {
+        try {
+            CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
+            if (null == cube) {
+                throw new InternalErrorException("Cannot find cube " + cubeName);
+            }
+
+            return cubeService.enableCube(cube);
+        } catch (Exception e) {
+            String message = "Failed to enable cube: " + cubeName;
+            logger.error(message, e);
+            throw new InternalErrorException(message + " Caused by: " + e.getMessage(), e);
+        }
+    }
+
+    @RequestMapping(value = "/{cubeName}", method = { RequestMethod.DELETE })
+    @ResponseBody
+    public void deleteCube(@PathVariable String cubeName) {
+        CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
+        if (null == cube) {
+            throw new NotFoundException("Cube with name " + cubeName + " not found..");
+        }
+
+        //drop Cube
+        try {
+            cubeService.deleteCube(cube);
+        } catch (Exception e) {
+            logger.error(e.getLocalizedMessage(), e);
+            throw new InternalErrorException("Failed to delete cube. " + " Caused by: " + e.getMessage(), e);
+        }
+
+    }
+
+    /**
+     * save cubeDesc
+     *
+     * @return Table metadata array
+     * @throws IOException
+     */
+    @RequestMapping(value = "", method = { RequestMethod.POST })
+    @ResponseBody
+    public CubeRequest saveCubeDesc(@RequestBody CubeRequest cubeRequest) {
+
+        CubeDesc desc = deserializeCubeDesc(cubeRequest);
+        if (desc == null) {
+            cubeRequest.setMessage("CubeDesc is null.");
+            return cubeRequest;
+        }
+        String name = CubeService.getCubeNameFromDesc(desc.getName());
+        if (StringUtils.isEmpty(name)) {
+            logger.info("Cube name should not be empty.");
+            throw new BadRequestException("Cube name should not be empty.");
+        }
+
+        try {
+            desc.setUuid(UUID.randomUUID().toString());
+            String projectName = (null == cubeRequest.getProject()) ? ProjectInstance.DEFAULT_PROJECT_NAME : cubeRequest.getProject();
+            cubeService.createCubeAndDesc(name, projectName, desc);
+        } catch (Exception e) {
+            logger.error("Failed to deal with the request.", e);
+            throw new InternalErrorException(e.getLocalizedMessage(), e);
+        }
+
+        cubeRequest.setUuid(desc.getUuid());
+        cubeRequest.setSuccessful(true);
+        return cubeRequest;
+    }
+
+    /**
+     * update CubDesc
+     *
+     * @return Table metadata array
+     * @throws JsonProcessingException
+     * @throws IOException
+     */
+    @RequestMapping(value = "", method = { RequestMethod.PUT })
+    @ResponseBody
+    public CubeRequest updateCubeDesc(@RequestBody CubeRequest cubeRequest) throws JsonProcessingException {
+
+        //update cube
+        CubeDesc desc = deserializeCubeDesc(cubeRequest);
+        CubeDesc oldCubeDesc;
+        boolean isCubeDescFreeEditable;
+
+        if (desc == null) {
+            return cubeRequest;
+        }
+
+        // Check if the cube is editable
+        isCubeDescFreeEditable = cubeService.isCubeDescFreeEditable(desc);
+
+        String projectName = (null == cubeRequest.getProject()) ? ProjectInstance.DEFAULT_PROJECT_NAME : cubeRequest.getProject();
+        try {
+            CubeInstance cube = cubeService.getCubeManager().getCube(cubeRequest.getCubeName());
+
+            if (cube == null) {
+                String error = "The cube named " + cubeRequest.getCubeName() + " does not exist ";
+                updateRequest(cubeRequest, false, error);
+                return cubeRequest;
+            }
+
+            //cube renaming is not allowed
+            if (!cube.getDescriptor().getName().equalsIgnoreCase(desc.getName())) {
+                String error = "Cube Desc renaming is not allowed: desc.getName(): " + desc.getName() + ", cubeRequest.getCubeName(): " + cubeRequest.getCubeName();
+                updateRequest(cubeRequest, false, error);
+                return cubeRequest;
+            }
+
+            oldCubeDesc = cube.getDescriptor();
+            if (isCubeDescFreeEditable || oldCubeDesc.consistentWith(desc)) {
+                desc = cubeService.updateCubeAndDesc(cube, desc, projectName, true);
+            } else {
+                logger.warn("Won't update the cube desc due to inconsistency");
+                updateRequest(cubeRequest, false, "CubeDesc " + desc.getName() + " is inconsistent with existing. Try purge that cube first or avoid updating key cube desc fields.");
+                return cubeRequest;
+            }
+        } catch (AccessDeniedException accessDeniedException) {
+            throw new ForbiddenException("You don't have right to update this cube.");
+        } catch (Exception e) {
+            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
+            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
+        }
+
+        if (!desc.getError().isEmpty()) {
+            logger.warn("Cube " + desc.getName() + " fail to update because " + desc.getError());
+            updateRequest(cubeRequest, false, omitMessage(desc.getError()));
+            return cubeRequest;
+        }
+
+        String descData = JsonUtil.writeValueAsIndentString(desc);
+        cubeRequest.setCubeDescData(descData);
+        cubeRequest.setSuccessful(true);
+        return cubeRequest;
+    }
+
+    /**
+     * get Hbase Info
+     *
+     * @return true
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{cubeName}/hbase", method = { RequestMethod.GET })
+    @ResponseBody
+    public List<HBaseResponse> getHBaseInfo(@PathVariable String cubeName) {
+        List<HBaseResponse> hbase = new ArrayList<HBaseResponse>();
+
+        CubeInstance cube = cubeService.getCubeManager().getCube(cubeName);
+        if (null == cube) {
+            throw new InternalErrorException("Cannot find cube " + cubeName);
+        }
+
+        List<CubeSegment> segments = cube.getSegments();
+
+        for (CubeSegment segment : segments) {
+            String tableName = segment.getStorageLocationIdentifier();
+            HBaseResponse hr = null;
+
+            // Get info of given table.
+            try {
+                hr = cubeService.getHTableInfo(tableName);
+            } catch (IOException e) {
+                logger.error("Failed to calcuate size of HTable \"" + tableName + "\".", e);
+            }
+
+            if (null == hr) {
+                logger.info("Failed to calcuate size of HTable \"" + tableName + "\".");
+                hr = new HBaseResponse();
+            }
+
+            hr.setTableName(tableName);
+            hr.setDateRangeStart(segment.getDateRangeStart());
+            hr.setDateRangeEnd(segment.getDateRangeEnd());
+            hbase.add(hr);
+        }
+
+        return hbase;
+    }
+
+    private CubeDesc deserializeCubeDesc(CubeRequest cubeRequest) {
+        CubeDesc desc = null;
+        try {
+            logger.debug("Saving cube " + cubeRequest.getCubeDescData());
+            desc = JsonUtil.readValue(cubeRequest.getCubeDescData(), CubeDesc.class);
+        } catch (JsonParseException e) {
+            logger.error("The cube definition is not valid.", e);
+            updateRequest(cubeRequest, false, e.getMessage());
+        } catch (JsonMappingException e) {
+            logger.error("The cube definition is not valid.", e);
+            updateRequest(cubeRequest, false, e.getMessage());
+        } catch (IOException e) {
+            logger.error("Failed to deal with the request.", e);
+            throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
+        }
+        return desc;
+    }
+
+    private StreamingConfig deserializeStreamingDesc(CubeRequest cubeRequest) {
+        StreamingConfig desc = null;
+        try {
+            logger.debug("Saving StreamingConfig " + cubeRequest.getStreamingData());
+            desc = JsonUtil.readValue(cubeRequest.getStreamingData(), StreamingConfig.class);
+        } catch (JsonParseException e) {
+            logger.error("The StreamingConfig definition is not valid.", e);
+            updateRequest(cubeRequest, false, e.getMessage());
+        } catch (JsonMappingException e) {
+            logger.error("The data StreamingConfig definition is not valid.", e);
+            updateRequest(cubeRequest, false, e.getMessage());
+        } catch (IOException e) {
+            logger.error("Failed to deal with the request.", e);
+            throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
+        }
+        return desc;
+    }
+
+    private KafkaConfig deserializeKafkaDesc(CubeRequest cubeRequest) {
+        KafkaConfig desc = null;
+        try {
+            logger.debug("Saving KafkaConfig " + cubeRequest.getKafkaData());
+            desc = JsonUtil.readValue(cubeRequest.getKafkaData(), KafkaConfig.class);
+        } catch (JsonParseException e) {
+            logger.error("The KafkaConfig definition is not valid.", e);
+            updateRequest(cubeRequest, false, e.getMessage());
+        } catch (JsonMappingException e) {
+            logger.error("The data KafkaConfig definition is not valid.", e);
+            updateRequest(cubeRequest, false, e.getMessage());
+        } catch (IOException e) {
+            logger.error("Failed to deal with the request.", e);
+            throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
+        }
+        return desc;
+    }
+
+    /**
+     * @return
+     */
+    private String omitMessage(List<String> errors) {
+        StringBuffer buffer = new StringBuffer();
+        for (Iterator<String> iterator = errors.iterator(); iterator.hasNext();) {
+            String string = (String) iterator.next();
+            buffer.append(string);
+            buffer.append("\n");
+        }
+        return buffer.toString();
+    }
+
+    private void updateRequest(CubeRequest request, boolean success, String message) {
+        request.setCubeDescData("");
+        request.setSuccessful(success);
+        request.setMessage(message);
+    }
+
+    public void setCubeService(CubeService cubeService) {
+        this.cubeService = cubeService;
+    }
+
+    public void setJobService(JobService jobService) {
+        this.jobService = jobService;
+    }
+
+    public void setStreamingService(StreamingService streamingService) {
+        this.streamingService = streamingService;
+    }
+
+    public void setKafkaConfigService(KafkaConfigService kafkaConfigService) {
+        this.kafkaConfigService = kafkaConfigService;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/controller/CubeDescController.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/CubeDescController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/CubeDescController.java
new file mode 100644
index 0000000..61584a3
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/controller/CubeDescController.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.controller;
+
+import java.io.IOException;
+
+import org.apache.kylin.cube.CubeInstance;
+import org.apache.kylin.cube.model.CubeDesc;
+import org.apache.kylin.rest.service.CubeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+/**
+ * @author xduo
+ * 
+ */
+@Controller
+@RequestMapping(value = "/cube_desc")
+public class CubeDescController {
+
+    @Autowired
+    private CubeService cubeService;
+
+    /**
+     * Get detail information of the "Cube ID"
+     * 
+     * @param cubeDescName
+     *            Cube ID
+     * @return
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{cubeName}", method = { RequestMethod.GET })
+    @ResponseBody
+    public CubeDesc[] getCube(@PathVariable String cubeName) {
+        CubeInstance cubeInstance = cubeService.getCubeManager().getCube(cubeName);
+        if (cubeInstance == null) {
+            return null;
+        }
+        CubeDesc cSchema = cubeInstance.getDescriptor();
+        if (cSchema != null) {
+            return new CubeDesc[] { cSchema };
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Get detail information of the "Cube ID"
+     * return CubeDesc instead of CubeDesc[]
+     *
+     * @param cubeDescName
+     *            Cube ID
+     * @return
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{cubeName}/desc", method = { RequestMethod.GET })
+    @ResponseBody
+    public CubeDesc getDesc(@PathVariable String cubeName) {
+        CubeInstance cubeInstance = cubeService.getCubeManager().getCube(cubeName);
+        if (cubeInstance == null) {
+            return null;
+        }
+        CubeDesc cSchema = cubeInstance.getDescriptor();
+        if (cSchema != null) {
+            return cSchema;
+        } else {
+            return null;
+        }
+    }
+
+    public void setCubeService(CubeService cubeService) {
+        this.cubeService = cubeService;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/controller/DiagnosisController.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/DiagnosisController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/DiagnosisController.java
new file mode 100644
index 0000000..b9da9b2
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/controller/DiagnosisController.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.controller;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.kylin.metadata.badquery.BadQueryEntry;
+import org.apache.kylin.metadata.badquery.BadQueryHistory;
+import org.apache.kylin.rest.exception.InternalErrorException;
+import org.apache.kylin.rest.service.DiagnosisService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.google.common.collect.Lists;
+
+@Controller
+@RequestMapping(value = "/diag")
+public class DiagnosisController {
+
+    private static final Logger logger = LoggerFactory.getLogger(DiagnosisController.class);
+
+    @Autowired
+    private DiagnosisService dgService;
+
+    /**
+     * Get bad query history
+     */
+    @RequestMapping(value = "/{project}/sql", method = { RequestMethod.GET })
+    @ResponseBody
+    public List<BadQueryEntry> getBadQuerySql(@PathVariable String project) {
+
+        List<BadQueryEntry> badEntry = Lists.newArrayList();
+        try {
+            BadQueryHistory badQueryHistory = dgService.getProjectBadQueryHistory(project);
+            badEntry.addAll(badQueryHistory.getEntries());
+        } catch (IOException e) {
+            throw new InternalErrorException(e + " Caused by: " + e.getMessage(), e);
+        }
+
+        return badEntry;
+    }
+
+    /**
+     * Get diagnosis information for project
+     */
+    @RequestMapping(value = "/project/{project}/download", method = { RequestMethod.GET })
+    @ResponseBody
+    public void dumpProjectDiagnosisInfo(@PathVariable String project, final HttpServletRequest request, final HttpServletResponse response) {
+        String filePath;
+        try {
+            filePath = dgService.dumpProjectDiagnosisInfo(project);
+        } catch (IOException e) {
+            throw new InternalErrorException(e + " Caused by: " + e.getMessage(), e);
+        }
+
+        setDownloadResponse(filePath, response);
+    }
+
+    /**
+     * Get diagnosis information for job
+     */
+    @RequestMapping(value = "/job/{jobId}/download", method = { RequestMethod.GET })
+    @ResponseBody
+    public void dumpJobDiagnosisInfo(@PathVariable String jobId, final HttpServletRequest request, final HttpServletResponse response) {
+        String filePath;
+        try {
+            filePath = dgService.dumpJobDiagnosisInfo(jobId);
+        } catch (IOException e) {
+            throw new InternalErrorException(e + " Caused by: " + e.getMessage(), e);
+        }
+
+        setDownloadResponse(filePath, response);
+    }
+
+    private void setDownloadResponse(String downloadFile, final HttpServletResponse response) {
+        File file = new File(downloadFile);
+        try (InputStream fileInputStream = new FileInputStream(file); OutputStream output = response.getOutputStream();) {
+            response.reset();
+            response.setContentType("application/octet-stream");
+            response.setContentLength((int) (file.length()));
+            response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
+            IOUtils.copyLarge(fileInputStream, output);
+            output.flush();
+        } catch (IOException e) {
+            throw new InternalErrorException(e + " Caused by: " + e.getMessage(), e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/controller/ExternalFilterController.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/ExternalFilterController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/ExternalFilterController.java
new file mode 100644
index 0000000..7baa639
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/controller/ExternalFilterController.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.controller;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.kylin.common.util.JsonUtil;
+import org.apache.kylin.metadata.model.ExternalFilterDesc;
+import org.apache.kylin.rest.request.ExternalFilterRequest;
+import org.apache.kylin.rest.service.ExtFilterService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.google.common.collect.Lists;
+
+/**
+ * @author jiazhong
+ */
+@Controller
+@RequestMapping(value = "/extFilter")
+public class ExternalFilterController extends BasicController {
+    private static final Logger logger = LoggerFactory.getLogger(ExternalFilterController.class);
+
+    @Autowired
+    private ExtFilterService extFilterService;
+
+    @RequestMapping(value = "/saveExtFilter", method = { RequestMethod.POST })
+    @ResponseBody
+    public Map<String, String> saveExternalFilter(@RequestBody ExternalFilterRequest request) throws IOException {
+        Map<String, String> result = new HashMap();
+        String filterProject = request.getProject();
+        ExternalFilterDesc desc = JsonUtil.readValue(request.getExtFilter(), ExternalFilterDesc.class);
+        desc.setUuid(UUID.randomUUID().toString());
+        extFilterService.saveExternalFilter(desc);
+        extFilterService.syncExtFilterToProject(new String[] { desc.getName() }, filterProject);
+        result.put("success", "true");
+        return result;
+    }
+
+    @RequestMapping(value = "/updateExtFilter", method = { RequestMethod.PUT })
+    @ResponseBody
+    public Map<String, String> updateExternalFilter(@RequestBody ExternalFilterRequest request) throws IOException {
+        Map<String, String> result = new HashMap();
+        ExternalFilterDesc desc = JsonUtil.readValue(request.getExtFilter(), ExternalFilterDesc.class);
+        extFilterService.updateExternalFilter(desc);
+        extFilterService.syncExtFilterToProject(new String[] { desc.getName() }, request.getProject());
+        result.put("success", "true");
+        return result;
+    }
+
+    @RequestMapping(value = "/{filter}/{project}", method = { RequestMethod.DELETE })
+    @ResponseBody
+    public Map<String, String> removeFilter(@PathVariable String filter, @PathVariable String project) throws IOException {
+        Map<String, String> result = new HashMap<String, String>();
+        extFilterService.removeExtFilterFromProject(filter, project);
+        extFilterService.removeExternalFilter(filter);
+        result.put("success", "true");
+        return result;
+    }
+
+    @RequestMapping(value = "", method = { RequestMethod.GET })
+    @ResponseBody
+    public List<ExternalFilterDesc> getExternalFilters(@RequestParam(value = "project", required = true) String project) throws IOException {
+        List<ExternalFilterDesc> filterDescs = Lists.newArrayList();
+        filterDescs.addAll(extFilterService.getProjectManager().listExternalFilterDescs(project).values());
+        return filterDescs;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/controller/JobController.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/JobController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/JobController.java
new file mode 100644
index 0000000..dce3847
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/controller/JobController.java
@@ -0,0 +1,221 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.controller;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.util.ClassUtil;
+import org.apache.kylin.job.JobInstance;
+import org.apache.kylin.job.Scheduler;
+import org.apache.kylin.job.SchedulerFactory;
+import org.apache.kylin.job.constant.JobStatusEnum;
+import org.apache.kylin.job.constant.JobTimeFilterEnum;
+import org.apache.kylin.job.engine.JobEngineConfig;
+import org.apache.kylin.job.exception.SchedulerException;
+import org.apache.kylin.job.execution.AbstractExecutable;
+import org.apache.kylin.job.lock.JobLock;
+import org.apache.kylin.rest.exception.InternalErrorException;
+import org.apache.kylin.rest.request.JobListRequest;
+import org.apache.kylin.rest.service.JobService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+/**
+ *
+ */
+@Controller
+@RequestMapping(value = "jobs")
+public class JobController extends BasicController implements InitializingBean {
+    private static final Logger logger = LoggerFactory.getLogger(JobController.class);
+
+    @Autowired
+    private JobService jobService;
+
+    private JobLock jobLock;
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public void afterPropertiesSet() throws Exception {
+
+        String timeZone = jobService.getConfig().getTimeZone();
+        TimeZone tzone = TimeZone.getTimeZone(timeZone);
+        TimeZone.setDefault(tzone);
+
+        final KylinConfig kylinConfig = KylinConfig.getInstanceFromEnv();
+        final Scheduler<AbstractExecutable> scheduler = (Scheduler<AbstractExecutable>) SchedulerFactory.scheduler(kylinConfig.getSchedulerType());
+
+        jobLock = (JobLock) ClassUtil.newInstance(kylinConfig.getJobControllerLock());
+
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    scheduler.init(new JobEngineConfig(kylinConfig), jobLock);
+                    while (!scheduler.hasStarted()) {
+                        logger.error("scheduler has not been started");
+                        Thread.sleep(1000);
+                    }
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }).start();
+
+        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    scheduler.shutdown();
+                } catch (SchedulerException e) {
+                    logger.error("error occurred to shutdown scheduler", e);
+                }
+            }
+        }));
+    }
+
+    /**
+     * get all cube jobs
+     * 
+     * @return
+     * @throws IOException
+     */
+    @RequestMapping(value = "", method = { RequestMethod.GET })
+    @ResponseBody
+    public List<JobInstance> list(JobListRequest jobRequest) {
+
+        List<JobInstance> jobInstanceList = Collections.emptyList();
+        List<JobStatusEnum> statusList = new ArrayList<JobStatusEnum>();
+
+        if (null != jobRequest.getStatus()) {
+            for (int status : jobRequest.getStatus()) {
+                statusList.add(JobStatusEnum.getByCode(status));
+            }
+        }
+
+        JobTimeFilterEnum timeFilter = JobTimeFilterEnum.getByCode(jobRequest.getTimeFilter());
+
+        try {
+            jobInstanceList = jobService.listAllJobs(jobRequest.getCubeName(), jobRequest.getProjectName(), statusList, jobRequest.getLimit(), jobRequest.getOffset(), timeFilter);
+        } catch (Exception e) {
+            logger.error(e.getLocalizedMessage(), e);
+            throw new InternalErrorException(e);
+        }
+        return jobInstanceList;
+    }
+
+    /**
+     * Get a cube job
+     * 
+     * @return
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{jobId}", method = { RequestMethod.GET })
+    @ResponseBody
+    public JobInstance get(@PathVariable String jobId) {
+        JobInstance jobInstance = null;
+        try {
+            jobInstance = jobService.getJobInstance(jobId);
+        } catch (Exception e) {
+            logger.error(e.getLocalizedMessage(), e);
+            throw new InternalErrorException(e);
+        }
+
+        return jobInstance;
+    }
+
+    /**
+     * Get a job step output
+     * 
+     * @return
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{jobId}/steps/{stepId}/output", method = { RequestMethod.GET })
+    @ResponseBody
+    public Map<String, String> getStepOutput(@PathVariable String jobId, @PathVariable String stepId) {
+        Map<String, String> result = new HashMap<String, String>();
+        result.put("jobId", jobId);
+        result.put("stepId", String.valueOf(stepId));
+        result.put("cmd_output", jobService.getExecutableManager().getOutput(stepId).getVerboseMsg());
+        return result;
+    }
+
+    /**
+     * Resume a cube job
+     * 
+     * @return
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{jobId}/resume", method = { RequestMethod.PUT })
+    @ResponseBody
+    public JobInstance resume(@PathVariable String jobId) {
+        try {
+            final JobInstance jobInstance = jobService.getJobInstance(jobId);
+            jobService.resumeJob(jobInstance);
+            return jobService.getJobInstance(jobId);
+        } catch (Exception e) {
+            logger.error(e.getLocalizedMessage(), e);
+            throw new InternalErrorException(e);
+        }
+    }
+
+    /**
+     * Cancel a job
+     * 
+     * @return
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{jobId}/cancel", method = { RequestMethod.PUT })
+    @ResponseBody
+    public JobInstance cancel(@PathVariable String jobId) {
+
+        try {
+            final JobInstance jobInstance = jobService.getJobInstance(jobId);
+            return jobService.cancelJob(jobInstance);
+        } catch (Exception e) {
+            logger.error(e.getLocalizedMessage(), e);
+            throw new InternalErrorException(e);
+        }
+
+    }
+
+    public void setJobService(JobService jobService) {
+        this.jobService = jobService;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/controller/ModelController.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/ModelController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/ModelController.java
new file mode 100644
index 0000000..5f6a91b
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/controller/ModelController.java
@@ -0,0 +1,236 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.controller;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.util.JsonUtil;
+import org.apache.kylin.metadata.MetadataManager;
+import org.apache.kylin.metadata.model.DataModelDesc;
+import org.apache.kylin.metadata.project.ProjectInstance;
+import org.apache.kylin.rest.exception.BadRequestException;
+import org.apache.kylin.rest.exception.ForbiddenException;
+import org.apache.kylin.rest.exception.InternalErrorException;
+import org.apache.kylin.rest.exception.NotFoundException;
+import org.apache.kylin.rest.request.ModelRequest;
+import org.apache.kylin.rest.service.ModelService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+
+/**
+ * ModelController is defined as Restful API entrance for UI.
+ *
+ * @author jiazhong
+ */
+@Controller
+@RequestMapping(value = "/models")
+public class ModelController extends BasicController {
+    private static final Logger logger = LoggerFactory.getLogger(ModelController.class);
+
+    @Autowired
+    private ModelService modelService;
+
+    @RequestMapping(value = "", method = { RequestMethod.GET })
+    @ResponseBody
+    public List<DataModelDesc> getModels(@RequestParam(value = "modelName", required = false) String modelName, @RequestParam(value = "projectName", required = false) String projectName, @RequestParam(value = "limit", required = false) Integer limit, @RequestParam(value = "offset", required = false) Integer offset) {
+        try {
+            return modelService.getModels(modelName, projectName, limit, offset);
+        } catch (IOException e) {
+            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
+            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
+        }
+    }
+
+    /**
+     *
+     * create model
+     * @throws java.io.IOException
+     */
+    @RequestMapping(value = "", method = { RequestMethod.POST })
+    @ResponseBody
+    public ModelRequest saveModelDesc(@RequestBody ModelRequest modelRequest) {
+        //Update Model
+        DataModelDesc modelDesc = deserializeDataModelDesc(modelRequest);
+        if (modelDesc == null || StringUtils.isEmpty(modelDesc.getName())) {
+            return modelRequest;
+        }
+
+        if (StringUtils.isEmpty(modelDesc.getName())) {
+            logger.info("Model name should not be empty.");
+            throw new BadRequestException("Model name should not be empty.");
+        }
+
+        try {
+            modelDesc.setUuid(UUID.randomUUID().toString());
+            String projectName = (null == modelRequest.getProject()) ? ProjectInstance.DEFAULT_PROJECT_NAME : modelRequest.getProject();
+
+            modelService.createModelDesc(projectName, modelDesc);
+        } catch (IOException e) {
+            // TODO Auto-generated catch block
+            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
+            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
+        }
+
+        modelRequest.setUuid(modelDesc.getUuid());
+        modelRequest.setSuccessful(true);
+        return modelRequest;
+    }
+
+    @RequestMapping(value = "", method = { RequestMethod.PUT })
+    @ResponseBody
+    public ModelRequest updateModelDesc(@RequestBody ModelRequest modelRequest) throws JsonProcessingException {
+        DataModelDesc modelDesc = deserializeDataModelDesc(modelRequest);
+        if (modelDesc == null) {
+            return modelRequest;
+        }
+        try {
+            modelDesc = modelService.updateModelAndDesc(modelDesc);
+        } catch (AccessDeniedException accessDeniedException) {
+            throw new ForbiddenException("You don't have right to update this model.");
+        } catch (Exception e) {
+            logger.error("Failed to deal with the request:" + e.getLocalizedMessage(), e);
+            throw new InternalErrorException("Failed to deal with the request: " + e.getLocalizedMessage());
+        }
+
+        if (modelDesc.getError().isEmpty()) {
+            modelRequest.setSuccessful(true);
+        } else {
+            logger.warn("Model " + modelDesc.getName() + " fail to update because " + modelDesc.getError());
+            updateRequest(modelRequest, false, omitMessage(modelDesc.getError()));
+        }
+        String descData = JsonUtil.writeValueAsIndentString(modelDesc);
+        modelRequest.setModelDescData(descData);
+        return modelRequest;
+    }
+
+    @RequestMapping(value = "/{modelName}", method = { RequestMethod.DELETE })
+    @ResponseBody
+    public void deleteModel(@PathVariable String modelName) {
+        DataModelDesc desc = modelService.getMetadataManager().getDataModelDesc(modelName);
+        if (null == desc) {
+            throw new NotFoundException("Data Model with name " + modelName + " not found..");
+        }
+        try {
+            modelService.dropModel(desc);
+        } catch (Exception e) {
+            logger.error(e.getLocalizedMessage(), e);
+            throw new InternalErrorException("Failed to delete model. " + " Caused by: " + e.getMessage(), e);
+        }
+    }
+
+    @RequestMapping(value = "/{modelName}/clone", method = { RequestMethod.PUT })
+    @ResponseBody
+    public ModelRequest cloneModel(@PathVariable String modelName, @RequestBody ModelRequest modelRequest) {
+        String project = modelRequest.getProject();
+        MetadataManager metaManager = MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
+        DataModelDesc modelDesc = metaManager.getDataModelDesc(modelName);
+        String newModelName = modelRequest.getModelName();
+
+        if (StringUtils.isEmpty(project)) {
+            logger.info("Project name should not be empty.");
+            throw new BadRequestException("Project name should not be empty.");
+        }
+
+        if (modelDesc == null || StringUtils.isEmpty(modelName)) {
+            logger.info("Model does not exist.");
+            throw new BadRequestException("Model does not exist.");
+        }
+
+        if (StringUtils.isEmpty(newModelName)) {
+            logger.info("New model name is empty.");
+            throw new BadRequestException("New model name is empty.");
+        }
+
+        DataModelDesc newModelDesc = DataModelDesc.getCopyOf(modelDesc);
+        newModelDesc.setName(newModelName);
+        try {
+            newModelDesc = modelService.createModelDesc(project, newModelDesc);
+
+            //reload avoid shallow
+            metaManager.reloadDataModelDesc(newModelName);
+        } catch (IOException e) {
+            throw new InternalErrorException("failed to clone DataModelDesc", e);
+        }
+
+        modelRequest.setUuid(newModelDesc.getUuid());
+        modelRequest.setSuccessful(true);
+        return modelRequest;
+    }
+
+    private DataModelDesc deserializeDataModelDesc(ModelRequest modelRequest) {
+        DataModelDesc desc = null;
+        try {
+            logger.debug("Saving MODEL " + modelRequest.getModelDescData());
+            desc = JsonUtil.readValue(modelRequest.getModelDescData(), DataModelDesc.class);
+        } catch (JsonParseException e) {
+            logger.error("The data model definition is not valid.", e);
+            updateRequest(modelRequest, false, e.getMessage());
+        } catch (JsonMappingException e) {
+            logger.error("The data model definition is not valid.", e);
+            updateRequest(modelRequest, false, e.getMessage());
+        } catch (IOException e) {
+            logger.error("Failed to deal with the request.", e);
+            throw new InternalErrorException("Failed to deal with the request:" + e.getMessage(), e);
+        }
+        return desc;
+    }
+
+    private void updateRequest(ModelRequest request, boolean success, String message) {
+        request.setModelDescData("");
+        request.setSuccessful(success);
+        request.setMessage(message);
+    }
+
+    public void setModelService(ModelService modelService) {
+        this.modelService = modelService;
+    }
+
+    /**
+     * @param errors
+     * @return
+     */
+    private String omitMessage(List<String> errors) {
+        StringBuffer buffer = new StringBuffer();
+        for (Iterator<String> iterator = errors.iterator(); iterator.hasNext();) {
+            String string = (String) iterator.next();
+            buffer.append(string);
+            buffer.append("\n");
+        }
+        return buffer.toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/controller/ModelDescController.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/ModelDescController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/ModelDescController.java
new file mode 100644
index 0000000..4171afd
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/controller/ModelDescController.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.controller;
+
+import java.io.IOException;
+
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.metadata.MetadataManager;
+import org.apache.kylin.metadata.model.DataModelDesc;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+/**
+ * @author jiazhong
+ * 
+ */
+@Controller
+@RequestMapping(value = "/model")
+public class ModelDescController extends BasicController {
+
+    /**
+     * Get detail information of the "Model ID"
+     * 
+     * @param modelDescName
+     *            Model ID
+     * @return
+     * @throws IOException
+     */
+    @RequestMapping(value = "/{model_name}", method = { RequestMethod.GET })
+    @ResponseBody
+    public DataModelDesc getModel(@PathVariable String model_name) {
+        MetadataManager metaManager = MetadataManager.getInstance(KylinConfig.getInstanceFromEnv());
+        DataModelDesc modeDesc = metaManager.getDataModelDesc(model_name);
+        return modeDesc;
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/ProjectController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
new file mode 100644
index 0000000..f829fff
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/controller/ProjectController.java
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.controller;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.kylin.common.persistence.AclEntity;
+import org.apache.kylin.cube.CubeInstance;
+import org.apache.kylin.metadata.project.ProjectInstance;
+import org.apache.kylin.rest.constant.Constant;
+import org.apache.kylin.rest.exception.InternalErrorException;
+import org.apache.kylin.rest.request.CreateProjectRequest;
+import org.apache.kylin.rest.request.UpdateProjectRequest;
+import org.apache.kylin.rest.service.AccessService;
+import org.apache.kylin.rest.service.CubeService;
+import org.apache.kylin.rest.service.ProjectService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.acls.domain.GrantedAuthoritySid;
+import org.springframework.security.acls.domain.PrincipalSid;
+import org.springframework.security.acls.model.AccessControlEntry;
+import org.springframework.security.acls.model.Acl;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+/**
+ * @author xduo
+ */
+@Controller
+@RequestMapping(value = "/projects")
+public class ProjectController extends BasicController {
+    private static final Logger logger = LoggerFactory.getLogger(ProjectController.class);
+
+    @Autowired
+    private ProjectService projectService;
+    @Autowired
+    private AccessService accessService;
+    @Autowired
+    private CubeService cubeService;
+
+    /**
+     * Get available project list
+     *
+     * @return Table metadata array
+     * @throws IOException
+     */
+    @RequestMapping(value = "", method = { RequestMethod.GET })
+    @ResponseBody
+    public List<ProjectInstance> getProjects(@RequestParam(value = "limit", required = false) Integer limit, @RequestParam(value = "offset", required = false) Integer offset) {
+        return projectService.listAllProjects(limit, offset);
+    }
+
+    @RequestMapping(value = "/readable", method = { RequestMethod.GET })
+    @ResponseBody
+    public List<ProjectInstance> getReadableProjects(@RequestParam(value = "limit", required = false) Integer limit, @RequestParam(value = "offset", required = false) Integer offset) {
+        List<ProjectInstance> readableProjects = new ArrayList<ProjectInstance>();
+        //list all projects first
+        List<ProjectInstance> projectInstances = projectService.listAllProjects(limit, offset);
+
+        //get user infomation
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+        UserDetails userDetails = null;
+        if (authentication == null) {
+            logger.debug("authentication is null.");
+            throw new InternalErrorException("Can not find authentication infomation.");
+        }
+        if (authentication.getPrincipal() instanceof UserDetails) {
+            logger.debug("authentication.getPrincipal() is " + authentication.getPrincipal());
+            userDetails = (UserDetails) authentication.getPrincipal();
+        }
+        if (authentication.getDetails() instanceof UserDetails) {
+            logger.debug("authentication.getDetails() is " + authentication.getDetails());
+            userDetails = (UserDetails) authentication.getDetails();
+        }
+
+        //check if ROLE_ADMIN return all,also get user role list
+        List<String> userAuthority = new ArrayList<>();
+        for (GrantedAuthority auth : authentication.getAuthorities()) {
+            userAuthority.add(auth.getAuthority());
+            if (auth.getAuthority().equals(Constant.ROLE_ADMIN))
+                return projectInstances;
+        }
+        String userName = userDetails.getUsername();
+        for (ProjectInstance projectInstance : projectInstances) {
+            if (projectInstance == null) {
+                continue;
+            }
+
+            boolean hasProjectPermission = false;
+            AclEntity ae = accessService.getAclEntity("ProjectInstance", projectInstance.getId());
+            Acl projectAcl = accessService.getAcl(ae);
+            //project no Acl info will be skipped
+            if (projectAcl != null) {
+
+                //project owner has permission
+                if (((PrincipalSid) projectAcl.getOwner()).getPrincipal().equals(userName)) {
+                    readableProjects.add(projectInstance);
+                    continue;
+                }
+
+                //check project permission and role
+                for (AccessControlEntry ace : projectAcl.getEntries()) {
+                    if (ace.getSid() instanceof PrincipalSid && ((PrincipalSid) ace.getSid()).getPrincipal().equals(userName)) {
+                        hasProjectPermission = true;
+                        readableProjects.add(projectInstance);
+                        break;
+
+                    } else if (ace.getSid() instanceof GrantedAuthoritySid) {
+                        String projectAuthority = ((GrantedAuthoritySid) ace.getSid()).getGrantedAuthority();
+                        if (userAuthority.contains(projectAuthority)) {
+                            hasProjectPermission = true;
+                            readableProjects.add(projectInstance);
+                            break;
+                        }
+
+                    }
+
+                }
+            }
+
+            if (!hasProjectPermission) {
+                List<CubeInstance> cubeInstances = cubeService.listAllCubes(projectInstance.getName());
+
+                for (CubeInstance cubeInstance : cubeInstances) {
+                    if (cubeInstance == null) {
+                        continue;
+                    }
+                    boolean hasCubePermission = false;
+                    AclEntity cubeAe = accessService.getAclEntity("CubeInstance", cubeInstance.getId());
+                    Acl cubeAcl = accessService.getAcl(cubeAe);
+                    //cube no Acl info will not be used to filter project
+                    if (cubeAcl != null) {
+                        //cube owner will have permission to read project
+                        if (((PrincipalSid) cubeAcl.getOwner()).getPrincipal().equals(userName)) {
+                            hasProjectPermission = true;
+                            break;
+                        }
+                        for (AccessControlEntry cubeAce : cubeAcl.getEntries()) {
+
+                            if (cubeAce.getSid() instanceof PrincipalSid && ((PrincipalSid) cubeAce.getSid()).getPrincipal().equals(userName)) {
+                                hasCubePermission = true;
+                                break;
+                            } else if (cubeAce.getSid() instanceof GrantedAuthoritySid) {
+                                String cubeAuthority = ((GrantedAuthoritySid) cubeAce.getSid()).getGrantedAuthority();
+                                if (userAuthority.contains(cubeAuthority)) {
+                                    hasCubePermission = true;
+                                    break;
+                                }
+
+                            }
+                        }
+                    }
+                    if (hasCubePermission) {
+                        hasProjectPermission = true;
+                        break;
+                    }
+                }
+                if (hasProjectPermission) {
+                    readableProjects.add(projectInstance);
+                }
+            }
+
+        }
+        return readableProjects;
+    }
+
+    @RequestMapping(value = "", method = { RequestMethod.POST })
+    @ResponseBody
+    public ProjectInstance saveProject(@RequestBody CreateProjectRequest projectRequest) {
+        if (StringUtils.isEmpty(projectRequest.getName())) {
+            throw new InternalErrorException("A project name must be given to create a project");
+        }
+
+        ProjectInstance createdProj = null;
+        try {
+            createdProj = projectService.createProject(projectRequest);
+        } catch (Exception e) {
+            logger.error("Failed to deal with the request.", e);
+            throw new InternalErrorException(e.getLocalizedMessage());
+        }
+
+        return createdProj;
+    }
+
+    @RequestMapping(value = "", method = { RequestMethod.PUT })
+    @ResponseBody
+    public ProjectInstance updateProject(@RequestBody UpdateProjectRequest projectRequest) {
+        if (StringUtils.isEmpty(projectRequest.getFormerProjectName())) {
+            throw new InternalErrorException("A project name must be given to update a project");
+        }
+
+        ProjectInstance updatedProj = null;
+        try {
+            ProjectInstance currentProject = projectService.getProjectManager().getProject(projectRequest.getFormerProjectName());
+            updatedProj = projectService.updateProject(projectRequest, currentProject);
+        } catch (Exception e) {
+            logger.error("Failed to deal with the request.", e);
+            throw new InternalErrorException(e.getLocalizedMessage());
+        }
+
+        return updatedProj;
+    }
+
+    @RequestMapping(value = "/{projectName}", method = { RequestMethod.DELETE })
+    @ResponseBody
+    public void deleteProject(@PathVariable String projectName) {
+        try {
+
+            ProjectInstance project = projectService.getProjectManager().getProject(projectName);
+            projectService.deleteProject(projectName, project);
+        } catch (Exception e) {
+            logger.error(e.getLocalizedMessage(), e);
+            throw new InternalErrorException("Failed to delete project. " + " Caused by: " + e.getMessage(), e);
+        }
+    }
+
+    public void setProjectService(ProjectService projectService) {
+        this.projectService = projectService;
+    }
+
+    public void setAccessService(AccessService accessService) {
+        this.accessService = accessService;
+    }
+
+    public void setCubeService(CubeService cubeService) {
+        this.cubeService = cubeService;
+    }
+}

http://git-wip-us.apache.org/repos/asf/kylin/blob/1a124e68/server-base/src/main/java/org/apache/kylin/rest/controller/QueryController.java
----------------------------------------------------------------------
diff --git a/server-base/src/main/java/org/apache/kylin/rest/controller/QueryController.java b/server-base/src/main/java/org/apache/kylin/rest/controller/QueryController.java
new file mode 100644
index 0000000..93b71ad
--- /dev/null
+++ b/server-base/src/main/java/org/apache/kylin/rest/controller/QueryController.java
@@ -0,0 +1,270 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.kylin.rest.controller;
+
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.kylin.common.KylinConfig;
+import org.apache.kylin.common.debug.BackdoorToggles;
+import org.apache.kylin.cube.CubeInstance;
+import org.apache.kylin.rest.constant.Constant;
+import org.apache.kylin.rest.exception.InternalErrorException;
+import org.apache.kylin.rest.model.Query;
+import org.apache.kylin.rest.model.SelectedColumnMeta;
+import org.apache.kylin.rest.model.TableMeta;
+import org.apache.kylin.rest.request.MetaRequest;
+import org.apache.kylin.rest.request.PrepareSqlRequest;
+import org.apache.kylin.rest.request.SQLRequest;
+import org.apache.kylin.rest.request.SaveSqlRequest;
+import org.apache.kylin.rest.response.SQLResponse;
+import org.apache.kylin.rest.service.QueryService;
+import org.apache.kylin.rest.util.QueryUtil;
+import org.apache.kylin.storage.exception.ScanOutOfLimitException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.supercsv.io.CsvListWriter;
+import org.supercsv.io.ICsvListWriter;
+import org.supercsv.prefs.CsvPreference;
+
+import com.google.common.base.Preconditions;
+
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheManager;
+import net.sf.ehcache.Element;
+
+/**
+ * Handle query requests.
+ * 
+ * @author xduo
+ */
+@Controller
+public class QueryController extends BasicController {
+
+    private static final Logger logger = LoggerFactory.getLogger(QueryController.class);
+
+    public static final String SUCCESS_QUERY_CACHE = "StorageCache";
+    public static final String EXCEPTION_QUERY_CACHE = "ExceptionQueryCache";
+
+    @Autowired
+    private QueryService queryService;
+
+    @Autowired
+    private CacheManager cacheManager;
+
+    @PostConstruct
+    public void init() throws IOException {
+        Preconditions.checkNotNull(cacheManager, "cacheManager is not injected yet");
+    }
+
+    @RequestMapping(value = "/query", method = RequestMethod.POST)
+    @ResponseBody
+    public SQLResponse query(@RequestBody SQLRequest sqlRequest) {
+        return doQueryWithCache(sqlRequest);
+    }
+
+    // TODO should be just "prepare" a statement, get back expected ResultSetMetaData
+    @RequestMapping(value = "/query/prestate", method = RequestMethod.POST, produces = "application/json")
+    @ResponseBody
+    public SQLResponse prepareQuery(@RequestBody PrepareSqlRequest sqlRequest) {
+        return doQueryWithCache(sqlRequest);
+    }
+
+    @RequestMapping(value = "/saved_queries", method = RequestMethod.POST)
+    @ResponseBody
+    public void saveQuery(@RequestBody SaveSqlRequest sqlRequest) throws IOException {
+        String creator = SecurityContextHolder.getContext().getAuthentication().getName();
+        Query newQuery = new Query(sqlRequest.getName(), sqlRequest.getProject(), sqlRequest.getSql(), sqlRequest.getDescription());
+
+        queryService.saveQuery(creator, newQuery);
+    }
+
+    @RequestMapping(value = "/saved_queries/{id}", method = RequestMethod.DELETE)
+    @ResponseBody
+    public void removeQuery(@PathVariable String id) throws IOException {
+        String creator = SecurityContextHolder.getContext().getAuthentication().getName();
+        queryService.removeQuery(creator, id);
+    }
+
+    @RequestMapping(value = "/saved_queries", method = RequestMethod.GET)
+    @ResponseBody
+    public List<Query> getQueries() throws IOException {
+        String creator = SecurityContextHolder.getContext().getAuthentication().getName();
+        return queryService.getQueries(creator);
+    }
+
+    @RequestMapping(value = "/query/format/{format}", method = RequestMethod.GET)
+    @ResponseBody
+    public void downloadQueryResult(@PathVariable String format, SQLRequest sqlRequest, HttpServletResponse response) {
+        SQLResponse result = doQueryWithCache(sqlRequest);
+        response.setContentType("text/" + format + ";charset=utf-8");
+        response.setHeader("Content-Disposition", "attachment; filename=\"result." + format + "\"");
+        ICsvListWriter csvWriter = null;
+
+        try {
+            csvWriter = new CsvListWriter(response.getWriter(), CsvPreference.STANDARD_PREFERENCE);
+
+            List<String> headerList = new ArrayList<String>();
+
+            for (SelectedColumnMeta column : result.getColumnMetas()) {
+                headerList.add(column.getName());
+            }
+
+            String[] headers = new String[headerList.size()];
+            csvWriter.writeHeader(headerList.toArray(headers));
+
+            for (List<String> row : result.getResults()) {
+                csvWriter.write(row);
+            }
+        } catch (IOException e) {
+            logger.error("", e);
+        } finally {
+            IOUtils.closeQuietly(csvWriter);
+        }
+    }
+
+    @RequestMapping(value = "/tables_and_columns", method = RequestMethod.GET)
+    @ResponseBody
+    public List<TableMeta> getMetadata(MetaRequest metaRequest) {
+        try {
+            return queryService.getMetadata(metaRequest.getProject());
+        } catch (SQLException e) {
+            logger.error(e.getLocalizedMessage(), e);
+            throw new InternalErrorException(e.getLocalizedMessage(), e);
+        }
+    }
+
+    private SQLResponse doQueryWithCache(SQLRequest sqlRequest) {
+        try {
+            BackdoorToggles.setToggles(sqlRequest.getBackdoorToggles());
+
+            String sql = sqlRequest.getSql();
+            String project = sqlRequest.getProject();
+            logger.info("Using project: " + project);
+            logger.info("The original query:  " + sql);
+
+            String serverMode = KylinConfig.getInstanceFromEnv().getServerMode();
+            if (!(Constant.SERVER_MODE_QUERY.equals(serverMode.toLowerCase()) || Constant.SERVER_MODE_ALL.equals(serverMode.toLowerCase()))) {
+                throw new InternalErrorException("Query is not allowed in " + serverMode + " mode.");
+            }
+
+            if (!sql.toLowerCase().contains("select")) {
+                logger.debug("Directly return exception as not supported");
+                throw new InternalErrorException("Not Supported SQL.");
+            }
+
+            long startTime = System.currentTimeMillis();
+
+            SQLResponse sqlResponse = searchQueryInCache(sqlRequest);
+            try {
+                if (null == sqlResponse) {
+                    sqlResponse = queryService.query(sqlRequest);
+
+                    long durationThreshold = KylinConfig.getInstanceFromEnv().getQueryDurationCacheThreshold();
+                    long scancountThreshold = KylinConfig.getInstanceFromEnv().getQueryScanCountCacheThreshold();
+                    sqlResponse.setDuration(System.currentTimeMillis() - startTime);
+                    logger.info("Stats of SQL response: isException: {}, duration: {}, total scan count {}", //
+                            new String[] { String.valueOf(sqlResponse.getIsException()), String.valueOf(sqlResponse.getDuration()), String.valueOf(sqlResponse.getTotalScanCount()) });
+                    if (!sqlResponse.getIsException() && (sqlResponse.getDuration() > durationThreshold || sqlResponse.getTotalScanCount() > scancountThreshold)) {
+                        cacheManager.getCache(SUCCESS_QUERY_CACHE).put(new Element(sqlRequest, sqlResponse));
+                    }
+                } else {
+                    sqlResponse.setDuration(System.currentTimeMillis() - startTime);
+                }
+
+                checkQueryAuth(sqlResponse);
+
+            } catch (Throwable e) { // calcite may throw AssertError
+                logger.error("Exception when execute sql", e);
+                String errMsg = QueryUtil.makeErrorMsgUserFriendly(e);
+
+                sqlResponse = new SQLResponse(null, null, 0, true, errMsg);
+
+                // for exception queries, only cache ScanOutOfLimitException
+                if (e instanceof ScanOutOfLimitException) {
+                    Cache exceptionCache = cacheManager.getCache(EXCEPTION_QUERY_CACHE);
+                    exceptionCache.put(new Element(sqlRequest, sqlResponse));
+                }
+            }
+
+            queryService.logQuery(sqlRequest, sqlResponse);
+
+            if (sqlResponse.getIsException())
+                throw new InternalErrorException(sqlResponse.getExceptionMessage());
+
+            return sqlResponse;
+
+        } finally {
+            BackdoorToggles.cleanToggles();
+        }
+    }
+
+    private SQLResponse searchQueryInCache(SQLRequest sqlRequest) {
+        SQLResponse response = null;
+        Cache exceptionCache = cacheManager.getCache(EXCEPTION_QUERY_CACHE);
+        Cache successCache = cacheManager.getCache(SUCCESS_QUERY_CACHE);
+
+        if (KylinConfig.getInstanceFromEnv().isQueryCacheEnabled() && !BackdoorToggles.getDisableCache()) {
+            if (exceptionCache.get(sqlRequest) != null) {
+                logger.info("The sqlResponse is found in EXCEPTION_QUERY_CACHE");
+                Element element = exceptionCache.get(sqlRequest);
+                response = (SQLResponse) element.getObjectValue();
+                response.setHitExceptionCache(true);
+            } else if (successCache.get(sqlRequest) != null) {
+                logger.info("The sqlResponse is found in SUCCESS_QUERY_CACHE");
+                Element element = successCache.get(sqlRequest);
+                response = (SQLResponse) element.getObjectValue();
+                response.setStorageCacheUsed(true);
+            }
+        }
+
+        return response;
+    }
+
+    private void checkQueryAuth(SQLResponse sqlResponse) throws AccessDeniedException {
+        if (!sqlResponse.getIsException() && KylinConfig.getInstanceFromEnv().isQuerySecureEnabled()) {
+            CubeInstance cubeInstance = this.queryService.getCubeManager().getCube(sqlResponse.getCube());
+            queryService.checkAuthorization(cubeInstance);
+        }
+    }
+
+    public void setQueryService(QueryService queryService) {
+        this.queryService = queryService;
+    }
+
+    public void setCacheManager(CacheManager cacheManager) {
+        this.cacheManager = cacheManager;
+    }
+
+}