Java tutorial
/* * The DecidR Development Team 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 de.decidr.model.commands.user; import java.util.List; import org.apache.log4j.Logger; import org.hibernate.Query; import org.hibernate.Session; import de.decidr.model.DecidrGlobals; import de.decidr.model.LifetimeValidator; import de.decidr.model.XmlTools; import de.decidr.model.acl.access.InvitationAccess; import de.decidr.model.acl.permissions.Permission; import de.decidr.model.acl.roles.Role; import de.decidr.model.commands.AclAwareCommand; import de.decidr.model.entities.Invitation; import de.decidr.model.entities.Server; import de.decidr.model.entities.ServerLoadView; import de.decidr.model.entities.Tenant; import de.decidr.model.entities.User; import de.decidr.model.entities.UserAdministratesWorkflowModel; import de.decidr.model.entities.UserIsMemberOfTenant; import de.decidr.model.entities.UserParticipatesInWorkflow; import de.decidr.model.entities.WorkflowInstance; import de.decidr.model.enums.ServerTypeEnum; import de.decidr.model.exceptions.AccessDeniedException; import de.decidr.model.exceptions.EntityNotFoundException; import de.decidr.model.exceptions.RequestExpiredException; import de.decidr.model.exceptions.TransactionException; import de.decidr.model.logging.DefaultLogger; import de.decidr.model.schema.decidrtypes.TConfiguration; import de.decidr.model.transactions.TransactionEvent; import de.decidr.model.transactions.TransactionStartedEvent; import de.decidr.model.workflowmodel.instancemanagement.CreateInstanceResult; import de.decidr.model.workflowmodel.instancemanagement.InstanceManager; /** * Confirms a single invitation by associating the user with the corresponding * tenant (if necessary). * * Workflow instances that are waiting for this invitation to be confirmed will * be started. * * @author Markus Fischer * @author Daniel Huss * @version 0.1 */ public class ConfirmInvitationCommand extends AclAwareCommand implements InvitationAccess { private static Logger logger = DefaultLogger.getLogger(ConfirmInvitationCommand.class); private Long invitationId; private Invitation invitation = null; private WorkflowInstance instanceToStart = null; /** * Current Hibernate Session */ private Session session = null; /** * Creates a new ConfirmInviationCommand. * * @param role * the user which executes the command * @param invitationId * the id of the invitation which should be confirmed */ public ConfirmInvitationCommand(Role role, Long invitationId) { super(role, (Permission) null); if (invitationId == null) { throw new IllegalArgumentException("Invitation ID must not be null."); } this.invitationId = invitationId; } @Override public Long[] getInvitationIds() { Long[] result = { invitationId }; return result; } /** * Makes the given user a member of the given tenant. This method has no * effect if the user is already a tenant member or the tenant admin. * * @param user * user who should become member of the given tenant * @param tenant * tenant to which the given user should be added */ private void makeMemberOfTenant(User user, Tenant tenant) { if ((tenant == null) || (user == null)) { throw new IllegalArgumentException("User and tenant must not be null"); } Query q = session.createQuery("select count(*) from UserIsMemberOfTenant a " + "where (a.tenant = :tenant AND a.user = :user) or a.tenant.admin = :user"); q.setEntity("tenant", tenant); q.setEntity("user", user); if (((Number) q.uniqueResult()).intValue() < 1) { // user isn't a tenant member yet, make him a tenant member! UserIsMemberOfTenant relation = new UserIsMemberOfTenant(); relation.setUser(user); relation.setTenant(tenant); session.save(relation); } } /** * Makes the receiver of the invitation a member of the tenant that is * specified by the invitation. */ private void processJoinTenantInvitation() { makeMemberOfTenant(invitation.getReceiver(), invitation.getJoinTenant()); } /** * Makes the receiver of the invitation a member of the tenant that owns the * workflow instance to participate in. Associates the receiver with the * workflow instance and starts the instance if the receiver was the last * user who had to confirm his invitation. * * @throws TransactionException * if the instance manager cannot start the new workflow * instance. */ @SuppressWarnings("unchecked") private void processWorkflowInstanceInvitation() throws TransactionException { User user = invitation.getReceiver(); Tenant tenant = invitation.getParticipateInWorkflowInstance().getDeployedWorkflowModel().getTenant(); makeMemberOfTenant(user, tenant); // Add as WorkflowParticipant if not already a participant boolean found = session .createQuery("select rel.user.id from UserParticipatesInWorkflow rel " + "where rel.user = :user " + "and rel.workflowInstance = :workflowInstance") .setEntity("user", user) .setEntity("workflowInstance", invitation.getParticipateInWorkflowInstance()).setMaxResults(1) .uniqueResult() != null; if (found) { // the user is currently not participating in the workflow UserParticipatesInWorkflow relation = new UserParticipatesInWorkflow(); relation.setUser(user); relation.setWorkflowInstance(invitation.getParticipateInWorkflowInstance()); session.save(relation); } // start the (delayed) workflow instance if this is the last invitation. WorkflowInstance instance = invitation.getParticipateInWorkflowInstance(); if (instance == null) { throw new EntityNotFoundException(WorkflowInstance.class); } String hql = "select count(*) from Invitation i where " + "i.participateInWorkflowInstance = :instance and " + "i.participateInWorkflowInstance is not null and " + "i.participateInWorkflowInstance.startedDate is null"; Number remainingInvitations = (Number) session.createQuery(hql).setEntity("instance", instance) .uniqueResult(); if (remainingInvitations.intValue() == 1) { // this is the last invitation InstanceManager manager = new InstanceManager(); // Fixed invitation confirmation bug: this is the old query // Query q = session // .createQuery("from ServerLoadView s where s.serverType.name = :serverType"); // Fixed invitation confirmation bug: this is the new query Query q = session.createQuery("select s from ServerLoadView s where s.serverType = :serverType"); List<ServerLoadView> serverStatistics = q.setString("serverType", ServerTypeEnum.Ode.toString()).list(); // instance only needed to get the OdePid and Server from the // instance manager CreateInstanceResult createInstanceResult; try { createInstanceResult = manager.createInstance(instance.getDeployedWorkflowModel(), XmlTools.unmarshalJaxbEntity(instance.getStartConfiguration(), TConfiguration.class), serverStatistics); } catch (Exception e) { throw new TransactionException(e); } instance.setOdePid(createInstanceResult.getODEPid()); instance.setStartedDate(DecidrGlobals.getTime().getTime()); instance.setServer((Server) session.get(Server.class, createInstanceResult.getServerId())); session.save(instance); } } /** * Makes the receiver of the invitation a member of the tenant and allows * him to administrate the workflow model that is specified by the * invitation. * * @throws AccessDeniedException */ private void processWorkflowModelInvitation() throws AccessDeniedException { User user = invitation.getReceiver(); Tenant tenant = invitation.getAdministrateWorkflowModel().getTenant(); makeMemberOfTenant(user, tenant); // only registered users can do this if (user.getUserProfile() == null) { throw new AccessDeniedException("You must be registered to become workflow administrator"); } // add as WorkflowAdmin only if not already a workflow admin Query q = session.createQuery("select count(*) from UserAdministratesWorkflowModel rel " + "where rel.user = :user and rel.workflowModel = :workflowModel"); q.setEntity("user", user).setEntity("workflowModel", invitation.getAdministrateWorkflowModel()); if (((Number) q.uniqueResult()).intValue() < 1) { // the user is currently not administrating the workflow model UserAdministratesWorkflowModel relation = new UserAdministratesWorkflowModel(); relation.setUser(user); relation.setWorkflowModel(invitation.getAdministrateWorkflowModel()); session.save(relation); } } @Override public void transactionAllowed(TransactionStartedEvent evt) throws TransactionException { instanceToStart = null; session = evt.getSession(); invitation = (Invitation) evt.getSession().get(Invitation.class, invitationId); // does the invitation exist? if (invitation == null) { throw new EntityNotFoundException(Invitation.class, invitationId); } // is the invitation still valid? if (!LifetimeValidator.isInvitationValid(invitation)) { throw new RequestExpiredException("The invitation has expired."); } if (invitation.getAdministrateWorkflowModel() != null) { // Invitation tye: administrate workflow model processWorkflowModelInvitation(); } else if (invitation.getJoinTenant() != null) { // Invitation tye: simply join tenant as member processJoinTenantInvitation(); } else if (invitation.getParticipateInWorkflowInstance() != null) { // add to tenant if user isn't tenant member and start delayed // workflow instances try { processWorkflowInstanceInvitation(); } catch (Exception e) { if (e instanceof TransactionException) { throw (TransactionException) e; } else { throw new TransactionException(e); } } } else { // not a valid invitation type String warnMessage = String.format( "An invitation (id: %1$s) was confirmed but had no type " + "[workflowInstance = null, tenant = null, workflowModel = null]", invitation.getId().toString()); logger.warn(warnMessage); } session.delete(invitation); } @Override public void transactionCommitted(TransactionEvent evt) throws TransactionException { /* * Start any prepared workflow instances. */ if (instanceToStart != null) { InstanceManager instanceManager = new InstanceManager(); try { instanceManager.startInstance(instanceToStart); } catch (Exception e) { throw new TransactionException(e); } } } }