au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.RigManagement.java Source code

Java tutorial

Introduction

Here is the source code for au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.RigManagement.java

Source

/**
 * SAHARA Scheduling Server
 *
 * Schedules and assigns local laboratory rigs.
 *
 * @license See LICENSE in the top level directory for complete license terms.
 *
 * Copyright (c) 2009 - 2011, University of Technology, Sydney
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice, 
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright 
 *    notice, this list of conditions and the following disclaimer in the 
 *    documentation and/or other materials provided with the distribution.
 *  * Neither the name of the University of Technology, Sydney nor the names 
 *    of its contributors may be used to endorse or promote products derived from 
 *    this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author Michael Diponio (mdiponio)
 * @date 29th January 2011
 */

package au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

import au.edu.uts.eng.remotelabs.schedserver.bookings.BookingEngineService;
import au.edu.uts.eng.remotelabs.schedserver.dataaccess.DataAccessActivator;
import au.edu.uts.eng.remotelabs.schedserver.dataaccess.dao.RigDao;
import au.edu.uts.eng.remotelabs.schedserver.dataaccess.dao.RigLogDao;
import au.edu.uts.eng.remotelabs.schedserver.dataaccess.dao.RigOfflineScheduleDao;
import au.edu.uts.eng.remotelabs.schedserver.dataaccess.dao.RigTypeDao;
import au.edu.uts.eng.remotelabs.schedserver.dataaccess.dao.UserDao;
import au.edu.uts.eng.remotelabs.schedserver.dataaccess.entities.Rig;
import au.edu.uts.eng.remotelabs.schedserver.dataaccess.entities.RigLog;
import au.edu.uts.eng.remotelabs.schedserver.dataaccess.entities.RigOfflineSchedule;
import au.edu.uts.eng.remotelabs.schedserver.dataaccess.entities.User;
import au.edu.uts.eng.remotelabs.schedserver.logger.Logger;
import au.edu.uts.eng.remotelabs.schedserver.logger.LoggerActivator;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.RigManagementActivator;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.CancelRigOffline;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.CancelRigOfflineResponse;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.CancelRigOfflineType;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.FreeRig;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.FreeRigResponse;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.GetRig;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.GetRigResponse;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.GetTypeStatus;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.GetTypeStatusResponse;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.GetTypes;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.GetTypesResponse;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.KickRigType;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.OfflinePeriodType;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.OperationRequestType;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.OperationResponseType;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.PutRigOffline;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.PutRigOfflineResponse;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.PutRigOfflineType;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.RigLogType;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.RigStateType;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.RigType;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.RigTypeIDType;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.RigTypeType;
import au.edu.uts.eng.remotelabs.schedserver.rigmanagement.intf.types.RigTypesType;
import au.edu.uts.eng.remotelabs.schedserver.rigoperations.RigMaintenance;
import au.edu.uts.eng.remotelabs.schedserver.rigoperations.RigReleaser;

/**
 * Rig management SOAP service.
 */
public class RigManagement implements RigManagementInterface {
    /** Logger. */
    public Logger logger;

    /** Flag for unit testing to disable rig client communication. */
    private boolean notTest = true;

    public RigManagement() {
        this.logger = LoggerActivator.getLogger();
    }

    @SuppressWarnings("unchecked")
    @Override
    public GetTypesResponse getTypes(GetTypes getTypes) {
        this.logger.debug("Received RigManagement#getTypes.");

        GetTypesResponse response = new GetTypesResponse();
        RigTypesType types = new RigTypesType();
        response.setGetTypesResponse(types);

        Session db = DataAccessActivator.getNewSession();
        try {

            for (au.edu.uts.eng.remotelabs.schedserver.dataaccess.entities.RigType rigType : (List<au.edu.uts.eng.remotelabs.schedserver.dataaccess.entities.RigType>) db
                    .createCriteria(au.edu.uts.eng.remotelabs.schedserver.dataaccess.entities.RigType.class)
                    .addOrder(Order.asc("name")).list()) {
                RigTypeType rigTypeParam = new RigTypeType();
                rigTypeParam.setName(rigType.getName());
                types.addType(rigTypeParam);

                Set<Rig> rigs = rigType.getRigs();
                rigTypeParam.setNumberRigs(rigs.size());

                rigTypeParam.setIsOnline(false);
                for (Rig rig : rigs) {
                    if (rig.isActive() && rig.isOnline()) {
                        rigTypeParam.setIsOnline(true);
                        break;
                    }
                }

                rigTypeParam.setIsAlarmed(false);
                for (Rig rig : rigs) {
                    if (!(rig.isActive() && rig.isOnline()) && !(new RigOfflineScheduleDao(db).isOffline(rig))) {
                        rigTypeParam.setIsAlarmed(true);
                        break;
                    }
                }
            }
        } finally {
            db.close();
        }

        return response;
    }

    @Override
    public GetTypeStatusResponse getTypeStatus(GetTypeStatus request) {
        String name = request.getGetTypeStatus().getName();
        this.logger.debug("Received RigManagement#getTypeStatus with params: name=" + name + '.');

        GetTypeStatusResponse response = new GetTypeStatusResponse();
        RigTypeType rigTypeParam = new RigTypeType();
        rigTypeParam.setName(name);
        response.setGetTypeStatusResponse(rigTypeParam);

        RigTypeDao dao = new RigTypeDao();
        try {
            au.edu.uts.eng.remotelabs.schedserver.dataaccess.entities.RigType rigType = dao.findByName(name);
            if (rigType == null) {
                this.logger.info("Unable to find rig type because the no rig type with name '" + name + "' found.");
                rigTypeParam.setNumberRigs(0);
                return response;
            }

            boolean online = false;
            boolean alarmed = false;

            Set<Rig> rigs = rigType.getRigs();
            rigTypeParam.setNumberRigs(rigs.size());

            RigTypeIDType typeID = new RigTypeIDType();
            typeID.setName(name);

            for (Rig rig : rigs) {
                RigType rigParam = new RigType();
                rigTypeParam.addRig(rigParam);

                rigParam.setName(rig.getName());
                rigParam.setRigType(typeID);
                rigParam.setCapabilities(rig.getRigCapabilities().getCapabilities());

                rigParam.setIsRegistered(rig.isActive());
                rigParam.setIsOnline(rig.isOnline());
                rigParam.setIsInSession(rig.isInSession());
                if (rig.isInSession())
                    rigParam.setSessionUser(rig.getSession().getUser().qName());

                if (rig.isOnline() && rig.isActive())
                    online = true;
                else {
                    if (rig.getOfflineReason() != null)
                        rigParam.setOfflineReason(rig.getOfflineReason());

                    /* If the rig is off-line and not scheduled to be off-line, the rig is alarmed. */
                    if (!(new RigOfflineScheduleDao(dao.getSession()).isOffline(rig))) {
                        alarmed = true;
                        rigParam.setIsAlarmed(true);
                    }
                }

                if (rig.getContactUrl() != null)
                    rigParam.setContactURL(rig.getContactUrl());
            }

            rigTypeParam.setIsOnline(online);
            rigTypeParam.setIsAlarmed(alarmed);
        } finally {
            dao.closeSession();
        }

        return response;
    }

    @SuppressWarnings("unchecked")
    @Override
    public GetRigResponse getRig(GetRig request) {
        String name = request.getGetRig().getName();
        this.logger.debug("Received RigManagement#getRig with parameters: name=" + name + '.');

        GetRigResponse response = new GetRigResponse();
        RigType rigParam = new RigType();
        rigParam.setName(name);
        RigTypeIDType typeID = new RigTypeIDType();
        typeID.setName("Unknown.");
        rigParam.setRigType(typeID);
        rigParam.setCapabilities("Unknown.");
        response.setGetRigResponse(rigParam);

        RigDao dao = new RigDao();
        try {
            Rig rig = dao.findByName(name);
            if (rig == null)
                return response;
            rig.getSessions();
            typeID.setName(rig.getRigType().getName());
            rigParam.setCapabilities(rig.getRigCapabilities().getCapabilities());

            rigParam.setIsRegistered(rig.isActive());
            rigParam.setIsOnline(rig.isOnline());
            if (rig.isInSession()) {
                rigParam.setIsInSession(true);
                rigParam.setSessionUser(rig.getSession().getUser().qName());
            }

            rigParam.setIsAlarmed(!(rig.isActive() && rig.isOnline())
                    && !(new RigOfflineScheduleDao(dao.getSession()).isOffline(rig)));

            if (rig.getOfflineReason() != null)
                rigParam.setOfflineReason(rig.getOfflineReason());
            if (rig.getContactUrl() != null)
                rigParam.setContactURL(rig.getContactUrl());

            for (RigLog log : (List<RigLog>) dao.getSession().createCriteria(RigLog.class)
                    .add(Restrictions.eq("rig", rig)).addOrder(Order.desc("timeStamp")).setMaxResults(10).list()) {
                RigLogType logParam = new RigLogType();
                Calendar ts = Calendar.getInstance();
                ts.setTime(log.getTimeStamp());
                logParam.setTimestamp(ts);
                logParam.setReason(log.getReason());

                if (RigLog.ONLINE.equals(log.getOldState()))
                    logParam.setOldState(RigStateType.ONLINE);
                else if (RigLog.OFFLINE.equals(log.getOldState()))
                    logParam.setOldState(RigStateType.OFFLINE);
                else if (RigLog.NOT_REGISTERED.equals(log.getOldState()))
                    logParam.setOldState(RigStateType.NOT_REGISTERED);

                if (RigLog.ONLINE.equals(log.getNewState()))
                    logParam.setNewState(RigStateType.ONLINE);
                else if (RigLog.OFFLINE.equals(log.getNewState()))
                    logParam.setNewState(RigStateType.OFFLINE);
                else if (RigLog.NOT_REGISTERED.equals(log.getNewState()))
                    logParam.setNewState(RigStateType.NOT_REGISTERED);

                rigParam.addLastLog(logParam);
            }

            for (RigOfflineSchedule sched : new RigOfflineScheduleDao(dao.getSession()).getOfflinePeriods(rig)) {
                OfflinePeriodType offline = new OfflinePeriodType();
                offline.setId(sched.getId().intValue());
                offline.setReason(sched.getReason());

                Calendar start = Calendar.getInstance();
                start.setTime(sched.getStartTime());
                offline.setStart(start);

                Calendar end = Calendar.getInstance();
                end.setTime(sched.getEndTime());
                offline.setEnd(end);

                rigParam.addOfflinePeriods(offline);
            }
        } finally {
            dao.closeSession();
        }

        return response;
    }

    @Override
    public PutRigOfflineResponse putRigOffline(PutRigOffline putRigOffline) {
        PutRigOfflineType param = putRigOffline.getPutRigOffline();
        this.logger.debug("Received RigManagement#putRigOffline with params: requestor ID=" + param.getRequestorID()
                + "requestor namespace=" + param.getRequestorNameSpace() + ", requestor name"
                + param.getRequestorName() + ", rig name=" + param.getRig().getName() + ", offline start="
                + param.getStart().getTime() + ", offline end=" + param.getEnd().getTime() + ", reason="
                + param.getReason() + '.');

        PutRigOfflineResponse response = new PutRigOfflineResponse();
        OperationResponseType result = new OperationResponseType();
        response.setPutRigOfflineResponse(result);

        RigDao dao = new RigDao();
        try {
            if (!this.isAuthorised(param, dao.getSession())) {
                this.logger.warn("Unable to put a rig offline because the user is not authorised to perform this "
                        + "operation (not a ADMIN).");
                result.setFailureCode(1);
                result.setFailureReason("Not authorised.");
                return response;
            }

            Rig rig = dao.findByName(param.getRig().getName());
            if (rig == null) {
                this.logger.warn("Unable to put a rig offline because the rig with name " + param.getRig().getName()
                        + " was not found.");
                result.setFailureCode(2);
                result.setFailureReason("Rig not found.");
                return response;
            }

            if (param.getStart().after(param.getEnd())) {
                this.logger
                        .warn("Unable to put a rig offline because the offline start " + param.getStart().getTime()
                                + " is after the offline end " + param.getEnd().getTime() + ".");
                result.setFailureCode(3);
                result.setFailureReason("Start after end.");
                return response;
            }

            Date startDate = param.getStart().getTime();
            Date endDate = param.getEnd().getTime();

            if ((Integer) dao.getSession().createCriteria(RigOfflineSchedule.class)
                    .add(Restrictions.eq("active", Boolean.TRUE)).add(Restrictions.eq("rig", rig))
                    .add(Restrictions.disjunction()
                            .add(Restrictions.and(Restrictions.gt("startTime", startDate),
                                    Restrictions.lt("endTime", endDate)))
                            .add(Restrictions.and(Restrictions.lt("startTime", startDate),
                                    Restrictions.gt("endTime", endDate)))
                            .add(Restrictions.and(Restrictions.lt("startTime", startDate),
                                    Restrictions.gt("endTime", endDate)))
                            .add(Restrictions.and(Restrictions.lt("startTime", startDate),
                                    Restrictions.gt("endTime", endDate))))
                    .setProjection(Projections.rowCount()).uniqueResult() > 0) {
                this.logger.warn("Unable to put a rig offline because there is a concurrent rig offline period.");
                result.setFailureCode(4);
                result.setFailureReason("Concurrent offline period.");
                return response;
            }

            result.setSuccessful(true);

            RigOfflineSchedule offline = new RigOfflineSchedule();
            offline.setActive(true);
            offline.setRig(rig);
            offline.setStartTime(startDate);
            offline.setEndTime(endDate);
            offline.setReason(param.getReason());
            new RigOfflineScheduleDao(dao.getSession()).persist(offline);

            /* Notify the booking engine. */
            BookingEngineService service = RigManagementActivator.getBookingService();
            if (service != null)
                service.putRigOffline(offline, dao.getSession());

            /* If the period is currently active, clear the rig maintenance state. */
            Date now = new Date();
            if (rig.isActive() && rig.isOnline() && offline.getStartTime().before(now)
                    && offline.getEndTime().after(now)) {
                this.logger.info("Setting maintenance state on rig " + rig.getName() + '.');
                if (this.notTest)
                    new RigMaintenance().putMaintenance(rig, true, dao.getSession());

                rig.setOnline(false);
                rig.setOfflineReason("In maintenance.");
                new RigLogDao(dao.getSession()).addOfflineLog(rig, "In maintenance.");
                dao.flush();
            }
        } finally {
            dao.closeSession();
        }

        return response;
    }

    @Override
    public CancelRigOfflineResponse cancelRigOffline(CancelRigOffline request) {
        CancelRigOfflineType cancelParam = request.getCancelRigOffline();
        this.logger.debug(
                "Received RigManagement#cancelRigOffline with params: requestor ID=" + cancelParam.getRequestorID()
                        + "requestor namespace=" + cancelParam.getRequestorNameSpace() + ", requestor name"
                        + cancelParam.getRequestorName() + ", offline ID=" + cancelParam.getPeriod().getId() + '.');

        CancelRigOfflineResponse response = new CancelRigOfflineResponse();
        OperationResponseType result = new OperationResponseType();
        response.setCancelRigOfflineResponse(result);

        RigOfflineScheduleDao dao = new RigOfflineScheduleDao();
        try {
            if (!this.isAuthorised(cancelParam, dao.getSession())) {
                this.logger
                        .warn("Unable to cancel a rig offline period because the user is not authorised to perform "
                                + "this operation (not a ADMIN).");
                result.setFailureCode(1);
                result.setFailureReason("Not authorised.");
                return response;
            }

            RigOfflineSchedule offline = dao.get(Long.valueOf(cancelParam.getPeriod().getId()));
            if (offline == null) {
                this.logger.warn("Unable to cancel a rig offline period because the offline period with ID "
                        + cancelParam.getPeriod().getId() + " was not found.");
                result.setFailureCode(2);
                result.setFailureReason("Period not found.");
                return response;
            }

            if (!offline.isActive()) {
                this.logger.warn("Offline period with ID " + offline.getId()
                        + " is already canceled. Not cancelling " + "it again.");
                result.setFailureCode(3);
                result.setFailureReason("Already cancelled.");
                return response;
            }

            result.setSuccessful(true);

            /* Cancel the offline period. */
            offline.setActive(false);
            dao.flush();

            /* Notify the booking engine. */
            BookingEngineService service = RigManagementActivator.getBookingService();
            if (service != null)
                service.clearRigOffline(offline, dao.getSession());

            /* If the period is currently active, clear the rig maintenance state. */
            Date now = new Date();
            Rig rig = offline.getRig();
            if (rig.isActive() && !rig.isOnline() && offline.getStartTime().before(now)
                    && offline.getEndTime().after(now)) {
                this.logger.info("Clearning maintenance state on rig " + offline.getRig().getName() + '.');
                if (this.notTest)
                    new RigMaintenance().clearMaintenance(rig, dao.getSession());
            }
        } finally {
            dao.closeSession();
        }

        return response;
    }

    @Override
    public FreeRigResponse freeRig(FreeRig freeRig) {
        KickRigType param = freeRig.getFreeRig();
        this.logger.debug("Received RigManagement#freeRig with params: requestor ID=" + param.getRequestorID()
                + "requestor namespace=" + param.getRequestorNameSpace() + ", requestor name"
                + param.getRequestorName() + ", rig name=" + param.getRig().getName() + ", reason="
                + param.getReason() + '.');

        FreeRigResponse response = new FreeRigResponse();
        OperationResponseType result = new OperationResponseType();
        response.setFreeRigResponse(result);

        RigDao dao = new RigDao();
        try {
            if (!this.isAuthorised(param, dao.getSession())) {
                this.logger.warn("Unable to free rig because the requesting user is not authorised to perform this "
                        + "operation (not a ADMIN).");
                result.setFailureCode(1);
                result.setFailureReason("No authorised.");
                return response;
            }

            Rig rig = dao.findByName(param.getRig().getName());
            if (rig == null) {
                this.logger.warn("Unable to free rig because rig with name " + param.getRig().getName()
                        + " was not " + "found.");
                result.setFailureCode(2);
                result.setFailureReason("Rig not found.");
                return response;
            }

            if (!rig.isInSession() || rig.getSession() == null) {
                this.logger.warn(
                        "Unable to free rig with name " + rig.getName() + " because the rig is not in session.");
                result.setFailureCode(3);
                result.setFailureReason("Rig not in session.");
                return response;
            }

            result.setSuccessful(true);

            au.edu.uts.eng.remotelabs.schedserver.dataaccess.entities.Session ses = rig.getSession();
            this.logger.info("Admin kicking off user " + ses.getUser().qName() + " from rig " + rig.getName() + ". "
                    + "Reason: " + param.getReason() + '.');
            ses.setActive(false);
            ses.setRemovalTime(new Date());
            ses.setRemovalReason("User was kicked off by admin. Reason: " + param.getReason());
            dao.flush();

            if (this.notTest)
                new RigReleaser().release(ses, dao.getSession());
        } finally {
            dao.closeSession();
        }

        return response;
    }

    /**
     * Checks whether the requestor is authorised to perform an operation. The
     * requestors are only authorised if they are admins.
     * 
     * @param request
     * @return true if the requestor is an admin
     */
    private boolean isAuthorised(OperationRequestType request, Session db) {
        UserDao dao = new UserDao(db);

        String ns = request.getRequestorNameSpace(), name = request.getRequestorName();
        User user = null;
        if (request.getRequestorID() > 0) {
            user = dao.get(Long.valueOf(request.getRequestorID()));
        } else if (ns != null && name != null) {
            user = dao.findByName(ns, name);
        }

        if (user == null)
            return false;

        return User.ADMIN.equals(user.getPersona());
    }
}