org.waarp.openr66.protocol.http.rest.HttpRestR66Handler.java Source code

Java tutorial

Introduction

Here is the source code for org.waarp.openr66.protocol.http.rest.HttpRestR66Handler.java

Source

/**
 * This file is part of Waarp Project (named also Waarp or GG).
 * 
 * Copyright 2009, Frederic Bregier, and individual contributors by the @author
 * tags. See the COPYRIGHT.txt in the distribution for a full listing of
 * individual contributors.
 * 
 * All Waarp Project is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 * 
 * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * Waarp . If not, see <http://www.gnu.org/licenses/>.
 */
package org.waarp.openr66.protocol.http.rest;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpResponseStatus;

import org.waarp.common.command.exception.Reply421Exception;
import org.waarp.common.command.exception.Reply530Exception;
import org.waarp.common.database.DbSession;
import org.waarp.common.database.exception.WaarpDatabaseException;
import org.waarp.common.database.exception.WaarpDatabaseNoConnectionException;
import org.waarp.common.digest.FilesystemBasedDigest;
import org.waarp.common.logging.WaarpLogger;
import org.waarp.common.logging.WaarpLoggerFactory;
import org.waarp.common.utility.WaarpNettyUtil;
import org.waarp.common.utility.WaarpStringUtils;
import org.waarp.gateway.kernel.exception.HttpInvalidAuthenticationException;
import org.waarp.gateway.kernel.rest.HttpRestHandler;
import org.waarp.gateway.kernel.rest.RestConfiguration;
import org.waarp.openr66.context.R66Session;
import org.waarp.openr66.database.DbConstant;
import org.waarp.openr66.database.data.DbHostAuth;
import org.waarp.openr66.protocol.configuration.Configuration;
import org.waarp.openr66.protocol.http.rest.handler.DbConfigurationR66RestMethodHandler;
import org.waarp.openr66.protocol.http.rest.handler.DbHostAuthR66RestMethodHandler;
import org.waarp.openr66.protocol.http.rest.handler.DbHostConfigurationR66RestMethodHandler;
import org.waarp.openr66.protocol.http.rest.handler.DbRuleR66RestMethodHandler;
import org.waarp.openr66.protocol.http.rest.handler.DbTaskRunnerR66RestMethodHandler;
import org.waarp.openr66.protocol.http.rest.handler.HttpRestBandwidthR66Handler;
import org.waarp.openr66.protocol.http.rest.handler.HttpRestBusinessR66Handler;
import org.waarp.openr66.protocol.http.rest.handler.HttpRestConfigR66Handler;
import org.waarp.openr66.protocol.http.rest.handler.HttpRestInformationR66Handler;
import org.waarp.openr66.protocol.http.rest.handler.HttpRestLogR66Handler;
import org.waarp.openr66.protocol.http.rest.handler.HttpRestServerR66Handler;
import org.waarp.openr66.protocol.http.rest.handler.HttpRestControlR66Handler;
import org.waarp.openr66.protocol.localhandler.ServerActions;

/**
 * Handler for Rest HTTP support for R66
 * 
 * @author Frederic Bregier
 * 
 */
public class HttpRestR66Handler extends HttpRestHandler {

    /**
     * Internal Logger
     */
    private static final WaarpLogger logger = WaarpLoggerFactory.getLogger(HttpRestR66Handler.class);

    private static HashMap<String, DbSession> dbSessionFromUser = new HashMap<String, DbSession>();

    public static enum RESTHANDLERS {
        DbHostAuth(DbHostAuthR66RestMethodHandler.BASEURI,
                org.waarp.openr66.database.data.DbHostAuth.class), DbRule(DbRuleR66RestMethodHandler.BASEURI,
                        org.waarp.openr66.database.data.DbRule.class), DbTaskRunner(
                                DbTaskRunnerR66RestMethodHandler.BASEURI,
                                org.waarp.openr66.database.data.DbTaskRunner.class), DbHostConfiguration(
                                        DbHostConfigurationR66RestMethodHandler.BASEURI,
                                        org.waarp.openr66.database.data.DbHostConfiguration.class), DbConfiguration(
                                                DbConfigurationR66RestMethodHandler.BASEURI,
                                                org.waarp.openr66.database.data.DbConfiguration.class), Bandwidth(
                                                        HttpRestBandwidthR66Handler.BASEURI,
                                                        null), Business(HttpRestBusinessR66Handler.BASEURI,
                                                                null), Config(HttpRestConfigR66Handler.BASEURI,
                                                                        null), Information(
                                                                                HttpRestInformationR66Handler.BASEURI,
                                                                                null), Log(
                                                                                        HttpRestLogR66Handler.BASEURI,
                                                                                        null), Server(
                                                                                                HttpRestServerR66Handler.BASEURI,
                                                                                                null), Control(
                                                                                                        HttpRestControlR66Handler.BASEURI,
                                                                                                        null);

        public String uri;
        @SuppressWarnings("rawtypes")
        public Class clasz;

        @SuppressWarnings("rawtypes")
        RESTHANDLERS(String uri, Class clasz) {
            this.uri = uri;
            this.clasz = clasz;
        }

        public static RESTHANDLERS getRESTHANDLER(String baseUri) {
            for (RESTHANDLERS resthandler : RESTHANDLERS.values()) {
                if (resthandler.uri.equals(baseUri)) {
                    return resthandler;
                }
            }
            return null;
        }
    }

    /**
     * To be called once to ensure default is built
     */
    public static void defaultHandlers() {
        synchronized (defaultConfiguration) {
            if (defaultConfiguration.restHashMap.isEmpty()) {
                defaultConfiguration.REST_AUTHENTICATED = true;
                defaultConfiguration.RESTHANDLERS_CRUD = new byte[RESTHANDLERS.values().length];
                for (int i = 0; i < defaultConfiguration.RESTHANDLERS_CRUD.length; i++) {
                    defaultConfiguration.RESTHANDLERS_CRUD[i] = 0x0F;
                }
                METHOD[] methods = METHOD.values();
                defaultConfiguration.restHashMap.put(RESTHANDLERS.DbTaskRunner.uri,
                        new DbTaskRunnerR66RestMethodHandler(defaultConfiguration, methods));
                defaultConfiguration.restHashMap.put(RESTHANDLERS.DbHostAuth.uri,
                        new DbHostAuthR66RestMethodHandler(defaultConfiguration, methods));
                defaultConfiguration.restHashMap.put(RESTHANDLERS.DbRule.uri,
                        new DbRuleR66RestMethodHandler(defaultConfiguration, methods));
                defaultConfiguration.restHashMap.put(RESTHANDLERS.DbHostConfiguration.uri,
                        new DbHostConfigurationR66RestMethodHandler(defaultConfiguration, methods));
                defaultConfiguration.restHashMap.put(RESTHANDLERS.DbConfiguration.uri,
                        new DbConfigurationR66RestMethodHandler(defaultConfiguration, methods));
                defaultConfiguration.restHashMap.put(RESTHANDLERS.Bandwidth.uri,
                        new HttpRestBandwidthR66Handler(defaultConfiguration, methods));
                defaultConfiguration.restHashMap.put(RESTHANDLERS.Business.uri,
                        new HttpRestBusinessR66Handler(defaultConfiguration, methods));
                defaultConfiguration.restHashMap.put(RESTHANDLERS.Config.uri,
                        new HttpRestConfigR66Handler(defaultConfiguration, methods));
                defaultConfiguration.restHashMap.put(RESTHANDLERS.Information.uri,
                        new HttpRestInformationR66Handler(defaultConfiguration, methods));
                defaultConfiguration.restHashMap.put(RESTHANDLERS.Log.uri,
                        new HttpRestLogR66Handler(defaultConfiguration, methods));
                defaultConfiguration.restHashMap.put(RESTHANDLERS.Server.uri,
                        new HttpRestServerR66Handler(defaultConfiguration, methods));
                defaultConfiguration.restHashMap.put(RESTHANDLERS.Control.uri,
                        new HttpRestControlR66Handler(defaultConfiguration, methods));
            }
        }
    }

    public HttpRestR66Handler(RestConfiguration config) {
        super(config);
        restHashMap = config.restHashMap;
    }

    protected static METHOD[] getMethods(byte check) {
        List<METHOD> methods = new ArrayList<METHOD>();
        if (RestConfiguration.CRUD.CREATE.isValid(check)) {
            methods.add(METHOD.POST);
        }
        if (RestConfiguration.CRUD.READ.isValid(check)) {
            methods.add(METHOD.GET);
        }
        if (RestConfiguration.CRUD.UPDATE.isValid(check)) {
            methods.add(METHOD.PUT);
        }
        if (RestConfiguration.CRUD.DELETE.isValid(check)) {
            methods.add(METHOD.DELETE);
        }
        return methods.toArray(new METHOD[0]);
    }

    public static void instantiateHandlers(RestConfiguration restConfiguration) {
        defaultHandlers();
        byte check = restConfiguration.RESTHANDLERS_CRUD[RESTHANDLERS.DbTaskRunner.ordinal()];
        if (check != 0) {
            METHOD[] methods = getMethods(check);
            restConfiguration.restHashMap.put(RESTHANDLERS.DbTaskRunner.uri,
                    new DbTaskRunnerR66RestMethodHandler(restConfiguration, methods));
        }
        check = restConfiguration.RESTHANDLERS_CRUD[RESTHANDLERS.DbHostAuth.ordinal()];
        if (check != 0) {
            METHOD[] methods = getMethods(check);
            restConfiguration.restHashMap.put(RESTHANDLERS.DbHostAuth.uri,
                    new DbHostAuthR66RestMethodHandler(restConfiguration, methods));
        }
        check = restConfiguration.RESTHANDLERS_CRUD[RESTHANDLERS.DbRule.ordinal()];
        if (check != 0) {
            METHOD[] methods = getMethods(check);
            restConfiguration.restHashMap.put(RESTHANDLERS.DbRule.uri,
                    new DbRuleR66RestMethodHandler(restConfiguration, methods));
        }
        check = restConfiguration.RESTHANDLERS_CRUD[RESTHANDLERS.DbHostConfiguration.ordinal()];
        if (check != 0) {
            METHOD[] methods = getMethods(check);
            restConfiguration.restHashMap.put(RESTHANDLERS.DbHostConfiguration.uri,
                    new DbHostConfigurationR66RestMethodHandler(restConfiguration, methods));
        }
        check = restConfiguration.RESTHANDLERS_CRUD[RESTHANDLERS.DbConfiguration.ordinal()];
        if (check != 0) {
            METHOD[] methods = getMethods(check);
            restConfiguration.restHashMap.put(RESTHANDLERS.DbConfiguration.uri,
                    new DbConfigurationR66RestMethodHandler(restConfiguration, methods));
        }
        check = restConfiguration.RESTHANDLERS_CRUD[RESTHANDLERS.Bandwidth.ordinal()];
        if (check != 0) {
            METHOD[] methods = getMethods(check);
            restConfiguration.restHashMap.put(RESTHANDLERS.Bandwidth.uri,
                    new HttpRestBandwidthR66Handler(restConfiguration, methods));
        }
        check = restConfiguration.RESTHANDLERS_CRUD[RESTHANDLERS.Business.ordinal()];
        if (check != 0) {
            METHOD[] methods = getMethods(check);
            restConfiguration.restHashMap.put(RESTHANDLERS.Business.uri,
                    new HttpRestBusinessR66Handler(restConfiguration, methods));
        }
        check = restConfiguration.RESTHANDLERS_CRUD[RESTHANDLERS.Config.ordinal()];
        if (check != 0) {
            METHOD[] methods = getMethods(check);
            restConfiguration.restHashMap.put(RESTHANDLERS.Config.uri,
                    new HttpRestConfigR66Handler(restConfiguration, methods));
        }
        check = restConfiguration.RESTHANDLERS_CRUD[RESTHANDLERS.Information.ordinal()];
        if (check != 0) {
            METHOD[] methods = getMethods(check);
            restConfiguration.restHashMap.put(RESTHANDLERS.Information.uri,
                    new HttpRestInformationR66Handler(restConfiguration, methods));
        }
        check = restConfiguration.RESTHANDLERS_CRUD[RESTHANDLERS.Log.ordinal()];
        if (check != 0) {
            METHOD[] methods = getMethods(check);
            restConfiguration.restHashMap.put(RESTHANDLERS.Log.uri,
                    new HttpRestLogR66Handler(restConfiguration, methods));
        }
        check = restConfiguration.RESTHANDLERS_CRUD[RESTHANDLERS.Server.ordinal()];
        if (check != 0) {
            METHOD[] methods = getMethods(check);
            restConfiguration.restHashMap.put(RESTHANDLERS.Server.uri,
                    new HttpRestServerR66Handler(restConfiguration, methods));
        }
        check = restConfiguration.RESTHANDLERS_CRUD[RESTHANDLERS.Control.ordinal()];
        if (check != 0) {
            METHOD[] methods = getMethods(check);
            restConfiguration.restHashMap.put(RESTHANDLERS.Control.uri,
                    new HttpRestControlR66Handler(restConfiguration, methods));
        }
        logger.debug("Initialized handler: " + RESTHANDLERS.values().length);
    }

    /**
     * Server Actions handler
     */
    private ServerActions serverHandler = new ServerActions();

    @Override
    protected void checkConnection(ChannelHandlerContext ctx) throws HttpInvalidAuthenticationException {
        logger.debug("Request: {} ### {}", arguments, response);
        String user = null;
        String key = null;
        if (restConfiguration.REST_AUTHENTICATED) {
            user = arguments.getXAuthUser();
            if (user == null || user.isEmpty()) {
                status = HttpResponseStatus.UNAUTHORIZED;
                throw new HttpInvalidAuthenticationException("Empty Authentication");
            }
            DbHostAuth host;
            try {
                host = new DbHostAuth(DbConstant.admin.getSession(), user);
                key = new String(host.getHostkey(), WaarpStringUtils.UTF8);
            } catch (WaarpDatabaseException e) {
                // might be global Admin
                if (user.equals(Configuration.configuration.getADMINNAME())) {
                    key = new String(Configuration.configuration.getSERVERADMINKEY(), WaarpStringUtils.UTF8);
                }
            }
            if (key == null || key.isEmpty()) {
                status = HttpResponseStatus.UNAUTHORIZED;
                throw new HttpInvalidAuthenticationException("Wrong Authentication");
            }
            if (restConfiguration.REST_SIGNATURE) {
                arguments.checkBaseAuthent(restConfiguration.hmacSha256, key, restConfiguration.REST_TIME_LIMIT);
            } else {
                arguments.checkTime(restConfiguration.REST_TIME_LIMIT);
            }
        } else {
            // User set only for right access, not for signature check
            user = Configuration.configuration.getADMINNAME();
            if (restConfiguration.REST_SIGNATURE) {
                arguments.checkBaseAuthent(restConfiguration.hmacSha256, null, restConfiguration.REST_TIME_LIMIT);
            } else {
                arguments.checkTime(restConfiguration.REST_TIME_LIMIT);
            }
        }
        getServerHandler().newSession();
        R66Session session = getServerHandler().getSession();
        if (!restConfiguration.REST_AUTHENTICATED) {
            // Default is Admin
            session.getAuth().specialNoSessionAuth(true, Configuration.configuration.getHOST_SSLID());
        } else {
            // we have one DbSession per connection, only after authentication
            DbSession temp = getDbSessionFromUser().get(user);
            if (temp == null) {
                try {
                    temp = new DbSession(DbConstant.admin, false);
                    getDbSessionFromUser().put(user, temp);
                } catch (WaarpDatabaseNoConnectionException e) {
                }
            }
            if (temp != null) {
                temp.useConnection();
                this.dbSession = temp;
            }
            try {
                session.getAuth().connectionHttps(getDbSession(), user,
                        FilesystemBasedDigest.passwdCrypt(key.getBytes(WaarpStringUtils.UTF8)));
            } catch (Reply530Exception e) {
                status = HttpResponseStatus.UNAUTHORIZED;
                throw new HttpInvalidAuthenticationException("Wrong Authentication", e);
            } catch (Reply421Exception e) {
                status = HttpResponseStatus.SERVICE_UNAVAILABLE;
                throw new HttpInvalidAuthenticationException("Service unavailable", e);
            }
        }
        arguments.setXAuthRole(session.getAuth().getRole());
        arguments.methodFromUri();
        arguments.methodFromHeader();
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        getServerHandler().channelClosed(ctx);
    }

    /**
     * Called at the beginning of every new request
     * 
     * Override if needed
     */
    protected void initialize() {
        super.initialize();
    }

    /**
     * Initialize the REST service (server side) for one restConfiguration
     * 
     * @param restConfiguration
     */
    public static void initializeService(RestConfiguration restConfiguration) {
        instantiateHandlers(restConfiguration);
        if (group == null) {
            group = Configuration.configuration.getHttpChannelGroup();
        }
        // Configure the server.
        ServerBootstrap httpBootstrap = new ServerBootstrap();
        WaarpNettyUtil.setServerBootstrap(httpBootstrap, Configuration.configuration.getHttpBossGroup(),
                Configuration.configuration.getHttpWorkerGroup(),
                (int) Configuration.configuration.getTIMEOUTCON());
        // Set up the event pipeline factory.
        if (restConfiguration.REST_SSL) {
            httpBootstrap.childHandler(new HttpRestR66Initializer(false, Configuration.getWaarpSslContextFactory(),
                    restConfiguration));
        } else {
            httpBootstrap.childHandler(new HttpRestR66Initializer(false, null, restConfiguration));
        }
        // Bind and start to accept incoming connections.
        ChannelFuture future;
        if (restConfiguration != null && restConfiguration.REST_ADDRESS != null
                && !restConfiguration.REST_ADDRESS.isEmpty()) {
            future = httpBootstrap
                    .bind(new InetSocketAddress(restConfiguration.REST_ADDRESS, restConfiguration.REST_PORT));
        } else {
            future = httpBootstrap.bind(new InetSocketAddress(restConfiguration.REST_PORT));
        }
        try {
            future.await();
        } catch (InterruptedException e) {
        }
        if (future.isSuccess()) {
            group.add(future.channel());
        }
    }

    /**
     * @return the dbSessionFromUser
     */
    public static HashMap<String, DbSession> getDbSessionFromUser() {
        return dbSessionFromUser;
    }

    /**
     * @return the serverHandler
     */
    public ServerActions getServerHandler() {
        return serverHandler;
    }
}