001/* 002 * Copyright 2006-2007 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.batch.repeat.context; 018 019import org.springframework.core.AttributeAccessor; 020import org.springframework.core.AttributeAccessorSupport; 021 022/** 023 * An {@link AttributeAccessor} that synchronizes on a mutex (not this) before 024 * modifying or accessing the underlying attributes. 025 * 026 * @author Dave Syer 027 * 028 */ 029public class SynchronizedAttributeAccessor implements AttributeAccessor { 030 031 /** 032 * All methods are delegated to this support object. 033 */ 034 AttributeAccessorSupport support = new AttributeAccessorSupport() { 035 /** 036 * Generated serial UID. 037 */ 038 private static final long serialVersionUID = -7664290016506582290L; 039 }; 040 041 /* 042 * (non-Javadoc) 043 * @see org.springframework.core.AttributeAccessor#attributeNames() 044 */ 045 @Override 046 public String[] attributeNames() { 047 synchronized (support) { 048 return support.attributeNames(); 049 } 050 } 051 052 /* 053 * (non-Javadoc) 054 * @see java.lang.Object#equals(java.lang.Object) 055 */ 056 @Override 057 public boolean equals(Object other) { 058 if (this == other) { 059 return true; 060 } 061 AttributeAccessorSupport that; 062 if (other instanceof SynchronizedAttributeAccessor) { 063 that = ((SynchronizedAttributeAccessor) other).support; 064 } 065 else if (other instanceof AttributeAccessorSupport) { 066 that = (AttributeAccessorSupport) other; 067 } 068 else { 069 return false; 070 } 071 synchronized (support) { 072 return support.equals(that); 073 } 074 } 075 076 /* 077 * (non-Javadoc) 078 * @see org.springframework.core.AttributeAccessor#getAttribute(java.lang.String) 079 */ 080 @Override 081 public Object getAttribute(String name) { 082 synchronized (support) { 083 return support.getAttribute(name); 084 } 085 } 086 087 /* 088 * (non-Javadoc) 089 * @see org.springframework.core.AttributeAccessor#hasAttribute(java.lang.String) 090 */ 091 @Override 092 public boolean hasAttribute(String name) { 093 synchronized (support) { 094 return support.hasAttribute(name); 095 } 096 } 097 098 /* 099 * (non-Javadoc) 100 * @see java.lang.Object#hashCode() 101 */ 102 @Override 103 public int hashCode() { 104 return support.hashCode(); 105 } 106 107 /* 108 * (non-Javadoc) 109 * @see org.springframework.core.AttributeAccessor#removeAttribute(java.lang.String) 110 */ 111 @Override 112 public Object removeAttribute(String name) { 113 synchronized (support) { 114 return support.removeAttribute(name); 115 } 116 } 117 118 /* 119 * (non-Javadoc) 120 * @see org.springframework.core.AttributeAccessor#setAttribute(java.lang.String, 121 * java.lang.Object) 122 */ 123 @Override 124 public void setAttribute(String name, Object value) { 125 synchronized (support) { 126 support.setAttribute(name, value); 127 } 128 } 129 130 /** 131 * Additional support for atomic put if absent. 132 * @param name the key for the attribute name 133 * @param value the value of the attribute 134 * @return null if the attribute was not already set, the existing value 135 * otherwise. 136 */ 137 public Object setAttributeIfAbsent(String name, Object value) { 138 synchronized (support) { 139 Object old = getAttribute(name); 140 if (old != null) { 141 return old; 142 } 143 setAttribute(name, value); 144 } 145 return null; 146 } 147 148 /* 149 * (non-Javadoc) 150 * @see java.lang.Object#toString() 151 */ 152 @Override 153 public String toString() { 154 StringBuilder buffer = new StringBuilder("SynchronizedAttributeAccessor: ["); 155 synchronized (support) { 156 String[] names = attributeNames(); 157 for (int i = 0; i < names.length; i++) { 158 String name = names[i]; 159 buffer.append(names[i]).append("=").append(getAttribute(name)); 160 if (i < names.length - 1) { 161 buffer.append(", "); 162 } 163 } 164 buffer.append("]"); 165 return buffer.toString(); 166 } 167 } 168 169}