/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF 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 org.apache.ode.daohib.bpel; import java.util.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.ode.bpel.common.CorrelationKey; import org.apache.ode.bpel.common.CorrelationKeySet; import org.apache.ode.bpel.dao.*; import org.apache.ode.bpel.iapi.Scheduler; import org.apache.ode.daohib.SessionManager; import org.apache.ode.daohib.bpel.hobj.HCorrelator; import org.apache.ode.daohib.bpel.hobj.HCorrelatorMessage; import org.apache.ode.daohib.bpel.hobj.HCorrelatorSelector; import org.apache.ode.daohib.bpel.hobj.HMessageExchange; import org.apache.ode.daohib.bpel.hobj.HProcess; import org.apache.ode.daohib.bpel.hobj.HProcessInstance; import org.hibernate.Hibernate; import org.hibernate.LockMode; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.exception.LockAcquisitionException; import javax.xml.namespace.QName; /** * Hibernate-based {@link CorrelatorDAO} implementation. */ class CorrelatorDaoImpl extends HibernateDao implements CorrelatorDAO { static Logger __log = LoggerFactory.getLogger(CorrelatorDaoImpl.class); /** filter for finding a matching selector. */ private static final String LOCK_SELECTORS = "update from HCorrelatorSelector as hs set hs.lock = hs.lock+1 where hs.processType = :processType"; private static final String CHECK_SELECTORS = "from HCorrelatorSelector as hs where hs.processType = :processType and hs.correlator.correlatorId = :correlatorId"; private static final String FLTR_SELECTORS = "from HCorrelatorSelector as hs where hs.processType = :processType and hs.correlator.correlatorId = :correlatorId"; private static final String FLTR_SELECTORS_SUBQUERY = ("from HCorrelatorSelector as hs where hs.processType = :processType and hs.correlatorId = " + "(select hc.id from HCorrelator as hc where hc.correlatorId = :correlatorId )").intern(); /** Query for removing routes. */ private static final String QRY_DELSELECTORS = "delete from HCorrelatorSelector where groupId = ? and instance = ?"; private HCorrelator _hobj; public CorrelatorDaoImpl(SessionManager sm, HCorrelator hobj) { super(sm, hobj); entering("CorrelatorDaoImpl.CorrelatorDaoImpl"); _hobj = hobj; } @SuppressWarnings("unchecked") public MessageExchangeDAO dequeueMessage(CorrelationKeySet keySet) { entering("CorrelatorDaoImpl.dequeueMessage"); MessageExchangeDAO mex = null; String hdr = "dequeueMessage(" + keySet + "): "; __log.debug(hdr); List<CorrelationKeySet> subSets = keySet.findSubSets(); Query qry = getSession().createFilter(_hobj.getMessageCorrelations(), generateUnmatchedQuery(subSets)); for( int i = 0; i < subSets.size(); i++ ) { qry.setString("s" + i, subSets.get(i).toCanonicalString()); } // We really should consider the possibility of multiple messages matching a criteria. // When the message is handled, its not too convenient to attempt to determine if the // received message conflicts with one already received. Iterator mcors; try { mcors = qry.setLockMode("this", LockMode.UPGRADE).iterate(); } catch (LockAcquisitionException e) { throw new Scheduler.JobProcessorException(e, true); } try { if (!mcors.hasNext()) { if (__log.isDebugEnabled()) __log.debug(hdr + "did not find a MESSAGE entry."); } else { HCorrelatorMessage mcor = (HCorrelatorMessage) mcors.next(); if (__log.isDebugEnabled()) __log.debug(hdr + "found MESSAGE entry " + mcor.getMessageExchange()); mex = new MessageExchangeDaoImpl(_sm, mcor.getMessageExchange()); } } finally { Hibernate.close(mcors); } return mex; } @SuppressWarnings("unchecked") public List<MessageRouteDAO> findRoute(CorrelationKeySet keySet) { List<MessageRouteDAO> routes = new ArrayList<MessageRouteDAO>(); entering("CorrelatorDaoImpl.findRoute"); String hdr = "findRoute(keySet=" + keySet + "): "; if (__log.isDebugEnabled()) __log.debug(hdr); String processType = new QName(_hobj.getProcess().getTypeNamespace(), _hobj.getProcess().getTypeName()).toString(); List<CorrelationKeySet> subSets = keySet.findSubSets(); Query q = getSession().createQuery(generateSelectorQuery(_sm.canJoinForUpdate() ? FLTR_SELECTORS : FLTR_SELECTORS_SUBQUERY, subSets)); q.setString("processType", processType); q.setString("correlatorId", _hobj.getCorrelatorId()); for( int i = 0; i < subSets.size(); i++ ) { q.setString("s" + i, subSets.get(i).toCanonicalString()); } // Make sure we obtain a lock for the selector we want to find. q.setLockMode("hs", LockMode.UPGRADE); List<HProcessInstance> targets = new ArrayList<HProcessInstance>(); List<HCorrelatorSelector> list; try { list = (List<HCorrelatorSelector>) q.list(); } catch (LockAcquisitionException e) { throw new Scheduler.JobProcessorException(e, true); } for (HCorrelatorSelector selector : list) { if (selector != null) { boolean isRoutePolicyOne = selector.getRoute() == null || "one".equals(selector.getRoute()); if ("all".equals(selector.getRoute()) || (isRoutePolicyOne && !targets.contains(selector.getInstance()))) { routes.add(new MessageRouteDaoImpl(_sm, selector)); targets.add(selector.getInstance()); } } } if(__log.isDebugEnabled()) __log.debug(hdr + "found " + routes); return routes; } private String generateUnmatchedQuery(List<CorrelationKeySet> subSets) { StringBuffer filterQuery = new StringBuffer(); if( subSets.size() == 1 ) { filterQuery.append(" where this.correlationKey = :s0"); } else if( subSets.size() > 1 ) { filterQuery.append(" where this.correlationKey in("); for( int i = 0; i < subSets.size(); i++ ) { if( i > 0 ) { filterQuery.append(", "); } filterQuery.append(":s").append(i); } filterQuery.append(")"); } return filterQuery.toString(); } private String generateSelectorQuery(String header, List<CorrelationKeySet> subSets) { StringBuffer filterQuery = new StringBuffer(header); if( subSets.size() == 1 ) { filterQuery.append(" and hs.correlationKey = :s0"); } else if( subSets.size() > 1 ) { filterQuery.append(" and hs.correlationKey in("); for( int i = 0; i < subSets.size(); i++ ) { if( i > 0 ) { filterQuery.append(", "); } filterQuery.append(":s").append(i); } filterQuery.append(")"); } return filterQuery.toString(); } public void enqueueMessage(MessageExchangeDAO mex, CorrelationKeySet correlationKeySet) { entering("CorrelatorDaoImpl.enqueueMessage"); String hdr = "enqueueMessage(mex=" + ((MessageExchangeDaoImpl) mex)._hobj.getId() + " keySet=" + correlationKeySet.toCanonicalString() + "): "; if (__log.isDebugEnabled()) __log.debug(hdr); for( CorrelationKeySet aSubSet : correlationKeySet.findSubSets() ) { HCorrelatorMessage mcor = new HCorrelatorMessage(); mcor.setCorrelator(_hobj); mcor.setCreated(new Date()); mcor.setMessageExchange((HMessageExchange) ((MessageExchangeDaoImpl) mex)._hobj); mcor.setCorrelationKey(aSubSet.toCanonicalString()); getSession().save(mcor); if (__log.isDebugEnabled()) __log.debug(hdr + "saved " + mcor); } } public void addRoute(String routeGroupId, ProcessInstanceDAO target, int idx, CorrelationKeySet correlationKeySet, String routePolicy) { entering("CorrelatorDaoImpl.addRoute"); String hdr = "addRoute(" + routeGroupId + ", iid=" + target.getInstanceId() + ", idx=" + idx + ", ckeySet=" + correlationKeySet + "): "; if (__log.isDebugEnabled()) __log.debug(hdr); HCorrelatorSelector hsel = new HCorrelatorSelector(); hsel.setGroupId(routeGroupId); hsel.setIndex(idx); hsel.setLock(0); hsel.setCorrelationKey(correlationKeySet.toCanonicalString()); hsel.setInstance((HProcessInstance) ((ProcessInstanceDaoImpl) target).getHibernateObj()); hsel.setProcessType(target.getProcess().getType().toString()); hsel.setCorrelator(_hobj); hsel.setCreated(new Date()); hsel.setRoute(routePolicy); try { getSession().save(hsel); } catch (LockAcquisitionException e) { throw new Scheduler.JobProcessorException(e, true); } if (__log.isDebugEnabled()) __log.debug(hdr + "saved " + hsel); } public boolean checkRoute(CorrelationKeySet correlationKeySet) { entering("CorrelatorDaoImpl.checkRoute"); Query q = getSession().getNamedQuery(HCorrelatorSelector.SELECT_MESSAGE_ROUTE); q.setEntity("corr",_hobj); q.setString("ckey", correlationKeySet.toCanonicalString()); q.setReadOnly(true); return q.list().isEmpty(); } public String getCorrelatorId() { return _hobj.getCorrelatorId(); } public void setCorrelatorId(String newId) { _hobj.setCorrelatorId(newId); } public void removeRoutes(String routeGroupId, ProcessInstanceDAO target) { entering("CorrelatorDaoImpl.removeRoutes"); String hdr = "removeRoutes(" + routeGroupId + ", iid=" + target.getInstanceId() + "): "; __log.debug(hdr); Session session = getSession(); Query q = session.createQuery(QRY_DELSELECTORS); q.setString(0, routeGroupId); // groupId q.setEntity(1, ((ProcessInstanceDaoImpl) target).getHibernateObj()); // instance int updates = q.executeUpdate(); session.flush(); // explicit flush to ensure route removed if (__log.isDebugEnabled()) __log.debug(hdr + "deleted " + updates + " rows"); } public Collection<CorrelatorMessageDAO> getAllMessages() { Collection<CorrelatorMessageDAO> msgs = new ArrayList<CorrelatorMessageDAO>(); for (HCorrelatorMessage correlatorMessage : _hobj.getMessageCorrelations()) msgs.add(new CorrelatorMessageDaoImpl(_sm, correlatorMessage)); return msgs; } public Collection<MessageRouteDAO> getAllRoutes() { Collection<MessageRouteDAO> routes = new ArrayList<MessageRouteDAO>(); for (HCorrelatorSelector selector : _hobj.getSelectors()) routes.add(new MessageRouteDaoImpl(_sm, selector)); return routes; } }