package de.rwth.idsg.bikeman.ixsi.dispatcher; import com.google.common.base.Optional; import de.rwth.idsg.bikeman.ixsi.CommunicationContext; import de.rwth.idsg.bikeman.ixsi.ErrorFactory; import de.rwth.idsg.bikeman.ixsi.IxsiProcessingException; import de.rwth.idsg.bikeman.ixsi.processor.UserValidator; import de.rwth.idsg.bikeman.ixsi.processor.api.StaticRequestProcessor; import de.rwth.idsg.bikeman.ixsi.processor.api.UserRequestProcessor; import de.rwth.idsg.bikeman.ixsi.repository.SystemValidator; import de.rwth.idsg.ixsi.jaxb.StaticDataRequestGroup; import de.rwth.idsg.ixsi.jaxb.StaticDataResponseGroup; import de.rwth.idsg.ixsi.jaxb.UserTriggeredRequestChoice; import de.rwth.idsg.ixsi.jaxb.UserTriggeredResponseChoice; import lombok.extern.slf4j.Slf4j; import org.joda.time.Period; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import xjc.schema.ixsi.AuthType; import xjc.schema.ixsi.ErrorType; import xjc.schema.ixsi.Language; import xjc.schema.ixsi.QueryRequestType; import xjc.schema.ixsi.QueryResponseType; import xjc.schema.ixsi.UserInfoType; import javax.xml.datatype.DatatypeFactory; import java.util.List; /** * @author Sevket Goekay <goekay@dbis.rwth-aachen.de> * @since 24.09.2014 */ @Slf4j @Component public class QueryRequestTypeDispatcher implements Dispatcher { @Autowired private ProcessorProvider processorProvider; @Autowired private SystemValidator systemValidator; @Autowired private UserValidator userValidator; @Override public void handle(CommunicationContext context) { log.trace("Entered handle..."); List<QueryRequestType> requestList = context.getIncomingIxsi().getRequest(); List<QueryResponseType> responseList = context.getOutgoingIxsi().getResponse(); log.trace("QueryRequestType size: {}", requestList.size()); for (QueryRequestType request : requestList) { responseList.add(handle(request)); } } private QueryResponseType handle(QueryRequestType request) { // Process the request // long startTime = System.currentTimeMillis(); QueryResponseType response = delegate(request); long stopTime = System.currentTimeMillis(); int duration = (int) (stopTime - startTime); Period calcTime = Period.millis(duration); response.setCalcTime(calcTime); response.setTransaction(request.getTransaction()); return response; } private QueryResponseType delegate(QueryRequestType request) { if (request.isSetStaticDataRequestGroup()) { return buildStaticResponse(request); } else if (request.isSetUserTriggeredRequestChoice()) { return buildUserResponse(request); } else { throw new IxsiProcessingException("Unknown incoming message: " + request); } } // ------------------------------------------------------------------------- // Choice content // ------------------------------------------------------------------------- @SuppressWarnings("unchecked") private QueryResponseType buildStaticResponse(QueryRequestType request) { log.trace("Entered buildStaticResponse..."); StaticDataRequestGroup req = request.getStaticDataRequestGroup(); StaticRequestProcessor p = processorProvider.find(req); // System validation // boolean isValid = systemValidator.validate(request.getSystemID()); if (!isValid) { return new QueryResponseType() .withStaticDataResponseGroup(p.buildError(ErrorFactory.Sys.idUknown())); } // Catch all exceptions down the pipeline caused by processors and do not let the communication fail! // Otherwise, the connection will break StaticDataResponseGroup res; try { res = p.process(req); } catch (Exception e) { log.error("Error occurred", e); res = p.buildError(ErrorFactory.Sys.backendFailed(e.getMessage(), null)); } return new QueryResponseType() .withStaticDataResponseGroup(res); } @SuppressWarnings("unchecked") private QueryResponseType buildUserResponse(QueryRequestType request) { log.trace("Entered buildUserResponse..."); UserTriggeredRequestChoice c = request.getUserTriggeredRequestChoice(); UserRequestProcessor p = processorProvider.find(c); // System validation // boolean isValid = systemValidator.validate(request.getSystemID()); if (!isValid) { return new QueryResponseType() .withUserTriggeredResponseGroup(p.buildError(ErrorFactory.Sys.idUknown())); } // Catch all exceptions down the pipeline caused by processors and do not let the communication fail! // Otherwise, the connection will break UserTriggeredResponseChoice res; try { res = delegateUserRequest(c, p, Optional.fromNullable(request.getLanguage()), request.getAuth()); } catch (Exception e) { log.error("Error occurred", e); res = p.buildError(ErrorFactory.Sys.backendFailed(e.getMessage(), null)); } return new QueryResponseType() .withUserTriggeredResponseGroup(res); } @SuppressWarnings("unchecked") private UserTriggeredResponseChoice delegateUserRequest(UserTriggeredRequestChoice c, UserRequestProcessor p, Optional<Language> lan, AuthType auth) { log.trace("Processing the authentication information..."); if (auth.isSetAnonymous() && auth.isAnonymous()) { return p.processAnonymously(c, lan); } else if (auth.isSetUserInfo()) { return validateUserAndProceed(c, p, lan, auth.getUserInfo()); } else if (auth.isSetSessionID()) { return p.buildError(ErrorFactory.Sys.notImplemented("Session-based authentication is not supported", null)); } else { return p.buildError(ErrorFactory.Sys.notImplemented("Authentication requirements are not met", null)); } } /** * User validation !! */ @SuppressWarnings("unchecked") private UserTriggeredResponseChoice validateUserAndProceed(UserTriggeredRequestChoice c, UserRequestProcessor p, Optional<Language> lan, List<UserInfoType> userInfoList) { if (userInfoList.size() != 1) { String msg = "More than one user per request is not allowed"; return p.buildError(ErrorFactory.Sys.invalidRequest(msg, msg)); } UserInfoType userInfo = userInfoList.get(0); Optional<ErrorType> error = userValidator.validate(userInfo); if (error.isPresent()) { return p.buildError(error.get()); } else { return p.processForUser(c, lan, userInfo); } } }