No effective change - change newline char

This commit is contained in:
rbygrave
2015-05-09 01:11:56 +12:00
parent 88f144ec33
commit f947a76fce
17 changed files with 1965 additions and 1965 deletions
@@ -1,103 +1,103 @@
package com.avaje.ebeaninternal.server.transaction;
import java.io.DataInput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.server.cluster.BinaryMessage;
import com.avaje.ebeaninternal.server.cluster.BinaryMessageList;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
public class BeanDelta {
private final List<BeanDeltaProperty> properties;
private final BeanDescriptor<?> beanDescriptor;
private final Object id;
public BeanDelta(BeanDescriptor<?> beanDescriptor, Object id) {
this.beanDescriptor = beanDescriptor;
this.id = id;
this.properties = new ArrayList<BeanDeltaProperty>();
}
public BeanDescriptor<?> getBeanDescriptor() {
return beanDescriptor;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("BeanDelta[");
sb.append(beanDescriptor.getName()).append(":");
sb.append(properties);
sb.append("]");
return sb.toString();
}
public Object getId() {
return id;
}
public void add(BeanProperty beanProperty, Object value) {
this.properties.add(new BeanDeltaProperty(beanProperty, value));
}
public void add(BeanDeltaProperty propertyDelta) {
this.properties.add(propertyDelta);
}
public void apply(EntityBean bean) {
for (int i = 0; i < properties.size(); i++) {
properties.get(i).apply(bean);
}
}
/**
* Read and return a BeanDelta from the binary input.
*/
public static BeanDelta readBinaryMessage(SpiEbeanServer server, DataInput dataInput) throws IOException {
String descriptorId = dataInput.readUTF();
BeanDescriptor<?> desc = server.getBeanDescriptorById(descriptorId);
Object id = desc.getIdBinder().readData(dataInput);
BeanDelta bp = new BeanDelta(desc, id);
int count = dataInput.readInt();
for (int i = 0; i < count; i++) {
String propName = dataInput.readUTF();
BeanProperty beanProperty = desc.getBeanProperty(propName);
Object value = beanProperty.getScalarType().readData(dataInput);
bp.add(beanProperty, value);
}
return bp;
}
/**
* Write this bean delta in binary message format.
*/
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
BinaryMessage m = new BinaryMessage(50);
DataOutputStream os = m.getOs();
os.writeInt(BinaryMessage.TYPE_BEANDELTA);
os.writeUTF(beanDescriptor.getDescriptorId());
beanDescriptor.getIdBinder().writeData(os, id);
os.writeInt(properties.size());
for (int i = 0; i < properties.size(); i++) {
properties.get(i).writeBinaryMessage(m);
}
os.flush();
msgList.add(m);
}
}
package com.avaje.ebeaninternal.server.transaction;
import java.io.DataInput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.server.cluster.BinaryMessage;
import com.avaje.ebeaninternal.server.cluster.BinaryMessageList;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
public class BeanDelta {
private final List<BeanDeltaProperty> properties;
private final BeanDescriptor<?> beanDescriptor;
private final Object id;
public BeanDelta(BeanDescriptor<?> beanDescriptor, Object id) {
this.beanDescriptor = beanDescriptor;
this.id = id;
this.properties = new ArrayList<BeanDeltaProperty>();
}
public BeanDescriptor<?> getBeanDescriptor() {
return beanDescriptor;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("BeanDelta[");
sb.append(beanDescriptor.getName()).append(":");
sb.append(properties);
sb.append("]");
return sb.toString();
}
public Object getId() {
return id;
}
public void add(BeanProperty beanProperty, Object value) {
this.properties.add(new BeanDeltaProperty(beanProperty, value));
}
public void add(BeanDeltaProperty propertyDelta) {
this.properties.add(propertyDelta);
}
public void apply(EntityBean bean) {
for (int i = 0; i < properties.size(); i++) {
properties.get(i).apply(bean);
}
}
/**
* Read and return a BeanDelta from the binary input.
*/
public static BeanDelta readBinaryMessage(SpiEbeanServer server, DataInput dataInput) throws IOException {
String descriptorId = dataInput.readUTF();
BeanDescriptor<?> desc = server.getBeanDescriptorById(descriptorId);
Object id = desc.getIdBinder().readData(dataInput);
BeanDelta bp = new BeanDelta(desc, id);
int count = dataInput.readInt();
for (int i = 0; i < count; i++) {
String propName = dataInput.readUTF();
BeanProperty beanProperty = desc.getBeanProperty(propName);
Object value = beanProperty.getScalarType().readData(dataInput);
bp.add(beanProperty, value);
}
return bp;
}
/**
* Write this bean delta in binary message format.
*/
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
BinaryMessage m = new BinaryMessage(50);
DataOutputStream os = m.getOs();
os.writeInt(BinaryMessage.TYPE_BEANDELTA);
os.writeUTF(beanDescriptor.getDescriptorId());
beanDescriptor.getIdBinder().writeData(os, id);
os.writeInt(properties.size());
for (int i = 0; i < properties.size(); i++) {
properties.get(i).writeBinaryMessage(m);
}
os.flush();
msgList.add(m);
}
}
@@ -1,42 +1,42 @@
package com.avaje.ebeaninternal.server.transaction;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.avaje.ebeaninternal.server.cluster.BinaryMessageList;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
public class BeanDeltaList {
private final BeanDescriptor<?> beanDescriptor;
private final List<BeanDelta> deltaBeans = new ArrayList<BeanDelta>();
public BeanDeltaList(BeanDescriptor<?> beanDescriptor) {
this.beanDescriptor = beanDescriptor;
}
public String toString() {
return deltaBeans.toString();
}
public BeanDescriptor<?> getBeanDescriptor() {
return beanDescriptor;
}
public void add(BeanDelta b) {
deltaBeans.add(b);
}
public List<BeanDelta> getDeltaBeans() {
return deltaBeans;
}
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
for (int i = 0; i < deltaBeans.size(); i++) {
deltaBeans.get(i).writeBinaryMessage(msgList);
}
}
}
package com.avaje.ebeaninternal.server.transaction;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.avaje.ebeaninternal.server.cluster.BinaryMessageList;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
public class BeanDeltaList {
private final BeanDescriptor<?> beanDescriptor;
private final List<BeanDelta> deltaBeans = new ArrayList<BeanDelta>();
public BeanDeltaList(BeanDescriptor<?> beanDescriptor) {
this.beanDescriptor = beanDescriptor;
}
public String toString() {
return deltaBeans.toString();
}
public BeanDescriptor<?> getBeanDescriptor() {
return beanDescriptor;
}
public void add(BeanDelta b) {
deltaBeans.add(b);
}
public List<BeanDelta> getDeltaBeans() {
return deltaBeans;
}
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
for (int i = 0; i < deltaBeans.size(); i++) {
deltaBeans.get(i).writeBinaryMessage(msgList);
}
}
}
@@ -1,48 +1,48 @@
package com.avaje.ebeaninternal.server.transaction;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
public class BeanDeltaMap {
private Map<String,BeanDeltaList> deltaMap = new HashMap<String,BeanDeltaList>();
public BeanDeltaMap() {
}
public BeanDeltaMap(List<BeanDelta> deltaBeans) {
if (deltaBeans != null){
for (int i = 0; i < deltaBeans.size(); i++) {
BeanDelta deltaBean = deltaBeans.get(i);
addBeanDelta(deltaBean);
}
}
}
public String toString() {
return deltaMap.values().toString();
}
public void addBeanDelta(BeanDelta beanDelta){
BeanDescriptor<?> d = beanDelta.getBeanDescriptor();
BeanDeltaList list = getDeltaBeanList(d);
list.add(beanDelta);
}
public Collection<BeanDeltaList> deltaLists() {
return deltaMap.values();
}
private BeanDeltaList getDeltaBeanList(BeanDescriptor<?> d) {
BeanDeltaList deltaList = deltaMap.get(d.getFullName());
if (deltaList == null){
deltaList = new BeanDeltaList(d);
deltaMap.put(d.getFullName(), deltaList);
}
return deltaList;
}
}
package com.avaje.ebeaninternal.server.transaction;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
public class BeanDeltaMap {
private Map<String,BeanDeltaList> deltaMap = new HashMap<String,BeanDeltaList>();
public BeanDeltaMap() {
}
public BeanDeltaMap(List<BeanDelta> deltaBeans) {
if (deltaBeans != null){
for (int i = 0; i < deltaBeans.size(); i++) {
BeanDelta deltaBean = deltaBeans.get(i);
addBeanDelta(deltaBean);
}
}
}
public String toString() {
return deltaMap.values().toString();
}
public void addBeanDelta(BeanDelta beanDelta){
BeanDescriptor<?> d = beanDelta.getBeanDescriptor();
BeanDeltaList list = getDeltaBeanList(d);
list.add(beanDelta);
}
public Collection<BeanDeltaList> deltaLists() {
return deltaMap.values();
}
private BeanDeltaList getDeltaBeanList(BeanDescriptor<?> d) {
BeanDeltaList deltaList = deltaMap.get(d.getFullName());
if (deltaList == null){
deltaList = new BeanDeltaList(d);
deltaMap.put(d.getFullName(), deltaList);
}
return deltaList;
}
}
@@ -1,36 +1,36 @@
package com.avaje.ebeaninternal.server.transaction;
import java.io.DataOutputStream;
import java.io.IOException;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.cluster.BinaryMessage;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
public class BeanDeltaProperty {
private final BeanProperty beanProperty;
private final Object value;
public BeanDeltaProperty(BeanProperty beanProperty, Object value) {
this.beanProperty = beanProperty;
this.value = value;
}
public String toString() {
return beanProperty.getName()+":"+value;
}
public void apply(EntityBean bean) {
beanProperty.setValue(bean, value);
}
public void writeBinaryMessage(BinaryMessage m) throws IOException {
DataOutputStream os = m.getOs();
os.writeUTF(beanProperty.getName());
beanProperty.getScalarType().writeData(os, value);
}
}
package com.avaje.ebeaninternal.server.transaction;
import java.io.DataOutputStream;
import java.io.IOException;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.cluster.BinaryMessage;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
public class BeanDeltaProperty {
private final BeanProperty beanProperty;
private final Object value;
public BeanDeltaProperty(BeanProperty beanProperty, Object value) {
this.beanProperty = beanProperty;
this.value = value;
}
public String toString() {
return beanProperty.getName()+":"+value;
}
public void apply(EntityBean bean) {
beanProperty.setValue(bean, value);
}
public void writeBinaryMessage(BinaryMessage m) throws IOException {
DataOutputStream os = m.getOs();
os.writeUTF(beanProperty.getName());
beanProperty.getScalarType().writeData(os, value);
}
}
@@ -1,24 +1,24 @@
package com.avaje.ebeaninternal.server.transaction;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
public class BeanPathUpdate {
private final Map<String,BeanPathUpdateIds> map = new LinkedHashMap<String, BeanPathUpdateIds>();
public void add(BeanDescriptor<?> desc, String path, Object id) {
String key = desc.getFullName()+":"+path;
BeanPathUpdateIds pathIds = map.get(key);
if (pathIds == null){
pathIds = new BeanPathUpdateIds(desc, path);
map.put(key, pathIds);
}
pathIds.addId((Serializable)id);
}
}
package com.avaje.ebeaninternal.server.transaction;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
public class BeanPathUpdate {
private final Map<String,BeanPathUpdateIds> map = new LinkedHashMap<String, BeanPathUpdateIds>();
public void add(BeanDescriptor<?> desc, String path, Object id) {
String key = desc.getFullName()+":"+path;
BeanPathUpdateIds pathIds = map.get(key);
if (pathIds == null){
pathIds = new BeanPathUpdateIds(desc, path);
map.put(key, pathIds);
}
pathIds.addId((Serializable)id);
}
}
@@ -1,144 +1,144 @@
package com.avaje.ebeaninternal.server.transaction;
import java.io.DataInput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.server.cluster.BinaryMessage;
import com.avaje.ebeaninternal.server.cluster.BinaryMessageList;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
public class BeanPathUpdateIds {
private transient BeanDescriptor<?> beanDescriptor;
private final String descriptorId;
private String path;
private ArrayList<Serializable> ids;
/**
* Create the payload.
*/
public BeanPathUpdateIds(BeanDescriptor<?> desc, String path) {
this.beanDescriptor = desc;
this.descriptorId = desc.getDescriptorId();
this.path = path;
}
public String toString() {
StringBuilder sb = new StringBuilder();
if (beanDescriptor != null) {
sb.append(beanDescriptor.getFullName());
} else {
sb.append("descId:").append(descriptorId);
}
sb.append(" path:").append(path);
sb.append(" ids:").append(ids);
return sb.toString();
}
public static BeanPathUpdateIds readBinaryMessage(SpiEbeanServer server, DataInput dataInput) throws IOException {
String descriptorId = dataInput.readUTF();
String path = dataInput.readUTF();
BeanDescriptor<?> desc = server.getBeanDescriptorById(descriptorId);
BeanPathUpdateIds bp = new BeanPathUpdateIds(desc, path);
bp.read(dataInput);
return bp;
}
private void read(DataInput dataInput) throws IOException {
IdBinder idBinder = beanDescriptor.getIdBinder();
ids = readIdList(dataInput, idBinder);
}
private ArrayList<Serializable> readIdList(DataInput dataInput, IdBinder idBinder) throws IOException {
int count = dataInput.readInt();
if (count < 1) {
return null;
}
ArrayList<Serializable> idList = new ArrayList<Serializable>(count);
for (int i = 0; i < count; i++) {
Object id = idBinder.readData(dataInput);
idList.add((Serializable) id);
}
return idList;
}
/**
* Write the contents into a BinaryMessage form.
* <p>
* For a RemoteBeanPersist with a large number of id's note that this is
* broken up into many BinaryMessages each with a maximum of 100 ids. This
* enables the contents of a large RemoteTransactionEvent to be split up
* across multiple Packets.
* </p>
*/
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
IdBinder idBinder = beanDescriptor.getIdBinder();
int count = ids == null ? 0 : ids.size();
if (count > 0) {
int loop = 0;
int i = 0;
int eof = ids.size();
do {
++loop;
int endOfLoop = Math.min(eof, loop * 100);
BinaryMessage m = new BinaryMessage(endOfLoop * 4 + 20);
DataOutputStream os = m.getOs();
os.writeInt(BinaryMessage.TYPE_BEANPATHUPDATE);
os.writeUTF(descriptorId);
os.writeUTF(path);
os.writeInt(count);
for (; i < endOfLoop; i++) {
Serializable idValue = ids.get(i);
idBinder.writeData(os, idValue);
}
os.flush();
msgList.add(m);
} while (i < eof);
}
}
public void addId(Serializable id) {
ids.add(id);
}
public BeanDescriptor<?> getBeanDescriptor() {
return beanDescriptor;
}
/**
* Return the Descriptor Id. A more compact alternative to using the
* beanType.
*/
public String getDescriptorId() {
return descriptorId;
}
public String getPath() {
return path;
}
public List<Serializable> getIds() {
return ids;
}
}
package com.avaje.ebeaninternal.server.transaction;
import java.io.DataInput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.server.cluster.BinaryMessage;
import com.avaje.ebeaninternal.server.cluster.BinaryMessageList;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
public class BeanPathUpdateIds {
private transient BeanDescriptor<?> beanDescriptor;
private final String descriptorId;
private String path;
private ArrayList<Serializable> ids;
/**
* Create the payload.
*/
public BeanPathUpdateIds(BeanDescriptor<?> desc, String path) {
this.beanDescriptor = desc;
this.descriptorId = desc.getDescriptorId();
this.path = path;
}
public String toString() {
StringBuilder sb = new StringBuilder();
if (beanDescriptor != null) {
sb.append(beanDescriptor.getFullName());
} else {
sb.append("descId:").append(descriptorId);
}
sb.append(" path:").append(path);
sb.append(" ids:").append(ids);
return sb.toString();
}
public static BeanPathUpdateIds readBinaryMessage(SpiEbeanServer server, DataInput dataInput) throws IOException {
String descriptorId = dataInput.readUTF();
String path = dataInput.readUTF();
BeanDescriptor<?> desc = server.getBeanDescriptorById(descriptorId);
BeanPathUpdateIds bp = new BeanPathUpdateIds(desc, path);
bp.read(dataInput);
return bp;
}
private void read(DataInput dataInput) throws IOException {
IdBinder idBinder = beanDescriptor.getIdBinder();
ids = readIdList(dataInput, idBinder);
}
private ArrayList<Serializable> readIdList(DataInput dataInput, IdBinder idBinder) throws IOException {
int count = dataInput.readInt();
if (count < 1) {
return null;
}
ArrayList<Serializable> idList = new ArrayList<Serializable>(count);
for (int i = 0; i < count; i++) {
Object id = idBinder.readData(dataInput);
idList.add((Serializable) id);
}
return idList;
}
/**
* Write the contents into a BinaryMessage form.
* <p>
* For a RemoteBeanPersist with a large number of id's note that this is
* broken up into many BinaryMessages each with a maximum of 100 ids. This
* enables the contents of a large RemoteTransactionEvent to be split up
* across multiple Packets.
* </p>
*/
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
IdBinder idBinder = beanDescriptor.getIdBinder();
int count = ids == null ? 0 : ids.size();
if (count > 0) {
int loop = 0;
int i = 0;
int eof = ids.size();
do {
++loop;
int endOfLoop = Math.min(eof, loop * 100);
BinaryMessage m = new BinaryMessage(endOfLoop * 4 + 20);
DataOutputStream os = m.getOs();
os.writeInt(BinaryMessage.TYPE_BEANPATHUPDATE);
os.writeUTF(descriptorId);
os.writeUTF(path);
os.writeInt(count);
for (; i < endOfLoop; i++) {
Serializable idValue = ids.get(i);
idBinder.writeData(os, idValue);
}
os.flush();
msgList.add(m);
} while (i < eof);
}
}
public void addId(Serializable id) {
ids.add(id);
}
public BeanDescriptor<?> getBeanDescriptor() {
return beanDescriptor;
}
/**
* Return the Descriptor Id. A more compact alternative to using the
* beanType.
*/
public String getDescriptorId() {
return descriptorId;
}
public String getPath() {
return path;
}
public List<Serializable> getIds() {
return ids;
}
}
@@ -1,50 +1,50 @@
package com.avaje.ebeaninternal.server.transaction;
import java.io.Serializable;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import com.avaje.ebeaninternal.server.core.PersistRequest;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
/**
* Organises the individual bean persist requests by type.
*/
public final class BeanPersistIdMap {
private final Map<String,BeanPersistIds> beanMap = new LinkedHashMap<String, BeanPersistIds>();
public String toString() {
return beanMap.toString();
}
public boolean isEmpty() {
return beanMap.isEmpty();
}
public Collection<BeanPersistIds> values() {
return beanMap.values();
}
/**
* Add a Insert Update or Delete payload.
*/
public void add(BeanDescriptor<?> desc, PersistRequest.Type type, Object id) {
BeanPersistIds r = getPersistIds(desc);
r.addId(type, (Serializable)id);
}
private BeanPersistIds getPersistIds(BeanDescriptor<?> desc) {
String beanType = desc.getFullName();
BeanPersistIds r = beanMap.get(beanType);
if (r == null){
r = new BeanPersistIds(desc);
beanMap.put(beanType, r);
}
return r;
}
}
package com.avaje.ebeaninternal.server.transaction;
import java.io.Serializable;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import com.avaje.ebeaninternal.server.core.PersistRequest;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
/**
* Organises the individual bean persist requests by type.
*/
public final class BeanPersistIdMap {
private final Map<String,BeanPersistIds> beanMap = new LinkedHashMap<String, BeanPersistIds>();
public String toString() {
return beanMap.toString();
}
public boolean isEmpty() {
return beanMap.isEmpty();
}
public Collection<BeanPersistIds> values() {
return beanMap.values();
}
/**
* Add a Insert Update or Delete payload.
*/
public void add(BeanDescriptor<?> desc, PersistRequest.Type type, Object id) {
BeanPersistIds r = getPersistIds(desc);
r.addId(type, (Serializable)id);
}
private BeanPersistIds getPersistIds(BeanDescriptor<?> desc) {
String beanType = desc.getFullName();
BeanPersistIds r = beanMap.get(beanType);
if (r == null){
r = new BeanPersistIds(desc);
beanMap.put(beanType, r);
}
return r;
}
}
@@ -1,288 +1,288 @@
package com.avaje.ebeaninternal.server.transaction;
import java.io.DataInput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.avaje.ebean.event.BeanPersistListener;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.server.cluster.BinaryMessage;
import com.avaje.ebeaninternal.server.cluster.BinaryMessageList;
import com.avaje.ebeaninternal.server.core.PersistRequest;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
/**
* Wraps the information representing a Inserted Updated or Deleted Bean.
* <p>
* This information is broadcast across the cluster so that remote BeanListeners
* are notified of the inserts updates and deletes that occured.
* </p>
* <p>
* You control it the data is broadcast and what data is broadcast by the
* BeanListener.getClusterData() method. It is guessed that often just the Id
* property or perhaps a few properties in a Map will be broadcast to reduce the
* size of data sent around the network.
* </p>
*/
public class BeanPersistIds implements Serializable {
private static final long serialVersionUID = 8389469180931531409L;
private transient BeanDescriptor<?> beanDescriptor;
private final String descriptorId;
private ArrayList<Serializable> insertIds;
private ArrayList<Serializable> updateIds;
private ArrayList<Serializable> deleteIds;
/**
* Create the payload.
*/
public BeanPersistIds(BeanDescriptor<?> desc) {
this.beanDescriptor = desc;
this.descriptorId = desc.getDescriptorId();
}
public static BeanPersistIds readBinaryMessage(SpiEbeanServer server, DataInput dataInput) throws IOException {
String descriptorId = dataInput.readUTF();
BeanDescriptor<?> desc = server.getBeanDescriptorById(descriptorId);
BeanPersistIds bp = new BeanPersistIds(desc);
bp.read(dataInput);
return bp;
}
private void read(DataInput dataInput) throws IOException {
IdBinder idBinder = beanDescriptor.getIdBinder();
int iudType = dataInput.readInt();
ArrayList<Serializable> idList = readIdList(dataInput, idBinder);
switch (iudType) {
case 0:
insertIds = idList;
break;
case 1:
updateIds = idList;
break;
case 2:
deleteIds = idList;
break;
default:
throw new RuntimeException("Invalid iudType "+iudType);
}
}
/**
* Write the contents into a BinaryMessage form.
* <p>
* For a RemoteBeanPersist with a large number of id's note that this is
* broken up into many BinaryMessages each with a maximum of 100 ids. This
* enables the contents of a large RemoteTransactionEvent to be split up
* across multiple Packets.
* </p>
*/
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
writeIdList(beanDescriptor, 0, insertIds, msgList);
writeIdList(beanDescriptor, 1, updateIds, msgList);
writeIdList(beanDescriptor, 2, deleteIds, msgList);
}
private ArrayList<Serializable> readIdList(DataInput dataInput, IdBinder idBinder) throws IOException {
int count = dataInput.readInt();
if (count < 1) {
return null;
}
ArrayList<Serializable> idList = new ArrayList<Serializable>(count);
for (int i = 0; i < count; i++) {
Object id = idBinder.readData(dataInput);
idList.add((Serializable) id);
}
return idList;
}
/**
* Write a BinaryMessage containing the descriptorId, iudType and list of Id
* values.
* <p>
* Note that a given BinaryMessage has a maximum of 100 Ids. This is due to
* the limit of UDP packet sizes. We break up the RemoteBeanPersist into
* potentially many smaller BinaryMessages which may be put into multiple
* Packets.
* </p>
*/
private void writeIdList(BeanDescriptor<?> desc, int iudType, ArrayList<Serializable> idList,
BinaryMessageList msgList) throws IOException {
IdBinder idBinder = desc.getIdBinder();
int count = idList == null ? 0 : idList.size();
if (count > 0) {
int loop = 0;
int i = 0;
int eof = idList.size();
do {
++loop;
int endOfLoop = Math.min(eof, loop * 100);
BinaryMessage m = new BinaryMessage(endOfLoop * 4 + 20);
DataOutputStream os = m.getOs();
os.writeInt(BinaryMessage.TYPE_BEANIUD);
os.writeUTF(descriptorId);
os.writeInt(iudType);
os.writeInt(count);
for (; i < endOfLoop; i++) {
Serializable idValue = idList.get(i);
idBinder.writeData(os, idValue);
}
os.flush();
msgList.add(m);
} while (i < eof);
}
}
public String toString() {
StringBuilder sb = new StringBuilder();
if (beanDescriptor != null) {
sb.append(beanDescriptor.getFullName());
} else {
sb.append("descId:").append(descriptorId);
}
if (insertIds != null) {
sb.append(" insertIds:").append(insertIds);
}
if (updateIds != null) {
sb.append(" updateIds:").append(updateIds);
}
if (deleteIds != null) {
sb.append(" deleteIds:").append(deleteIds);
}
return sb.toString();
}
public void addId(PersistRequest.Type type, Serializable id) {
switch (type) {
case INSERT:
addInsertId(id);
break;
case UPDATE:
addUpdateId(id);
break;
case DELETE:
addDeleteId(id);
break;
default:
break;
}
}
private void addInsertId(Serializable id) {
if (insertIds == null) {
insertIds = new ArrayList<Serializable>();
}
insertIds.add(id);
}
private void addUpdateId(Serializable id) {
if (updateIds == null) {
updateIds = new ArrayList<Serializable>();
}
updateIds.add(id);
}
private void addDeleteId(Serializable id) {
if (deleteIds == null) {
deleteIds = new ArrayList<Serializable>();
}
deleteIds.add(id);
}
public BeanDescriptor<?> getBeanDescriptor() {
return beanDescriptor;
}
/**
* Return the Descriptor Id. A more compact alternative to using the
* beanType.
*/
public String getDescriptorId() {
return descriptorId;
}
public List<Serializable> getInsertIds() {
return insertIds;
}
public List<Serializable> getUpdateIds() {
return updateIds;
}
public List<Serializable> getDeleteIds() {
return deleteIds;
}
public void setBeanDescriptor(BeanDescriptor<?> beanDescriptor) {
this.beanDescriptor = beanDescriptor;
}
/**
* Notify the cache and local BeanPersistListener of this event that came
* from another server in the cluster.
*/
public void notifyCacheAndListener() {
BeanPersistListener listener = beanDescriptor.getPersistListener();
// any change invalidates the query cache
beanDescriptor.queryCacheClear();
if (insertIds != null) {
if (listener != null) {
// notify listener
for (int i = 0; i < insertIds.size(); i++) {
listener.remoteInsert(insertIds.get(i));
}
}
}
if (updateIds != null) {
for (int i = 0; i < updateIds.size(); i++) {
Serializable id = updateIds.get(i);
// remove from cache
beanDescriptor.cacheBeanRemove(id);
if (listener != null) {
// notify listener
listener.remoteInsert(id);
}
}
}
if (deleteIds != null) {
for (int i = 0; i < deleteIds.size(); i++) {
Serializable id = deleteIds.get(i);
// remove from cache
beanDescriptor.cacheBeanRemove(id);
if (listener != null) {
// notify listener
listener.remoteInsert(id);
}
}
}
}
}
package com.avaje.ebeaninternal.server.transaction;
import java.io.DataInput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.avaje.ebean.event.BeanPersistListener;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.server.cluster.BinaryMessage;
import com.avaje.ebeaninternal.server.cluster.BinaryMessageList;
import com.avaje.ebeaninternal.server.core.PersistRequest;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
/**
* Wraps the information representing a Inserted Updated or Deleted Bean.
* <p>
* This information is broadcast across the cluster so that remote BeanListeners
* are notified of the inserts updates and deletes that occured.
* </p>
* <p>
* You control it the data is broadcast and what data is broadcast by the
* BeanListener.getClusterData() method. It is guessed that often just the Id
* property or perhaps a few properties in a Map will be broadcast to reduce the
* size of data sent around the network.
* </p>
*/
public class BeanPersistIds implements Serializable {
private static final long serialVersionUID = 8389469180931531409L;
private transient BeanDescriptor<?> beanDescriptor;
private final String descriptorId;
private ArrayList<Serializable> insertIds;
private ArrayList<Serializable> updateIds;
private ArrayList<Serializable> deleteIds;
/**
* Create the payload.
*/
public BeanPersistIds(BeanDescriptor<?> desc) {
this.beanDescriptor = desc;
this.descriptorId = desc.getDescriptorId();
}
public static BeanPersistIds readBinaryMessage(SpiEbeanServer server, DataInput dataInput) throws IOException {
String descriptorId = dataInput.readUTF();
BeanDescriptor<?> desc = server.getBeanDescriptorById(descriptorId);
BeanPersistIds bp = new BeanPersistIds(desc);
bp.read(dataInput);
return bp;
}
private void read(DataInput dataInput) throws IOException {
IdBinder idBinder = beanDescriptor.getIdBinder();
int iudType = dataInput.readInt();
ArrayList<Serializable> idList = readIdList(dataInput, idBinder);
switch (iudType) {
case 0:
insertIds = idList;
break;
case 1:
updateIds = idList;
break;
case 2:
deleteIds = idList;
break;
default:
throw new RuntimeException("Invalid iudType "+iudType);
}
}
/**
* Write the contents into a BinaryMessage form.
* <p>
* For a RemoteBeanPersist with a large number of id's note that this is
* broken up into many BinaryMessages each with a maximum of 100 ids. This
* enables the contents of a large RemoteTransactionEvent to be split up
* across multiple Packets.
* </p>
*/
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
writeIdList(beanDescriptor, 0, insertIds, msgList);
writeIdList(beanDescriptor, 1, updateIds, msgList);
writeIdList(beanDescriptor, 2, deleteIds, msgList);
}
private ArrayList<Serializable> readIdList(DataInput dataInput, IdBinder idBinder) throws IOException {
int count = dataInput.readInt();
if (count < 1) {
return null;
}
ArrayList<Serializable> idList = new ArrayList<Serializable>(count);
for (int i = 0; i < count; i++) {
Object id = idBinder.readData(dataInput);
idList.add((Serializable) id);
}
return idList;
}
/**
* Write a BinaryMessage containing the descriptorId, iudType and list of Id
* values.
* <p>
* Note that a given BinaryMessage has a maximum of 100 Ids. This is due to
* the limit of UDP packet sizes. We break up the RemoteBeanPersist into
* potentially many smaller BinaryMessages which may be put into multiple
* Packets.
* </p>
*/
private void writeIdList(BeanDescriptor<?> desc, int iudType, ArrayList<Serializable> idList,
BinaryMessageList msgList) throws IOException {
IdBinder idBinder = desc.getIdBinder();
int count = idList == null ? 0 : idList.size();
if (count > 0) {
int loop = 0;
int i = 0;
int eof = idList.size();
do {
++loop;
int endOfLoop = Math.min(eof, loop * 100);
BinaryMessage m = new BinaryMessage(endOfLoop * 4 + 20);
DataOutputStream os = m.getOs();
os.writeInt(BinaryMessage.TYPE_BEANIUD);
os.writeUTF(descriptorId);
os.writeInt(iudType);
os.writeInt(count);
for (; i < endOfLoop; i++) {
Serializable idValue = idList.get(i);
idBinder.writeData(os, idValue);
}
os.flush();
msgList.add(m);
} while (i < eof);
}
}
public String toString() {
StringBuilder sb = new StringBuilder();
if (beanDescriptor != null) {
sb.append(beanDescriptor.getFullName());
} else {
sb.append("descId:").append(descriptorId);
}
if (insertIds != null) {
sb.append(" insertIds:").append(insertIds);
}
if (updateIds != null) {
sb.append(" updateIds:").append(updateIds);
}
if (deleteIds != null) {
sb.append(" deleteIds:").append(deleteIds);
}
return sb.toString();
}
public void addId(PersistRequest.Type type, Serializable id) {
switch (type) {
case INSERT:
addInsertId(id);
break;
case UPDATE:
addUpdateId(id);
break;
case DELETE:
addDeleteId(id);
break;
default:
break;
}
}
private void addInsertId(Serializable id) {
if (insertIds == null) {
insertIds = new ArrayList<Serializable>();
}
insertIds.add(id);
}
private void addUpdateId(Serializable id) {
if (updateIds == null) {
updateIds = new ArrayList<Serializable>();
}
updateIds.add(id);
}
private void addDeleteId(Serializable id) {
if (deleteIds == null) {
deleteIds = new ArrayList<Serializable>();
}
deleteIds.add(id);
}
public BeanDescriptor<?> getBeanDescriptor() {
return beanDescriptor;
}
/**
* Return the Descriptor Id. A more compact alternative to using the
* beanType.
*/
public String getDescriptorId() {
return descriptorId;
}
public List<Serializable> getInsertIds() {
return insertIds;
}
public List<Serializable> getUpdateIds() {
return updateIds;
}
public List<Serializable> getDeleteIds() {
return deleteIds;
}
public void setBeanDescriptor(BeanDescriptor<?> beanDescriptor) {
this.beanDescriptor = beanDescriptor;
}
/**
* Notify the cache and local BeanPersistListener of this event that came
* from another server in the cluster.
*/
public void notifyCacheAndListener() {
BeanPersistListener listener = beanDescriptor.getPersistListener();
// any change invalidates the query cache
beanDescriptor.queryCacheClear();
if (insertIds != null) {
if (listener != null) {
// notify listener
for (int i = 0; i < insertIds.size(); i++) {
listener.remoteInsert(insertIds.get(i));
}
}
}
if (updateIds != null) {
for (int i = 0; i < updateIds.size(); i++) {
Serializable id = updateIds.get(i);
// remove from cache
beanDescriptor.cacheBeanRemove(id);
if (listener != null) {
// notify listener
listener.remoteInsert(id);
}
}
}
if (deleteIds != null) {
for (int i = 0; i < deleteIds.size(); i++) {
Serializable id = deleteIds.get(i);
// remove from cache
beanDescriptor.cacheBeanRemove(id);
if (listener != null) {
// notify listener
listener.remoteInsert(id);
}
}
}
}
}
@@ -1,210 +1,210 @@
package com.avaje.ebeaninternal.server.transaction;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.persistence.Entity;
import com.avaje.ebean.bean.PersistenceContext;
import com.avaje.ebeaninternal.api.Monitor;
/**
* Default implementation of PersistenceContext.
* <p>
* Ensures only one instance of a bean is used according to its type and unique
* id.
* </p>
* <p>
* PersistenceContext lives on a Transaction and as such is expected to only
* have a single thread accessing it at a time. This is not expected to be used
* concurrently.
* </p>
* <p>
* Duplicate beans are ones having the same type and unique id value. These are
* considered duplicates and replaced by the bean instance that was already
* loaded into the PersistanceContext.
* </p>
*/
public final class DefaultPersistenceContext implements PersistenceContext {
/**
* Map used hold caches. One cache per bean type.
*/
private final HashMap<String, ClassContext> typeCache = new HashMap<String, ClassContext>();
private final Monitor monitor = new Monitor();
/**
* Create a new PersistanceContext.
*/
public DefaultPersistenceContext() {
}
/**
* Set an object into the PersistanceContext.
*/
public void put(Object id, Object bean) {
synchronized (monitor) {
getClassContext(bean.getClass()).put(id, bean);
}
}
public Object putIfAbsent(Object id, Object bean) {
synchronized (monitor) {
return getClassContext(bean.getClass()).putIfAbsent(id, bean);
}
}
/**
* Return an object given its type and unique id.
*/
public Object get(Class<?> beanType, Object id) {
synchronized (monitor) {
return getClassContext(beanType).get(id);
}
}
public WithOption getWithOption(Class<?> beanType, Object id) {
synchronized (monitor) {
return getClassContext(beanType).getWithOption(id);
}
}
/**
* Return the number of beans of the given type in the persistence context.
*/
public int size(Class<?> beanType) {
synchronized (monitor) {
ClassContext classMap = typeCache.get(beanType.getName());
return classMap == null ? 0 : classMap.size();
}
}
/**
* Clear the PersistenceContext.
*/
public void clear() {
synchronized (monitor) {
typeCache.clear();
}
}
public void clear(Class<?> beanType) {
synchronized (monitor) {
ClassContext classMap = typeCache.get(beanType.getName());
if (classMap != null) {
classMap.clear();
}
}
}
public void deleted(Class<?> beanType, Object id) {
synchronized (monitor) {
ClassContext classMap = typeCache.get(beanType.getName());
if (classMap != null && id != null) {
classMap.deleted(id);
}
}
}
public void clear(Class<?> beanType, Object id) {
synchronized (monitor) {
ClassContext classMap = typeCache.get(beanType.getName());
if (classMap != null && id != null) {
classMap.remove(id);
}
}
}
public String toString() {
synchronized (monitor) {
return typeCache.toString();
}
}
private ClassContext getClassContext(Class<?> beanType) {
String clsName = getBeanBaseType(beanType).getName();
ClassContext classMap = typeCache.get(clsName);
if (classMap == null) {
classMap = new ClassContext();
typeCache.put(clsName, classMap);
}
return classMap;
}
private Class<?> getBeanBaseType(Class<?> beanType) {
Class<?> parent = beanType.getSuperclass();
while (parent != null && parent.isAnnotationPresent(Entity.class)) {
beanType = parent;
parent = parent.getSuperclass();
}
return beanType;
}
private static class ClassContext {
private final Map<Object, Object> map = new HashMap<Object, Object>();
private Set<Object> deleteSet;
private ClassContext() {
}
public String toString() {
return "size:" + map.size();
}
private WithOption getWithOption(Object id) {
if (deleteSet != null && deleteSet.contains(id)) {
return WithOption.DELETED;
}
Object bean = map.get(id);
return (bean == null) ? null : new WithOption(bean);
}
private Object get(Object id) {
return map.get(id);
}
private Object putIfAbsent(Object id, Object bean) {
Object existingValue = map.get(id);
if (existingValue != null) {
// it is not absent
return existingValue;
}
// put the new value and return null indicating the put was successful
map.put(id, bean);
return null;
}
private void put(Object id, Object b) {
map.put(id, b);
}
private int size() {
return map.size();
}
private void clear() {
map.clear();
}
private Object remove(Object id) {
return map.remove(id);
}
private void deleted(Object id) {
if (deleteSet == null) {
deleteSet = new HashSet<Object>();
}
deleteSet.add(id);
map.remove(id);
}
}
}
package com.avaje.ebeaninternal.server.transaction;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.persistence.Entity;
import com.avaje.ebean.bean.PersistenceContext;
import com.avaje.ebeaninternal.api.Monitor;
/**
* Default implementation of PersistenceContext.
* <p>
* Ensures only one instance of a bean is used according to its type and unique
* id.
* </p>
* <p>
* PersistenceContext lives on a Transaction and as such is expected to only
* have a single thread accessing it at a time. This is not expected to be used
* concurrently.
* </p>
* <p>
* Duplicate beans are ones having the same type and unique id value. These are
* considered duplicates and replaced by the bean instance that was already
* loaded into the PersistanceContext.
* </p>
*/
public final class DefaultPersistenceContext implements PersistenceContext {
/**
* Map used hold caches. One cache per bean type.
*/
private final HashMap<String, ClassContext> typeCache = new HashMap<String, ClassContext>();
private final Monitor monitor = new Monitor();
/**
* Create a new PersistanceContext.
*/
public DefaultPersistenceContext() {
}
/**
* Set an object into the PersistanceContext.
*/
public void put(Object id, Object bean) {
synchronized (monitor) {
getClassContext(bean.getClass()).put(id, bean);
}
}
public Object putIfAbsent(Object id, Object bean) {
synchronized (monitor) {
return getClassContext(bean.getClass()).putIfAbsent(id, bean);
}
}
/**
* Return an object given its type and unique id.
*/
public Object get(Class<?> beanType, Object id) {
synchronized (monitor) {
return getClassContext(beanType).get(id);
}
}
public WithOption getWithOption(Class<?> beanType, Object id) {
synchronized (monitor) {
return getClassContext(beanType).getWithOption(id);
}
}
/**
* Return the number of beans of the given type in the persistence context.
*/
public int size(Class<?> beanType) {
synchronized (monitor) {
ClassContext classMap = typeCache.get(beanType.getName());
return classMap == null ? 0 : classMap.size();
}
}
/**
* Clear the PersistenceContext.
*/
public void clear() {
synchronized (monitor) {
typeCache.clear();
}
}
public void clear(Class<?> beanType) {
synchronized (monitor) {
ClassContext classMap = typeCache.get(beanType.getName());
if (classMap != null) {
classMap.clear();
}
}
}
public void deleted(Class<?> beanType, Object id) {
synchronized (monitor) {
ClassContext classMap = typeCache.get(beanType.getName());
if (classMap != null && id != null) {
classMap.deleted(id);
}
}
}
public void clear(Class<?> beanType, Object id) {
synchronized (monitor) {
ClassContext classMap = typeCache.get(beanType.getName());
if (classMap != null && id != null) {
classMap.remove(id);
}
}
}
public String toString() {
synchronized (monitor) {
return typeCache.toString();
}
}
private ClassContext getClassContext(Class<?> beanType) {
String clsName = getBeanBaseType(beanType).getName();
ClassContext classMap = typeCache.get(clsName);
if (classMap == null) {
classMap = new ClassContext();
typeCache.put(clsName, classMap);
}
return classMap;
}
private Class<?> getBeanBaseType(Class<?> beanType) {
Class<?> parent = beanType.getSuperclass();
while (parent != null && parent.isAnnotationPresent(Entity.class)) {
beanType = parent;
parent = parent.getSuperclass();
}
return beanType;
}
private static class ClassContext {
private final Map<Object, Object> map = new HashMap<Object, Object>();
private Set<Object> deleteSet;
private ClassContext() {
}
public String toString() {
return "size:" + map.size();
}
private WithOption getWithOption(Object id) {
if (deleteSet != null && deleteSet.contains(id)) {
return WithOption.DELETED;
}
Object bean = map.get(id);
return (bean == null) ? null : new WithOption(bean);
}
private Object get(Object id) {
return map.get(id);
}
private Object putIfAbsent(Object id, Object bean) {
Object existingValue = map.get(id);
if (existingValue != null) {
// it is not absent
return existingValue;
}
// put the new value and return null indicating the put was successful
map.put(id, bean);
return null;
}
private void put(Object id, Object b) {
map.put(id, b);
}
private int size() {
return map.size();
}
private void clear() {
map.clear();
}
private Object remove(Object id) {
return map.remove(id);
}
private void deleted(Object id) {
if (deleteSet == null) {
deleteSet = new HashSet<Object>();
}
deleteSet.add(id);
map.remove(id);
}
}
}
@@ -1,128 +1,128 @@
package com.avaje.ebeaninternal.server.transaction;
import com.avaje.ebeaninternal.api.SpiTransaction;
import com.avaje.ebeaninternal.server.transaction.TransactionMap.State;
/**
* Used by EbeanMgr to store its Transactions in a ThreadLocal. This way the
* transaction objects don't have to passed around.
*/
public final class DefaultTransactionThreadLocal {
private static ThreadLocal<TransactionMap> local = new ThreadLocal<TransactionMap>() {
protected synchronized TransactionMap initialValue() {
return new TransactionMap();
}
};
/**
* Not allowed.
*/
private DefaultTransactionThreadLocal() {
}
/**
* Return the current TransactionState for a given serverName. This is for the
* local thread of course.
*/
private static TransactionMap.State getState(String serverName) {
return local.get().getStateWithCreate(serverName);
}
/**
* Set a new Transaction for this serverName and Thread.
*/
public static void set(String serverName, SpiTransaction trans) {
getState(serverName).set(trans);
}
/**
* A mechanism to get the transaction out of the thread local by replacing it
* with a 'proxy'.
* <p>
* Used for background fetching. Replaces the current transaction with a
* 'dummy' transaction. The current transaction is given to the background
* thread so it can continue the fetch.
* </p>
*/
public static void replace(String serverName, SpiTransaction trans) {
getState(serverName).replace(trans);
}
/**
* Return the current Transaction for this serverName and Thread.
*/
public static SpiTransaction get(String serverName) {
TransactionMap map = local.get();
State state = map.getState(serverName);
SpiTransaction t = (state == null) ? null : state.transaction;
if (map.isEmpty()) {
local.remove();
}
return t;
}
/**
* Commit the current transaction.
*/
public static void commit(String serverName) {
TransactionMap map = local.get();
State state = map.removeState(serverName);
if (state == null) {
throw new IllegalStateException("No current transaction for [" + serverName + "]");
}
state.commit();
if (map.isEmpty()) {
local.remove();
}
}
/**
* Rollback the current transaction.
*/
public static void rollback(String serverName) {
TransactionMap map = local.get();
State state = map.removeState(serverName);
if (state == null) {
throw new IllegalStateException("No current transaction for [" + serverName + "]");
}
state.rollback();
if (map.isEmpty()) {
local.remove();
}
}
/**
* If the transaction has not been committed then roll it back.
* <p>
* Designed to be put in a finally block instead of a rollback() in each catch
* block.
*
* <pre>
* Ebean.beingTransaction();
* try {
* // ... perform some actions in a single transaction
*
* Ebean.commitTransaction();
*
* } finally {
* // ensure transaction ended. If some error occurred then rollback()
* Ebean.endTransaction();
* }
* </pre>
*
* </p>
*/
public static void end(String serverName) {
TransactionMap map = local.get();
State state = map.removeState(serverName);
if (state != null) {
state.end();
}
if (map.isEmpty()) {
local.remove();
}
}
}
package com.avaje.ebeaninternal.server.transaction;
import com.avaje.ebeaninternal.api.SpiTransaction;
import com.avaje.ebeaninternal.server.transaction.TransactionMap.State;
/**
* Used by EbeanMgr to store its Transactions in a ThreadLocal. This way the
* transaction objects don't have to passed around.
*/
public final class DefaultTransactionThreadLocal {
private static ThreadLocal<TransactionMap> local = new ThreadLocal<TransactionMap>() {
protected synchronized TransactionMap initialValue() {
return new TransactionMap();
}
};
/**
* Not allowed.
*/
private DefaultTransactionThreadLocal() {
}
/**
* Return the current TransactionState for a given serverName. This is for the
* local thread of course.
*/
private static TransactionMap.State getState(String serverName) {
return local.get().getStateWithCreate(serverName);
}
/**
* Set a new Transaction for this serverName and Thread.
*/
public static void set(String serverName, SpiTransaction trans) {
getState(serverName).set(trans);
}
/**
* A mechanism to get the transaction out of the thread local by replacing it
* with a 'proxy'.
* <p>
* Used for background fetching. Replaces the current transaction with a
* 'dummy' transaction. The current transaction is given to the background
* thread so it can continue the fetch.
* </p>
*/
public static void replace(String serverName, SpiTransaction trans) {
getState(serverName).replace(trans);
}
/**
* Return the current Transaction for this serverName and Thread.
*/
public static SpiTransaction get(String serverName) {
TransactionMap map = local.get();
State state = map.getState(serverName);
SpiTransaction t = (state == null) ? null : state.transaction;
if (map.isEmpty()) {
local.remove();
}
return t;
}
/**
* Commit the current transaction.
*/
public static void commit(String serverName) {
TransactionMap map = local.get();
State state = map.removeState(serverName);
if (state == null) {
throw new IllegalStateException("No current transaction for [" + serverName + "]");
}
state.commit();
if (map.isEmpty()) {
local.remove();
}
}
/**
* Rollback the current transaction.
*/
public static void rollback(String serverName) {
TransactionMap map = local.get();
State state = map.removeState(serverName);
if (state == null) {
throw new IllegalStateException("No current transaction for [" + serverName + "]");
}
state.rollback();
if (map.isEmpty()) {
local.remove();
}
}
/**
* If the transaction has not been committed then roll it back.
* <p>
* Designed to be put in a finally block instead of a rollback() in each catch
* block.
*
* <pre>
* Ebean.beingTransaction();
* try {
* // ... perform some actions in a single transaction
*
* Ebean.commitTransaction();
*
* } finally {
* // ensure transaction ended. If some error occurred then rollback()
* Ebean.endTransaction();
* }
* </pre>
*
* </p>
*/
public static void end(String serverName) {
TransactionMap map = local.get();
State state = map.removeState(serverName);
if (state != null) {
state.end();
}
if (map.isEmpty()) {
local.remove();
}
}
}
@@ -1,76 +1,76 @@
package com.avaje.ebeaninternal.server.transaction;
import java.io.Serializable;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.avaje.ebeaninternal.server.core.PersistRequest;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
/**
* Beans deleted by Id used for updating L2 Cache.
*/
public final class DeleteByIdMap {
private final Map<String,BeanPersistIds> beanMap = new LinkedHashMap<String, BeanPersistIds>();
public String toString() {
return beanMap.toString();
}
public void notifyCache() {
for (BeanPersistIds deleteIds : beanMap.values()) {
BeanDescriptor<?> d = deleteIds.getBeanDescriptor();
List<Serializable> idValues = deleteIds.getDeleteIds();
if (idValues != null){
d.queryCacheClear();
for (int i = 0; i < idValues.size(); i++) {
d.cacheBeanRemove(idValues.get(i));
}
}
}
}
public boolean isEmpty() {
return beanMap.isEmpty();
}
public Collection<BeanPersistIds> values() {
return beanMap.values();
}
/**
* Add a Insert Update or Delete payload.
*/
public void add(BeanDescriptor<?> desc, Object id) {
BeanPersistIds r = getPersistIds(desc);
r.addId(PersistRequest.Type.DELETE, (Serializable)id);
}
/**
* Add a List of Insert Update or Delete Id's.
*/
public void addList(BeanDescriptor<?> desc, List<Object> idList) {
BeanPersistIds r = getPersistIds(desc);
for (int i = 0; i < idList.size(); i++) {
r.addId(PersistRequest.Type.DELETE, (Serializable) idList.get(i));
}
}
private BeanPersistIds getPersistIds(BeanDescriptor<?> desc) {
String beanType = desc.getFullName();
BeanPersistIds r = beanMap.get(beanType);
if (r == null){
r = new BeanPersistIds(desc);
beanMap.put(beanType, r);
}
return r;
}
}
package com.avaje.ebeaninternal.server.transaction;
import java.io.Serializable;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.avaje.ebeaninternal.server.core.PersistRequest;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
/**
* Beans deleted by Id used for updating L2 Cache.
*/
public final class DeleteByIdMap {
private final Map<String,BeanPersistIds> beanMap = new LinkedHashMap<String, BeanPersistIds>();
public String toString() {
return beanMap.toString();
}
public void notifyCache() {
for (BeanPersistIds deleteIds : beanMap.values()) {
BeanDescriptor<?> d = deleteIds.getBeanDescriptor();
List<Serializable> idValues = deleteIds.getDeleteIds();
if (idValues != null){
d.queryCacheClear();
for (int i = 0; i < idValues.size(); i++) {
d.cacheBeanRemove(idValues.get(i));
}
}
}
}
public boolean isEmpty() {
return beanMap.isEmpty();
}
public Collection<BeanPersistIds> values() {
return beanMap.values();
}
/**
* Add a Insert Update or Delete payload.
*/
public void add(BeanDescriptor<?> desc, Object id) {
BeanPersistIds r = getPersistIds(desc);
r.addId(PersistRequest.Type.DELETE, (Serializable)id);
}
/**
* Add a List of Insert Update or Delete Id's.
*/
public void addList(BeanDescriptor<?> desc, List<Object> idList) {
BeanPersistIds r = getPersistIds(desc);
for (int i = 0; i < idList.size(); i++) {
r.addId(PersistRequest.Type.DELETE, (Serializable) idList.get(i));
}
}
private BeanPersistIds getPersistIds(BeanDescriptor<?> desc) {
String beanType = desc.getFullName();
BeanPersistIds r = beanMap.get(beanType);
if (r == null){
r = new BeanPersistIds(desc);
beanMap.put(beanType, r);
}
return r;
}
}
@@ -1,48 +1,48 @@
package com.avaje.ebeaninternal.server.transaction;
import com.avaje.ebean.config.ExternalTransactionManager;
import com.avaje.ebeaninternal.api.SpiTransaction;
/**
* A TransactionScopeManager aware of external transaction managers.
*/
public class ExternalTransactionScopeManager extends TransactionScopeManager {
final ExternalTransactionManager externalManager;
/**
* Instantiates transaction scope manager.
*
* @param transactionManager the transaction manager
*/
public ExternalTransactionScopeManager(TransactionManager transactionManager, ExternalTransactionManager externalManager) {
super(transactionManager);
this.externalManager = externalManager;
}
public void commit() {
DefaultTransactionThreadLocal.commit(serverName);
}
public void end() {
DefaultTransactionThreadLocal.end(serverName);
}
public SpiTransaction get() {
return (SpiTransaction)externalManager.getCurrentTransaction();
}
public void replace(SpiTransaction trans) {
DefaultTransactionThreadLocal.replace(serverName, trans);
}
public void rollback() {
DefaultTransactionThreadLocal.rollback(serverName);
}
public void set(SpiTransaction trans) {
DefaultTransactionThreadLocal.set(serverName, trans);
}
}
package com.avaje.ebeaninternal.server.transaction;
import com.avaje.ebean.config.ExternalTransactionManager;
import com.avaje.ebeaninternal.api.SpiTransaction;
/**
* A TransactionScopeManager aware of external transaction managers.
*/
public class ExternalTransactionScopeManager extends TransactionScopeManager {
final ExternalTransactionManager externalManager;
/**
* Instantiates transaction scope manager.
*
* @param transactionManager the transaction manager
*/
public ExternalTransactionScopeManager(TransactionManager transactionManager, ExternalTransactionManager externalManager) {
super(transactionManager);
this.externalManager = externalManager;
}
public void commit() {
DefaultTransactionThreadLocal.commit(serverName);
}
public void end() {
DefaultTransactionThreadLocal.end(serverName);
}
public SpiTransaction get() {
return (SpiTransaction)externalManager.getCurrentTransaction();
}
public void replace(SpiTransaction trans) {
DefaultTransactionThreadLocal.replace(serverName, trans);
}
public void rollback() {
DefaultTransactionThreadLocal.rollback(serverName);
}
public void set(SpiTransaction trans) {
DefaultTransactionThreadLocal.set(serverName, trans);
}
}
@@ -1,117 +1,117 @@
package com.avaje.ebeaninternal.server.transaction;
import java.sql.SQLException;
import javax.persistence.PersistenceException;
import javax.sql.DataSource;
import javax.transaction.Status;
import javax.transaction.UserTransaction;
/**
* Jta based transaction.
*/
public class JtaTransaction extends JdbcTransaction {
private UserTransaction userTransaction;
private DataSource dataSource;
private boolean commmitted = false;
private boolean newTransaction = false;
/**
* Create the JtaTransaction.
*/
public JtaTransaction(String id, boolean explicit, UserTransaction utx, DataSource ds, TransactionManager manager) {
super(id, explicit, null, manager);
userTransaction = utx;
dataSource = ds;
try {
newTransaction = userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION;
if (newTransaction) {
userTransaction.begin();
}
} catch (Exception e) {
throw new PersistenceException(e);
}
try {
// Open JDBC Connection
this.connection = dataSource.getConnection();
if (connection == null) {
throw new PersistenceException("The DataSource returned a null connection.");
}
if (connection.getAutoCommit()) {
connection.setAutoCommit(false);
}
} catch (SQLException e) {
throw new PersistenceException(e);
}
}
/**
* Commit the transaction.
*/
public void commit() {
if (commmitted) {
throw new PersistenceException("This transaction has already been committed.");
}
try {
try {
if (newTransaction) {
userTransaction.commit();
}
notifyCommit();
} finally {
close();
}
} catch (Exception e) {
throw new PersistenceException(e);
}
commmitted = true;
}
public void rollback() {
rollback(null);
}
/**
* Rollback the transaction.
*/
public void rollback(Throwable e) {
if (!commmitted) {
try {
try {
if (userTransaction != null) {
if (newTransaction) {
userTransaction.rollback();
} else {
userTransaction.setRollbackOnly();
}
}
notifyRollback(e);
} finally {
closeConnection();
}
} catch (Exception ex) {
throw new PersistenceException(ex);
}
}
}
/**
* Close the underlying connection.
*/
private void closeConnection() throws SQLException {
if (connection != null) {
connection.close();
connection = null;
}
}
}
package com.avaje.ebeaninternal.server.transaction;
import java.sql.SQLException;
import javax.persistence.PersistenceException;
import javax.sql.DataSource;
import javax.transaction.Status;
import javax.transaction.UserTransaction;
/**
* Jta based transaction.
*/
public class JtaTransaction extends JdbcTransaction {
private UserTransaction userTransaction;
private DataSource dataSource;
private boolean commmitted = false;
private boolean newTransaction = false;
/**
* Create the JtaTransaction.
*/
public JtaTransaction(String id, boolean explicit, UserTransaction utx, DataSource ds, TransactionManager manager) {
super(id, explicit, null, manager);
userTransaction = utx;
dataSource = ds;
try {
newTransaction = userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION;
if (newTransaction) {
userTransaction.begin();
}
} catch (Exception e) {
throw new PersistenceException(e);
}
try {
// Open JDBC Connection
this.connection = dataSource.getConnection();
if (connection == null) {
throw new PersistenceException("The DataSource returned a null connection.");
}
if (connection.getAutoCommit()) {
connection.setAutoCommit(false);
}
} catch (SQLException e) {
throw new PersistenceException(e);
}
}
/**
* Commit the transaction.
*/
public void commit() {
if (commmitted) {
throw new PersistenceException("This transaction has already been committed.");
}
try {
try {
if (newTransaction) {
userTransaction.commit();
}
notifyCommit();
} finally {
close();
}
} catch (Exception e) {
throw new PersistenceException(e);
}
commmitted = true;
}
public void rollback() {
rollback(null);
}
/**
* Rollback the transaction.
*/
public void rollback(Throwable e) {
if (!commmitted) {
try {
try {
if (userTransaction != null) {
if (newTransaction) {
userTransaction.rollback();
} else {
userTransaction.setRollbackOnly();
}
}
notifyRollback(e);
} finally {
closeConnection();
}
} catch (Exception ex) {
throw new PersistenceException(ex);
}
}
}
/**
* Close the underlying connection.
*/
private void closeConnection() throws SQLException {
if (connection != null) {
connection.close();
connection = null;
}
}
}
@@ -1,229 +1,229 @@
package com.avaje.ebeaninternal.server.transaction;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.PersistenceException;
import javax.sql.DataSource;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.Status;
import javax.transaction.Synchronization;
import javax.transaction.SystemException;
import javax.transaction.TransactionSynchronizationRegistry;
import javax.transaction.UserTransaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.avaje.ebean.config.ExternalTransactionManager;
import com.avaje.ebeaninternal.api.SpiTransaction;
/**
* Hook into external JTA transaction manager.
*
* @author rbygrave
*/
public class JtaTransactionManager implements ExternalTransactionManager {
private static final Logger logger = LoggerFactory.getLogger(JtaTransactionManager.class);
private static final String EBEAN_TXN_RESOURCE = "EBEAN_TXN_RESOURCE";
/**
* The data source.
*/
private DataSource dataSource;
/**
* The Ebean transaction manager.
*/
private TransactionManager transactionManager;
/**
* The EbeanServer name.
*/
private String serverName;
/**
* Instantiates a new spring aware transaction scope manager.
*/
public JtaTransactionManager() {
}
/**
* Initialise this with the Ebean internal transaction manager.
*/
public void setTransactionManager(Object txnMgr) {
// RB: At this stage not exposing TransactionManager to
// the public API and hence the Object type and casting here
this.transactionManager = (TransactionManager) txnMgr;
this.dataSource = transactionManager.getDataSource();
this.serverName = transactionManager.getServerName();
}
private TransactionSynchronizationRegistry getSyncRegistry() {
try {
InitialContext ctx = new InitialContext();
return (TransactionSynchronizationRegistry)ctx.lookup("java:comp/TransactionSynchronizationRegistry");
} catch (NamingException e){
throw new PersistenceException(e);
}
}
private UserTransaction getUserTransaction() {
try {
InitialContext ctx = new InitialContext();
return (UserTransaction) ctx.lookup("java:comp/UserTransaction");
} catch (NamingException e){
// assuming CMT
return new DummyUserTransaction();
}
}
/**
* Looks for a current Spring managed transaction and wraps/returns that as a Ebean transaction.
* <p>
* Returns null if there is no current spring transaction (lazy loading outside a spring txn etc).
* </p>
*/
public Object getCurrentTransaction() {
TransactionSynchronizationRegistry syncRegistry = getSyncRegistry();
SpiTransaction t = (SpiTransaction)syncRegistry.getResource(EBEAN_TXN_RESOURCE);
if (t != null){
// we have already seen this transaction
return t;
}
// check current Ebean transaction
SpiTransaction currentEbeanTransaction = DefaultTransactionThreadLocal.get(serverName);
if (currentEbeanTransaction != null){
// NOT expecting this so log WARNING
String msg = "JTA Transaction - no current txn BUT using current Ebean one "+currentEbeanTransaction.getId();
logger.warn(msg);
return currentEbeanTransaction;
}
UserTransaction ut = getUserTransaction();
if (ut == null){
// no current JTA transaction
if (logger.isDebugEnabled()){
logger.debug("JTA Transaction - no current txn");
}
return null;
}
// This is a transaction that Ebean has not seen before.
// "wrap" it in a Ebean specific JtaTransaction
String txnId = String.valueOf(System.currentTimeMillis());
JtaTransaction newTrans = new JtaTransaction(txnId, true, ut, dataSource, transactionManager);
// create and register transaction listener
JtaTxnListener txnListener = createJtaTxnListener(newTrans);
syncRegistry.putResource(EBEAN_TXN_RESOURCE, newTrans);
syncRegistry.registerInterposedSynchronization(txnListener);
// also put in Ebean ThreadLocal
DefaultTransactionThreadLocal.set(serverName, newTrans);
return newTrans;
}
/**
* Create a listener to register with JTA to enable Ebean to be
* notified when transactions commit and rollback.
* <p>
* This is used by Ebean to notify it's appropriate listeners and maintain it's server
* cache etc.
* </p>
*/
private JtaTxnListener createJtaTxnListener(SpiTransaction t) {
return new JtaTxnListener(transactionManager, t);
}
private static class DummyUserTransaction implements UserTransaction {
public void begin() throws NotSupportedException, SystemException {
}
public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
SecurityException, IllegalStateException, SystemException {
}
public int getStatus() throws SystemException {
return 0;
}
public void rollback() throws IllegalStateException, SecurityException, SystemException {
}
public void setRollbackOnly() throws IllegalStateException, SystemException {
}
public void setTransactionTimeout(int seconds) throws SystemException {
}
}
/**
* A JTA Transaction Synchronization that we register to get notified when a
* managed transaction has been committed or rolled back.
* <p>
* When Ebean is notified (of the commit/rollback) it can then manage its
* cache, notify BeanPersistListeners etc.
* </p>
*/
private static class JtaTxnListener implements Synchronization {
private final TransactionManager transactionManager;
private final SpiTransaction transaction;
private final String serverName;
private JtaTxnListener(TransactionManager transactionManager, SpiTransaction t){
this.transactionManager = transactionManager;
this.transaction = t;
this.serverName = transactionManager.getServerName();
}
public void beforeCompletion() {
// Future note: for JPA2 locking we will
// have beforeCommit events to fire
}
public void afterCompletion(int status) {
switch (status) {
case Status.STATUS_COMMITTED:
if (logger.isDebugEnabled()){
logger.debug("Jta Txn ["+transaction.getId()+"] committed");
}
transactionManager.notifyOfCommit(transaction);
// Remove this transaction object as it is completed
DefaultTransactionThreadLocal.replace(serverName, null);
break;
case Status.STATUS_ROLLEDBACK:
if (logger.isDebugEnabled()){
logger.debug("Jta Txn ["+transaction.getId()+"] rollback");
}
transactionManager.notifyOfRollback(transaction, null);
// Remove this transaction object as it is completed
DefaultTransactionThreadLocal.replace(serverName, null);
break;
default:
logger.debug("Jta Txn ["+transaction.getId()+"] status:"+status);
}
}
}
}
package com.avaje.ebeaninternal.server.transaction;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.PersistenceException;
import javax.sql.DataSource;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.Status;
import javax.transaction.Synchronization;
import javax.transaction.SystemException;
import javax.transaction.TransactionSynchronizationRegistry;
import javax.transaction.UserTransaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.avaje.ebean.config.ExternalTransactionManager;
import com.avaje.ebeaninternal.api.SpiTransaction;
/**
* Hook into external JTA transaction manager.
*
* @author rbygrave
*/
public class JtaTransactionManager implements ExternalTransactionManager {
private static final Logger logger = LoggerFactory.getLogger(JtaTransactionManager.class);
private static final String EBEAN_TXN_RESOURCE = "EBEAN_TXN_RESOURCE";
/**
* The data source.
*/
private DataSource dataSource;
/**
* The Ebean transaction manager.
*/
private TransactionManager transactionManager;
/**
* The EbeanServer name.
*/
private String serverName;
/**
* Instantiates a new spring aware transaction scope manager.
*/
public JtaTransactionManager() {
}
/**
* Initialise this with the Ebean internal transaction manager.
*/
public void setTransactionManager(Object txnMgr) {
// RB: At this stage not exposing TransactionManager to
// the public API and hence the Object type and casting here
this.transactionManager = (TransactionManager) txnMgr;
this.dataSource = transactionManager.getDataSource();
this.serverName = transactionManager.getServerName();
}
private TransactionSynchronizationRegistry getSyncRegistry() {
try {
InitialContext ctx = new InitialContext();
return (TransactionSynchronizationRegistry)ctx.lookup("java:comp/TransactionSynchronizationRegistry");
} catch (NamingException e){
throw new PersistenceException(e);
}
}
private UserTransaction getUserTransaction() {
try {
InitialContext ctx = new InitialContext();
return (UserTransaction) ctx.lookup("java:comp/UserTransaction");
} catch (NamingException e){
// assuming CMT
return new DummyUserTransaction();
}
}
/**
* Looks for a current Spring managed transaction and wraps/returns that as a Ebean transaction.
* <p>
* Returns null if there is no current spring transaction (lazy loading outside a spring txn etc).
* </p>
*/
public Object getCurrentTransaction() {
TransactionSynchronizationRegistry syncRegistry = getSyncRegistry();
SpiTransaction t = (SpiTransaction)syncRegistry.getResource(EBEAN_TXN_RESOURCE);
if (t != null){
// we have already seen this transaction
return t;
}
// check current Ebean transaction
SpiTransaction currentEbeanTransaction = DefaultTransactionThreadLocal.get(serverName);
if (currentEbeanTransaction != null){
// NOT expecting this so log WARNING
String msg = "JTA Transaction - no current txn BUT using current Ebean one "+currentEbeanTransaction.getId();
logger.warn(msg);
return currentEbeanTransaction;
}
UserTransaction ut = getUserTransaction();
if (ut == null){
// no current JTA transaction
if (logger.isDebugEnabled()){
logger.debug("JTA Transaction - no current txn");
}
return null;
}
// This is a transaction that Ebean has not seen before.
// "wrap" it in a Ebean specific JtaTransaction
String txnId = String.valueOf(System.currentTimeMillis());
JtaTransaction newTrans = new JtaTransaction(txnId, true, ut, dataSource, transactionManager);
// create and register transaction listener
JtaTxnListener txnListener = createJtaTxnListener(newTrans);
syncRegistry.putResource(EBEAN_TXN_RESOURCE, newTrans);
syncRegistry.registerInterposedSynchronization(txnListener);
// also put in Ebean ThreadLocal
DefaultTransactionThreadLocal.set(serverName, newTrans);
return newTrans;
}
/**
* Create a listener to register with JTA to enable Ebean to be
* notified when transactions commit and rollback.
* <p>
* This is used by Ebean to notify it's appropriate listeners and maintain it's server
* cache etc.
* </p>
*/
private JtaTxnListener createJtaTxnListener(SpiTransaction t) {
return new JtaTxnListener(transactionManager, t);
}
private static class DummyUserTransaction implements UserTransaction {
public void begin() throws NotSupportedException, SystemException {
}
public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
SecurityException, IllegalStateException, SystemException {
}
public int getStatus() throws SystemException {
return 0;
}
public void rollback() throws IllegalStateException, SecurityException, SystemException {
}
public void setRollbackOnly() throws IllegalStateException, SystemException {
}
public void setTransactionTimeout(int seconds) throws SystemException {
}
}
/**
* A JTA Transaction Synchronization that we register to get notified when a
* managed transaction has been committed or rolled back.
* <p>
* When Ebean is notified (of the commit/rollback) it can then manage its
* cache, notify BeanPersistListeners etc.
* </p>
*/
private static class JtaTxnListener implements Synchronization {
private final TransactionManager transactionManager;
private final SpiTransaction transaction;
private final String serverName;
private JtaTxnListener(TransactionManager transactionManager, SpiTransaction t){
this.transactionManager = transactionManager;
this.transaction = t;
this.serverName = transactionManager.getServerName();
}
public void beforeCompletion() {
// Future note: for JPA2 locking we will
// have beforeCommit events to fire
}
public void afterCompletion(int status) {
switch (status) {
case Status.STATUS_COMMITTED:
if (logger.isDebugEnabled()){
logger.debug("Jta Txn ["+transaction.getId()+"] committed");
}
transactionManager.notifyOfCommit(transaction);
// Remove this transaction object as it is completed
DefaultTransactionThreadLocal.replace(serverName, null);
break;
case Status.STATUS_ROLLEDBACK:
if (logger.isDebugEnabled()){
logger.debug("Jta Txn ["+transaction.getId()+"] rollback");
}
transactionManager.notifyOfRollback(transaction, null);
// Remove this transaction object as it is completed
DefaultTransactionThreadLocal.replace(serverName, null);
break;
default:
logger.debug("Jta Txn ["+transaction.getId()+"] status:"+status);
}
}
}
}
@@ -1,163 +1,163 @@
package com.avaje.ebeaninternal.server.transaction;
import com.avaje.ebeaninternal.api.TransactionEvent;
import com.avaje.ebeaninternal.api.TransactionEventBeans;
import com.avaje.ebeaninternal.api.TransactionEventTable;
import com.avaje.ebeaninternal.api.TransactionEventTable.TableIUD;
import com.avaje.ebeaninternal.server.cluster.ClusterManager;
import com.avaje.ebeaninternal.server.core.PersistRequestBean;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
/**
* Performs post commit processing using a background thread.
* <p>
* This includes Cluster notification, and BeanPersistListeners.
* </p>
*/
public final class PostCommitProcessing {
private static final Logger logger = LoggerFactory.getLogger(PostCommitProcessing.class);
private final ClusterManager clusterManager;
private final TransactionEvent event;
private final String serverName;
private final TransactionManager manager;
private final List<PersistRequestBean<?>> persistBeanRequests;
private final BeanPersistIdMap beanPersistIdMap;
private final RemoteTransactionEvent remoteTransactionEvent;
private final DeleteByIdMap deleteByIdMap;
/**
* Create for a TransactionManager and event.
*/
public PostCommitProcessing(ClusterManager clusterManager, TransactionManager manager, TransactionEvent event) {
this.clusterManager = clusterManager;
this.manager = manager;
this.serverName = manager.getServerName();
this.event = event;
this.deleteByIdMap = event.getDeleteByIdMap();
this.persistBeanRequests = createPersistBeanRequests();
this.beanPersistIdMap = createBeanPersistIdMap();
this.remoteTransactionEvent = createRemoteTransactionEvent();
}
public void notifyLocalCacheIndex() {
// notify cache with bulk insert/update/delete statements
processTableEvents(event.getEventTables());
// notify cache with bean changes
event.notifyCache();
}
/**
* Table events are where SQL or external tools are used. In this case the
* cache is notified based on the table name (rather than bean type).
*/
private void processTableEvents(TransactionEventTable tableEvents) {
if (tableEvents != null && !tableEvents.isEmpty()) {
// notify cache with table based changes
BeanDescriptorManager dm = manager.getBeanDescriptorManager();
for (TableIUD tableIUD : tableEvents.values()) {
dm.cacheNotify(tableIUD);
}
}
}
public void notifyCluster() {
if (remoteTransactionEvent != null && !remoteTransactionEvent.isEmpty()) {
// send the interesting events to the cluster
if (logger.isDebugEnabled()) {
logger.debug("Cluster Send: {}", remoteTransactionEvent);
}
clusterManager.broadcast(remoteTransactionEvent);
}
}
public Runnable notifyPersistListeners() {
return new Runnable() {
public void run() {
localPersistListenersNotify();
}
};
}
private void localPersistListenersNotify() {
if (persistBeanRequests != null) {
for (int i = 0; i < persistBeanRequests.size(); i++) {
persistBeanRequests.get(i).notifyLocalPersistListener();
}
}
TransactionEventTable eventTables = event.getEventTables();
if (eventTables != null && !eventTables.isEmpty()) {
BulkEventListenerMap map = manager.getBulkEventListenerMap();
for (TableIUD tableIUD : eventTables.values()) {
map.process(tableIUD);
}
}
}
private List<PersistRequestBean<?>> createPersistBeanRequests() {
TransactionEventBeans eventBeans = event.getEventBeans();
if (eventBeans != null) {
return eventBeans.getRequests();
}
return null;
}
private BeanPersistIdMap createBeanPersistIdMap() {
if (persistBeanRequests == null) {
return null;
}
BeanPersistIdMap m = new BeanPersistIdMap();
for (int i = 0; i < persistBeanRequests.size(); i++) {
persistBeanRequests.get(i).addToPersistMap(m);
}
return m;
}
private RemoteTransactionEvent createRemoteTransactionEvent() {
if (!clusterManager.isClustering()) {
return null;
}
RemoteTransactionEvent remoteTransactionEvent = new RemoteTransactionEvent(serverName);
if (beanPersistIdMap != null) {
for (BeanPersistIds beanPersist : beanPersistIdMap.values()) {
remoteTransactionEvent.addBeanPersistIds(beanPersist);
}
}
if (deleteByIdMap != null) {
remoteTransactionEvent.setDeleteByIdMap(deleteByIdMap);
}
TransactionEventTable eventTables = event.getEventTables();
if (eventTables != null && !eventTables.isEmpty()) {
for (TableIUD tableIUD : eventTables.values()) {
remoteTransactionEvent.addTableIUD(tableIUD);
}
}
return remoteTransactionEvent;
}
}
package com.avaje.ebeaninternal.server.transaction;
import com.avaje.ebeaninternal.api.TransactionEvent;
import com.avaje.ebeaninternal.api.TransactionEventBeans;
import com.avaje.ebeaninternal.api.TransactionEventTable;
import com.avaje.ebeaninternal.api.TransactionEventTable.TableIUD;
import com.avaje.ebeaninternal.server.cluster.ClusterManager;
import com.avaje.ebeaninternal.server.core.PersistRequestBean;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
/**
* Performs post commit processing using a background thread.
* <p>
* This includes Cluster notification, and BeanPersistListeners.
* </p>
*/
public final class PostCommitProcessing {
private static final Logger logger = LoggerFactory.getLogger(PostCommitProcessing.class);
private final ClusterManager clusterManager;
private final TransactionEvent event;
private final String serverName;
private final TransactionManager manager;
private final List<PersistRequestBean<?>> persistBeanRequests;
private final BeanPersistIdMap beanPersistIdMap;
private final RemoteTransactionEvent remoteTransactionEvent;
private final DeleteByIdMap deleteByIdMap;
/**
* Create for a TransactionManager and event.
*/
public PostCommitProcessing(ClusterManager clusterManager, TransactionManager manager, TransactionEvent event) {
this.clusterManager = clusterManager;
this.manager = manager;
this.serverName = manager.getServerName();
this.event = event;
this.deleteByIdMap = event.getDeleteByIdMap();
this.persistBeanRequests = createPersistBeanRequests();
this.beanPersistIdMap = createBeanPersistIdMap();
this.remoteTransactionEvent = createRemoteTransactionEvent();
}
public void notifyLocalCacheIndex() {
// notify cache with bulk insert/update/delete statements
processTableEvents(event.getEventTables());
// notify cache with bean changes
event.notifyCache();
}
/**
* Table events are where SQL or external tools are used. In this case the
* cache is notified based on the table name (rather than bean type).
*/
private void processTableEvents(TransactionEventTable tableEvents) {
if (tableEvents != null && !tableEvents.isEmpty()) {
// notify cache with table based changes
BeanDescriptorManager dm = manager.getBeanDescriptorManager();
for (TableIUD tableIUD : tableEvents.values()) {
dm.cacheNotify(tableIUD);
}
}
}
public void notifyCluster() {
if (remoteTransactionEvent != null && !remoteTransactionEvent.isEmpty()) {
// send the interesting events to the cluster
if (logger.isDebugEnabled()) {
logger.debug("Cluster Send: {}", remoteTransactionEvent);
}
clusterManager.broadcast(remoteTransactionEvent);
}
}
public Runnable notifyPersistListeners() {
return new Runnable() {
public void run() {
localPersistListenersNotify();
}
};
}
private void localPersistListenersNotify() {
if (persistBeanRequests != null) {
for (int i = 0; i < persistBeanRequests.size(); i++) {
persistBeanRequests.get(i).notifyLocalPersistListener();
}
}
TransactionEventTable eventTables = event.getEventTables();
if (eventTables != null && !eventTables.isEmpty()) {
BulkEventListenerMap map = manager.getBulkEventListenerMap();
for (TableIUD tableIUD : eventTables.values()) {
map.process(tableIUD);
}
}
}
private List<PersistRequestBean<?>> createPersistBeanRequests() {
TransactionEventBeans eventBeans = event.getEventBeans();
if (eventBeans != null) {
return eventBeans.getRequests();
}
return null;
}
private BeanPersistIdMap createBeanPersistIdMap() {
if (persistBeanRequests == null) {
return null;
}
BeanPersistIdMap m = new BeanPersistIdMap();
for (int i = 0; i < persistBeanRequests.size(); i++) {
persistBeanRequests.get(i).addToPersistMap(m);
}
return m;
}
private RemoteTransactionEvent createRemoteTransactionEvent() {
if (!clusterManager.isClustering()) {
return null;
}
RemoteTransactionEvent remoteTransactionEvent = new RemoteTransactionEvent(serverName);
if (beanPersistIdMap != null) {
for (BeanPersistIds beanPersist : beanPersistIdMap.values()) {
remoteTransactionEvent.addBeanPersistIds(beanPersist);
}
}
if (deleteByIdMap != null) {
remoteTransactionEvent.setDeleteByIdMap(deleteByIdMap);
}
TransactionEventTable eventTables = event.getEventTables();
if (eventTables != null && !eventTables.isEmpty()) {
for (TableIUD tableIUD : eventTables.values()) {
remoteTransactionEvent.addTableIUD(tableIUD);
}
}
return remoteTransactionEvent;
}
}
@@ -1,141 +1,141 @@
package com.avaje.ebeaninternal.server.transaction;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.api.TransactionEventTable.TableIUD;
import com.avaje.ebeaninternal.server.cluster.BinaryMessageList;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class RemoteTransactionEvent implements Runnable {
private List<BeanPersistIds> beanPersistList = new ArrayList<BeanPersistIds>();
private List<TableIUD> tableList;
private List<BeanDeltaList> beanDeltaLists;
private BeanDeltaMap beanDeltaMap;
private DeleteByIdMap deleteByIdMap;
private String serverName;
private transient SpiEbeanServer server;
public RemoteTransactionEvent(String serverName) {
this.serverName = serverName;
}
public RemoteTransactionEvent(SpiEbeanServer server) {
this.server = server;
}
public void run() {
server.remoteTransactionEvent(this);
}
public String toString() {
StringBuilder sb = new StringBuilder();
if (beanDeltaMap != null){
sb.append(beanDeltaMap);
}
sb.append(beanPersistList);
if (tableList != null){
sb.append(tableList);
}
return sb.toString();
}
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
if (tableList != null){
for (int i = 0; i < tableList.size(); i++) {
tableList.get(i).writeBinaryMessage(msgList);
}
}
if (deleteByIdMap != null){
for (BeanPersistIds deleteIds : deleteByIdMap.values()) {
deleteIds.writeBinaryMessage(msgList);
}
}
if (beanPersistList != null){
for (int i = 0; i < beanPersistList.size(); i++) {
beanPersistList.get(i).writeBinaryMessage(msgList);
}
}
if (beanDeltaLists != null){
for (int i = 0; i < beanDeltaLists.size(); i++) {
beanDeltaLists.get(i).writeBinaryMessage(msgList);
}
}
}
public boolean isEmpty() {
return beanPersistList.isEmpty() && (tableList == null || tableList.isEmpty());
}
public void addBeanPersistIds(BeanPersistIds beanPersist){
beanPersistList.add(beanPersist);
}
public void addTableIUD(TableIUD tableIud){
if (tableList == null){
tableList = new ArrayList<TableIUD>(4);
}
tableList.add(tableIud);
}
public void addBeanDeltaList(BeanDeltaList deltaList){
if (beanDeltaLists == null){
beanDeltaLists = new ArrayList<BeanDeltaList>();
}
beanDeltaLists.add(deltaList);
}
public void addBeanDelta(BeanDelta beanDelta){
if (beanDeltaMap == null){
beanDeltaMap = new BeanDeltaMap();
}
beanDeltaMap.addBeanDelta(beanDelta);
}
public String getServerName() {
return serverName;
}
public SpiEbeanServer getServer() {
return server;
}
public void setServer(SpiEbeanServer server) {
this.server = server;
}
public DeleteByIdMap getDeleteByIdMap() {
return deleteByIdMap;
}
public void setDeleteByIdMap(DeleteByIdMap deleteByIdMap) {
this.deleteByIdMap = deleteByIdMap;
}
public List<TableIUD> getTableIUDList() {
return tableList;
}
public List<BeanPersistIds> getBeanPersistList() {
return beanPersistList;
}
public List<BeanDeltaList> getBeanDeltaLists() {
if (beanDeltaMap != null){
beanDeltaLists.addAll(beanDeltaMap.deltaLists());
}
return beanDeltaLists;
}
}
package com.avaje.ebeaninternal.server.transaction;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.api.TransactionEventTable.TableIUD;
import com.avaje.ebeaninternal.server.cluster.BinaryMessageList;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class RemoteTransactionEvent implements Runnable {
private List<BeanPersistIds> beanPersistList = new ArrayList<BeanPersistIds>();
private List<TableIUD> tableList;
private List<BeanDeltaList> beanDeltaLists;
private BeanDeltaMap beanDeltaMap;
private DeleteByIdMap deleteByIdMap;
private String serverName;
private transient SpiEbeanServer server;
public RemoteTransactionEvent(String serverName) {
this.serverName = serverName;
}
public RemoteTransactionEvent(SpiEbeanServer server) {
this.server = server;
}
public void run() {
server.remoteTransactionEvent(this);
}
public String toString() {
StringBuilder sb = new StringBuilder();
if (beanDeltaMap != null){
sb.append(beanDeltaMap);
}
sb.append(beanPersistList);
if (tableList != null){
sb.append(tableList);
}
return sb.toString();
}
public void writeBinaryMessage(BinaryMessageList msgList) throws IOException {
if (tableList != null){
for (int i = 0; i < tableList.size(); i++) {
tableList.get(i).writeBinaryMessage(msgList);
}
}
if (deleteByIdMap != null){
for (BeanPersistIds deleteIds : deleteByIdMap.values()) {
deleteIds.writeBinaryMessage(msgList);
}
}
if (beanPersistList != null){
for (int i = 0; i < beanPersistList.size(); i++) {
beanPersistList.get(i).writeBinaryMessage(msgList);
}
}
if (beanDeltaLists != null){
for (int i = 0; i < beanDeltaLists.size(); i++) {
beanDeltaLists.get(i).writeBinaryMessage(msgList);
}
}
}
public boolean isEmpty() {
return beanPersistList.isEmpty() && (tableList == null || tableList.isEmpty());
}
public void addBeanPersistIds(BeanPersistIds beanPersist){
beanPersistList.add(beanPersist);
}
public void addTableIUD(TableIUD tableIud){
if (tableList == null){
tableList = new ArrayList<TableIUD>(4);
}
tableList.add(tableIud);
}
public void addBeanDeltaList(BeanDeltaList deltaList){
if (beanDeltaLists == null){
beanDeltaLists = new ArrayList<BeanDeltaList>();
}
beanDeltaLists.add(deltaList);
}
public void addBeanDelta(BeanDelta beanDelta){
if (beanDeltaMap == null){
beanDeltaMap = new BeanDeltaMap();
}
beanDeltaMap.addBeanDelta(beanDelta);
}
public String getServerName() {
return serverName;
}
public SpiEbeanServer getServer() {
return server;
}
public void setServer(SpiEbeanServer server) {
this.server = server;
}
public DeleteByIdMap getDeleteByIdMap() {
return deleteByIdMap;
}
public void setDeleteByIdMap(DeleteByIdMap deleteByIdMap) {
this.deleteByIdMap = deleteByIdMap;
}
public List<TableIUD> getTableIUDList() {
return tableList;
}
public List<BeanPersistIds> getBeanPersistList() {
return beanPersistList;
}
public List<BeanDeltaList> getBeanDeltaLists() {
if (beanDeltaMap != null){
beanDeltaLists.addAll(beanDeltaMap.deltaLists());
}
return beanDeltaLists;
}
}
@@ -1,118 +1,118 @@
package com.avaje.ebeaninternal.server.transaction;
import java.util.HashMap;
import javax.persistence.PersistenceException;
import com.avaje.ebeaninternal.api.SpiTransaction;
/**
* Current transactions mapped by server name.
*/
public class TransactionMap {
/**
* Map of State by serverName.
*/
private HashMap<String,State> map = new HashMap<String, State>();
public String toString() {
return map.toString();
}
public boolean isEmpty() {
return map.isEmpty();
}
/**
* Return the State for a given serverName.
*/
public State getState(String serverName) {
return map.get(serverName);
}
/**
* Return the State for a given serverName.
*/
public State getStateWithCreate(String serverName) {
State state = map.get(serverName);
if (state == null){
state = new State();
map.put(serverName, state);
}
return state;
}
/**
* Remove and return the State for a given serverName.
*/
public State removeState(String serverName) {
return map.remove(serverName);
}
/**
* The transaction and whether it is active.
*/
public static class State {
SpiTransaction transaction;
public String toString() {
return "txn["+transaction+"]";
}
public SpiTransaction get() {
return transaction;
}
/**
* Set the transaction. This will now be the current transaction.
*/
public void set(SpiTransaction trans) {
if (transaction != null && transaction.isActive()){
String m = "The existing transaction is still active?";
throw new PersistenceException(m);
}
transaction = trans;
}
/**
* Commit the transaction.
*/
public void commit() {
transaction.commit();
transaction = null;
}
/**
* Rollback the transaction.
*/
public void rollback() {
transaction.rollback();
transaction = null;
}
/**
* End the transaction.
*/
public void end() {
if (transaction != null){
transaction.end();
transaction = null;
}
}
/**
* Used to replace transaction with a proxy.
*/
public void replace(SpiTransaction trans) {
transaction = trans;
}
}
}
package com.avaje.ebeaninternal.server.transaction;
import java.util.HashMap;
import javax.persistence.PersistenceException;
import com.avaje.ebeaninternal.api.SpiTransaction;
/**
* Current transactions mapped by server name.
*/
public class TransactionMap {
/**
* Map of State by serverName.
*/
private HashMap<String,State> map = new HashMap<String, State>();
public String toString() {
return map.toString();
}
public boolean isEmpty() {
return map.isEmpty();
}
/**
* Return the State for a given serverName.
*/
public State getState(String serverName) {
return map.get(serverName);
}
/**
* Return the State for a given serverName.
*/
public State getStateWithCreate(String serverName) {
State state = map.get(serverName);
if (state == null){
state = new State();
map.put(serverName, state);
}
return state;
}
/**
* Remove and return the State for a given serverName.
*/
public State removeState(String serverName) {
return map.remove(serverName);
}
/**
* The transaction and whether it is active.
*/
public static class State {
SpiTransaction transaction;
public String toString() {
return "txn["+transaction+"]";
}
public SpiTransaction get() {
return transaction;
}
/**
* Set the transaction. This will now be the current transaction.
*/
public void set(SpiTransaction trans) {
if (transaction != null && transaction.isActive()){
String m = "The existing transaction is still active?";
throw new PersistenceException(m);
}
transaction = trans;
}
/**
* Commit the transaction.
*/
public void commit() {
transaction.commit();
transaction = null;
}
/**
* Rollback the transaction.
*/
public void rollback() {
transaction.rollback();
transaction = null;
}
/**
* End the transaction.
*/
public void end() {
if (transaction != null){
transaction.end();
transaction = null;
}
}
/**
* Used to replace transaction with a proxy.
*/
public void replace(SpiTransaction trans) {
transaction = trans;
}
}
}