001: /*
002: * JBoss, Home of Professional Open Source
003: * Copyright 2005, JBoss Inc., and individual contributors as indicated
004: * by the @authors tag. See the copyright.txt in the distribution for a
005: * full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jbpm.identity.assignment;
023:
024: import java.util.Set;
025:
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028: import org.jbpm.JbpmContext;
029: import org.jbpm.graph.exe.ExecutionContext;
030: import org.jbpm.graph.exe.Token;
031: import org.jbpm.identity.Entity;
032: import org.jbpm.identity.Group;
033: import org.jbpm.identity.User;
034: import org.jbpm.identity.hibernate.IdentitySession;
035: import org.jbpm.security.SecurityHelper;
036: import org.jbpm.taskmgmt.def.AssignmentHandler;
037: import org.jbpm.taskmgmt.exe.Assignable;
038: import org.jbpm.taskmgmt.exe.SwimlaneInstance;
039:
040: /**
041: * implements an expression language for assigning actors to tasks based
042: * on this identity component.
043: *
044: * <pre>syntax : first-term --> next-term --> next-term --> ... --> next-term
045: *
046: * first-term ::= previous |
047: * swimlane(swimlane-name) |
048: * variable(variable-name) |
049: * user(user-name) |
050: * group(group-name)
051: *
052: * next-term ::= group(group-type) |
053: * member(role-name)
054: * </pre>
055: */
056: public class ExpressionAssignmentHandler implements AssignmentHandler {
057:
058: private static final long serialVersionUID = 1L;
059:
060: protected String expression;
061: protected ExecutionContext executionContext = null;
062: protected ExpressionSession expressionSession = null;
063: protected TermTokenizer tokenizer;
064: protected Entity entity = null;
065:
066: public void assign(Assignable assignable,
067: ExecutionContext executionContext) {
068:
069: try {
070: expressionSession = getExpressionSession();
071: if (expressionSession == null) {
072: throw new NullPointerException(
073: "getIdentitySession returned null");
074: }
075: this .tokenizer = new TermTokenizer(expression);
076: this .executionContext = executionContext;
077: entity = resolveFirstTerm(tokenizer.nextTerm());
078: while (tokenizer.hasMoreTerms() && (entity != null)) {
079: entity = resolveNextTerm(tokenizer.nextTerm());
080: }
081: // if the expression did not resolve to an actor
082: if (entity == null) {
083: // throw an exception
084: throw new RuntimeException(
085: "couldn't resolve assignment expression '"
086: + expression + "'");
087:
088: // else if the expression evaluated to a user
089: } else if (entity instanceof User) {
090: // do direct assignment
091: assignable.setActorId(entity.getName());
092:
093: // else if the expression evaluated to a group
094: } else if (entity instanceof Group) {
095: // put the group in the pool
096: assignable.setPooledActors(new String[] { entity
097: .getName() });
098: }
099:
100: } catch (RuntimeException e) {
101: throw new ExpressionAssignmentException(
102: "couldn't resolve assignment expression '"
103: + expression + "'", e);
104: }
105: }
106:
107: /**
108: * serves as a hook for customizing the way the identity session is retrieved.
109: * overload this method to reuse this expression assignment handler for your
110: * user data store.
111: */
112: protected ExpressionSession getExpressionSession() {
113: JbpmContext jbpmContext = JbpmContext.getCurrentJbpmContext();
114: if (jbpmContext == null) {
115: throw new RuntimeException(
116: "no active JbpmContext for resolving assignment expression'"
117: + expression + "'");
118: }
119: return new IdentitySession(jbpmContext.getSession());
120: }
121:
122: protected Entity resolveFirstTerm(String term) {
123: Entity entity = null;
124:
125: log.debug("resolving first term '" + term + "'");
126:
127: if (term.equalsIgnoreCase("previous")) {
128: String userName = SecurityHelper.getAuthenticatedActorId();
129: entity = getUserByName(userName);
130:
131: } else if ((term.startsWith("swimlane("))
132: && (term.endsWith(")"))) {
133: String swimlaneName = term.substring(9, term.length() - 1)
134: .trim();
135: String userName = getSwimlaneActorId(swimlaneName);
136: entity = getUserByName(userName);
137:
138: } else if ((term.startsWith("variable("))
139: && (term.endsWith(")"))) {
140: String variableName = term.substring(9, term.length() - 1)
141: .trim();
142: Object value = getVariable(variableName);
143:
144: if (value == null) {
145: throw new ExpressionAssignmentException("variable '"
146: + variableName + "' is null");
147:
148: } else if (value instanceof String) {
149: entity = getUserByName((String) value);
150:
151: } else if (value instanceof Entity) {
152: entity = (Entity) value;
153: }
154:
155: } else if ((term.startsWith("user(")) && (term.endsWith(")"))) {
156: String userName = term.substring(5, term.length() - 1)
157: .trim();
158: entity = getUserByName(userName);
159:
160: } else if ((term.startsWith("group(")) && (term.endsWith(")"))) {
161: String groupName = term.substring(6, term.length() - 1)
162: .trim();
163: entity = getGroupByName(groupName);
164:
165: } else {
166: throw new ExpressionAssignmentException(
167: "couldn't interpret first term in expression '"
168: + expression + "'");
169: }
170:
171: return entity;
172: }
173:
174: protected Entity resolveNextTerm(String term) {
175:
176: log.debug("resolving next term '" + term + "'");
177:
178: if ((term.startsWith("group(")) && (term.endsWith(")"))) {
179: String groupType = term.substring(6, term.length() - 1)
180: .trim();
181: User user = (User) entity;
182: Set groups = user.getGroupsForGroupType(groupType);
183: if (groups.size() == 0) {
184: throw new ExpressionAssignmentException(
185: "no groups for group-type '" + groupType + "'");
186: }
187: entity = (Entity) groups.iterator().next();
188:
189: } else if ((term.startsWith("member(")) && (term.endsWith(")"))) {
190: String role = term.substring(7, term.length() - 1).trim();
191: Group group = (Group) entity;
192: entity = expressionSession.getUserByGroupAndRole(group
193: .getName(), role);
194: if (entity == null) {
195: throw new ExpressionAssignmentException(
196: "no users in role '" + role + "'");
197: }
198:
199: } else {
200: throw new ExpressionAssignmentException(
201: "couldn't interpret term '" + term
202: + "' in expression '" + expression + "'");
203: }
204:
205: return entity;
206: }
207:
208: protected Object getVariable(String variableName) {
209: Token token = executionContext.getToken();
210: return executionContext.getContextInstance().getVariable(
211: variableName, token);
212: }
213:
214: protected Entity getGroupByName(String groupName) {
215: Group group = null;
216: group = expressionSession.getGroupByName(groupName);
217: if (group == null) {
218: throw new ExpressionAssignmentException("group '"
219: + groupName
220: + "' couldn't be fetched from the user db");
221: }
222: return group;
223: }
224:
225: protected Entity getUserByName(String userName) {
226: User user = null;
227: user = expressionSession.getUserByName(userName);
228: if (user == null) {
229: throw new ExpressionAssignmentException("user '" + userName
230: + "' couldn't be fetched from the user db");
231: }
232: return user;
233: }
234:
235: protected String getSwimlaneActorId(String swimlaneName) {
236: SwimlaneInstance swimlaneInstance = executionContext
237: .getTaskMgmtInstance()
238: .getSwimlaneInstance(swimlaneName);
239: if (swimlaneInstance == null) {
240: throw new ExpressionAssignmentException(
241: "no swimlane instance '" + swimlaneName + "'");
242: }
243: return swimlaneInstance.getActorId();
244: }
245:
246: private static final Log log = LogFactory
247: .getLog(ExpressionAssignmentHandler.class);
248: }
|