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}