org.apache.cxf.ws.rm.Source Maven / Gradle / Ivy
/**
* 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.cxf.ws.rm;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.ws.rm.persistence.RMStore;
import org.apache.cxf.ws.rm.v200702.Identifier;
public class Source extends AbstractEndpoint {
private static final String REQUESTOR_SEQUENCE_ID = "";
private Map map;
private Map current;
private Lock sequenceCreationLock;
private Condition sequenceCreationCondition;
private boolean sequenceCreationNotified;
Source(RMEndpoint reliableEndpoint) {
super(reliableEndpoint);
map = new ConcurrentHashMap();
current = new HashMap();
sequenceCreationLock = new ReentrantLock();
sequenceCreationCondition = sequenceCreationLock.newCondition();
}
public SourceSequence getSequence(Identifier id) {
return map.get(id.getValue());
}
public Collection getAllSequences() {
return CastUtils.cast(map.values());
}
public void addSequence(SourceSequence seq) {
addSequence(seq, true);
}
public void addSequence(SourceSequence seq, boolean persist) {
seq.setSource(this);
map.put(seq.getIdentifier().getValue(), seq);
if (persist) {
RMStore store = getReliableEndpoint().getManager().getStore();
if (null != store) {
store.createSourceSequence(seq);
}
}
processingSequenceCount.incrementAndGet();
}
public void removeSequence(SourceSequence seq) {
SourceSequence o;
o = map.remove(seq.getIdentifier().getValue());
RMStore store = getReliableEndpoint().getManager().getStore();
if (null != store) {
store.removeSourceSequence(seq.getIdentifier());
}
if (o != null) {
processingSequenceCount.decrementAndGet();
completedSequenceCount.incrementAndGet();
}
}
/**
* Returns a collection of all sequences for which have not yet been
* completely acknowledged.
*
* @return the collection of unacknowledged sequences.
*/
public Collection getAllUnacknowledgedSequences() {
Collection seqs = new ArrayList();
for (SourceSequence seq : map.values()) {
if (!seq.allAcknowledged()) {
seqs.add(seq);
}
}
return seqs;
}
/**
* Returns the current sequence used by a client side source.
*
* @return the current sequence.
*/
SourceSequence getCurrent() {
return getCurrent(null);
}
/**
* Sets the current sequence used by a client side source.
* @param s the current sequence.
*/
public void setCurrent(SourceSequence s) {
setCurrent(null, s);
}
/**
* Returns the current sequence used by a server side source for responses to a message
* sent as part of the inbound sequence with the specified identifier.
*
* @return the current sequence.
*/
SourceSequence getCurrent(Identifier i) {
sequenceCreationLock.lock();
try {
return getAssociatedSequence(i);
} finally {
sequenceCreationLock.unlock();
}
}
/**
* Returns the sequence associated with the given identifier.
*
* @param i the corresponding sequence identifier
* @return the associated sequence
* @pre the sequenceCreationLock is already held
*/
SourceSequence getAssociatedSequence(Identifier i) {
return current.get(i == null ? REQUESTOR_SEQUENCE_ID : i.getValue());
}
/**
* Await the availability of a sequence corresponding to the given identifier.
*
* @param i the sequence identifier
* @return
*/
SourceSequence awaitCurrent(Identifier i) {
sequenceCreationLock.lock();
try {
SourceSequence seq = getAssociatedSequence(i);
while (seq == null) {
while (!sequenceCreationNotified) {
try {
sequenceCreationCondition.await();
} catch (InterruptedException ie) {
// ignore
}
}
seq = getAssociatedSequence(i);
}
return seq;
} finally {
sequenceCreationLock.unlock();
}
}
/**
* Sets the current sequence used by a server side source for responses to a message
* sent as part of the inbound sequence with the specified identifier.
* @param s the current sequence.
*/
void setCurrent(Identifier i, SourceSequence s) {
sequenceCreationLock.lock();
try {
current.put(i == null ? REQUESTOR_SEQUENCE_ID : i.getValue(), s);
sequenceCreationNotified = true;
sequenceCreationCondition.signal();
} finally {
sequenceCreationLock.unlock();
}
}
}