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.svc;
023:
024: import java.io.Serializable;
025: import java.util.ArrayList;
026: import java.util.HashMap;
027: import java.util.Iterator;
028: import java.util.List;
029: import java.util.Map;
030:
031: import org.apache.commons.logging.Log;
032: import org.apache.commons.logging.LogFactory;
033: import org.hibernate.StaleObjectStateException;
034: import org.jbpm.JbpmContext;
035: import org.jbpm.JbpmException;
036: import org.jbpm.graph.exe.ProcessInstance;
037: import org.jbpm.logging.LoggingService;
038: import org.jbpm.msg.MessageService;
039: import org.jbpm.persistence.JbpmPersistenceException;
040: import org.jbpm.persistence.PersistenceService;
041: import org.jbpm.persistence.db.StaleObjectLogConfigurer;
042: import org.jbpm.scheduler.SchedulerService;
043: import org.jbpm.security.AuthenticationService;
044: import org.jbpm.security.AuthorizationService;
045: import org.jbpm.svc.save.CascadeSaveOperation;
046: import org.jbpm.svc.save.CheckUnpersistableVariablesOperation;
047: import org.jbpm.svc.save.HibernateSaveOperation;
048: import org.jbpm.svc.save.SaveLogsOperation;
049: import org.jbpm.svc.save.SaveOperation;
050: import org.jbpm.tx.TxService;
051:
052: public class Services implements Serializable {
053:
054: private static final long serialVersionUID = 1L;
055:
056: public static final String SERVICENAME_AUTHENTICATION = "authentication";
057: public static final String SERVICENAME_AUTHORIZATION = "authorization";
058: public static final String SERVICENAME_TX = "tx";
059: public static final String SERVICENAME_LOGGING = "logging";
060: public static final String SERVICENAME_MESSAGE = "message";
061: public static final String SERVICENAME_PERSISTENCE = "persistence";
062: public static final String SERVICENAME_SCHEDULER = "scheduler";
063: public static final String SERVICENAME_JCR = "jcr";
064: public static final String SERVICENAME_ADDRESSRESOLVER = "addressresolver";
065:
066: static final List defaultSaveOperations = new ArrayList();
067:
068: static {
069: defaultSaveOperations
070: .add(new CheckUnpersistableVariablesOperation());
071: // first we save the runtime data (process instance)
072: defaultSaveOperations.add(new HibernateSaveOperation());
073: // then we insert the logs cause the logs can have references
074: // to the runtime data
075: defaultSaveOperations.add(new SaveLogsOperation());
076: defaultSaveOperations.add(new CascadeSaveOperation());
077: }
078:
079: Map serviceFactories = null;
080: Map services = null;
081: List serviceNames = null;
082: List saveOperations = null;
083:
084: public static Service getCurrentService(String name) {
085: return getCurrentService(name, true);
086: }
087:
088: public static Service getCurrentService(String name,
089: boolean isRequired) {
090: Service service = null;
091: JbpmContext jbpmContext = JbpmContext.getCurrentJbpmContext();
092: if (jbpmContext != null) {
093: service = jbpmContext.getServices().getService(name);
094: }
095: if (isRequired && (service == null)) {
096: throw new JbpmServiceException("service '" + name
097: + "' unavailable");
098: }
099: return service;
100: }
101:
102: public Services(Map serviceFactories) {
103: this (serviceFactories,
104: new ArrayList(serviceFactories.keySet()), null);
105: }
106:
107: public Services(Map serviceFactories, List serviceNames,
108: List saveOperations) {
109: this .serviceFactories = serviceFactories;
110: this .serviceNames = serviceNames;
111: if (saveOperations != null) {
112: this .saveOperations = saveOperations;
113: } else {
114: this .saveOperations = defaultSaveOperations;
115: }
116: }
117:
118: public void setSaveOperations(List saveOperations) {
119: this .saveOperations = saveOperations;
120: }
121:
122: public Map getServiceFactories() {
123: if (serviceFactories == null) {
124: serviceFactories = new HashMap();
125: }
126: return serviceFactories;
127: }
128:
129: public ServiceFactory getServiceFactory(String name) {
130: return (ServiceFactory) getServiceFactories().get(name);
131: }
132:
133: public boolean hasService(String name) {
134: boolean hasService = false;
135: if (services != null) {
136: hasService = services.containsKey(name);
137: }
138: return hasService;
139: }
140:
141: public Service getService(String name) {
142: if (services == null) {
143: services = new HashMap();
144: }
145: Service service = (Service) services.get(name);
146: if (service == null) {
147: ServiceFactory serviceFactory = getServiceFactory(name);
148: if (serviceFactory != null) {
149: service = serviceFactory.openService();
150: services.put(name, service);
151: }
152: }
153: return service;
154: }
155:
156: public void save(ProcessInstance processInstance,
157: JbpmContext jbpmContext) {
158: Iterator iter = saveOperations.iterator();
159:
160: if (log.isDebugEnabled()) {
161: if (saveOperations == defaultSaveOperations) {
162: log.debug("executing default save operations");
163: } else {
164: log.debug("executing custom save operations");
165: }
166: }
167:
168: while (iter.hasNext()) {
169: SaveOperation saveOperation = (SaveOperation) iter.next();
170: saveOperation.save(processInstance, jbpmContext);
171: }
172: }
173:
174: // services /////////////////////////////////////////////////////////////////
175:
176: public AuthenticationService getAuthenticationService() {
177: return (AuthenticationService) getService(SERVICENAME_AUTHENTICATION);
178: }
179:
180: public AuthorizationService getAuthorizationService() {
181: return (AuthorizationService) getService(SERVICENAME_AUTHORIZATION);
182: }
183:
184: public LoggingService getLoggingService() {
185: return (LoggingService) getService(SERVICENAME_LOGGING);
186: }
187:
188: public MessageService getMessageService() {
189: return (MessageService) getService(SERVICENAME_MESSAGE);
190: }
191:
192: public PersistenceService getPersistenceService() {
193: return (PersistenceService) getService(SERVICENAME_PERSISTENCE);
194: }
195:
196: public SchedulerService getSchedulerService() {
197: return (SchedulerService) getService(SERVICENAME_SCHEDULER);
198: }
199:
200: public TxService getTxService() {
201: return (TxService) getService(SERVICENAME_TX);
202: }
203:
204: public void setAuthenticationService(
205: AuthenticationService authenticationService) {
206: services.put(SERVICENAME_AUTHENTICATION, authenticationService);
207: }
208:
209: public void setAuthorizationService(
210: AuthorizationService authorizationService) {
211: services.put(SERVICENAME_AUTHORIZATION, authorizationService);
212: }
213:
214: public void setLoggingService(LoggingService loggingService) {
215: services.put(SERVICENAME_LOGGING, loggingService);
216: }
217:
218: public void setMessageService(MessageService messageService) {
219: services.put(SERVICENAME_MESSAGE, messageService);
220: }
221:
222: public void setPersistenceService(
223: PersistenceService persistenceService) {
224: services.put(SERVICENAME_PERSISTENCE, persistenceService);
225: }
226:
227: public void setSchedulerService(SchedulerService schedulerService) {
228: services.put(SERVICENAME_SCHEDULER, schedulerService);
229: }
230:
231: public void setTxService(TxService txService) {
232: services.put(SERVICENAME_TX, txService);
233: }
234:
235: public void close() {
236: if (services != null) {
237: Map closeExceptions = new HashMap();
238: Throwable firstException = null;
239: Iterator iter = serviceNames.iterator();
240: while (iter.hasNext()) {
241: String serviceName = (String) iter.next();
242: Service service = (Service) services.get(serviceName);
243: if (service != null) {
244: try {
245: log.debug("closing service '" + serviceName
246: + "': " + service);
247: service.close();
248: } catch (JbpmPersistenceException e) {
249: // if this is a stale object exception, the jbpm configuration has control over the logging
250: if ("org.hibernate.StaleObjectStateException"
251: .equals(e.getCause().getClass()
252: .getName())) {
253: log.info("problem closing service '"
254: + serviceName
255: + "': optimistic locking failed");
256: StaleObjectLogConfigurer.staleObjectExceptionsLog
257: .error(
258: "problem closing service '"
259: + serviceName
260: + "': optimistic locking failed",
261: e);
262: } else {
263: log.error("problem closing service '"
264: + serviceName + "'", e);
265: }
266: } catch (Exception e) {
267: // NOTE that Error's are not caught because that might halt the JVM and mask the original Error.
268: log.error("problem closing service '"
269: + serviceName + "'", e);
270: closeExceptions.put(serviceName, e);
271: if (firstException == null) {
272: firstException = e;
273: }
274: }
275: }
276: }
277: if (!closeExceptions.isEmpty()) {
278: throw new JbpmException("problem closing services "
279: + closeExceptions, firstException);
280: }
281: }
282: }
283:
284: public static void assignId(Object object) {
285: JbpmContext jbpmContext = JbpmContext.getCurrentJbpmContext();
286: if (jbpmContext != null) {
287: // give this process instance an id
288: Services services = jbpmContext.getServices();
289: if (services.hasService(Services.SERVICENAME_PERSISTENCE)) {
290: PersistenceService persistenceService = services
291: .getPersistenceService();
292: persistenceService.assignId(object);
293: }
294: }
295: }
296:
297: private static Log log = LogFactory.getLog(Services.class);
298: }
|