001    /*
002     * JBoss DNA (http://www.jboss.org/dna)
003     * See the COPYRIGHT.txt file distributed with this work for information
004     * regarding copyright ownership.  Some portions may be licensed
005     * to Red Hat, Inc. under one or more contributor license agreements.
006     * See the AUTHORS.txt file in the distribution for a full listing of 
007     * individual contributors. 
008     *
009     * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
010     * is licensed to you under the terms of the GNU Lesser General Public License as
011     * published by the Free Software Foundation; either version 2.1 of
012     * the License, or (at your option) any later version.
013     *
014     * JBoss DNA is distributed in the hope that it will be useful,
015     * but WITHOUT ANY WARRANTY; without even the implied warranty of
016     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017     * Lesser General Public License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this software; if not, write to the Free
021     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
022     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
023     */
024    package org.jboss.dna.graph.property.basic;
025    
026    import java.util.ArrayList;
027    import java.util.Collections;
028    import java.util.List;
029    import java.util.Set;
030    import java.util.concurrent.locks.Lock;
031    import java.util.concurrent.locks.ReadWriteLock;
032    import java.util.concurrent.locks.ReentrantReadWriteLock;
033    import net.jcip.annotations.ThreadSafe;
034    import org.jboss.dna.common.util.CheckArg;
035    import org.jboss.dna.graph.property.NamespaceRegistry;
036    
037    /**
038     * A thread-safe {@link NamespaceRegistry} that may be used as a thread-safe wrapper around another non-thread-safe
039     * implementation.
040     * 
041     * @author Randall Hauch
042     */
043    @ThreadSafe
044    public class ThreadSafeNamespaceRegistry implements NamespaceRegistry {
045    
046        private final ReadWriteLock registryLock = new ReentrantReadWriteLock();
047        private final NamespaceRegistry delegate;
048    
049        /**
050         */
051        public ThreadSafeNamespaceRegistry() {
052            this(new SimpleNamespaceRegistry());
053        }
054    
055        /**
056         * @param nonThreadSafeRegistry a {@link NamespaceRegistry} implementation that is not thread safe and to which this instance
057         *        will delegate; may not be null
058         */
059        public ThreadSafeNamespaceRegistry( NamespaceRegistry nonThreadSafeRegistry ) {
060            CheckArg.isNotNull(nonThreadSafeRegistry, "nonThreadSafeRegistry");
061            delegate = nonThreadSafeRegistry;
062        }
063    
064        /**
065         * {@inheritDoc}
066         */
067        public String getNamespaceForPrefix( String prefix ) {
068            CheckArg.isNotNull(prefix, "prefix");
069            Lock lock = this.registryLock.readLock();
070            try {
071                lock.lock();
072                return this.delegate.getNamespaceForPrefix(prefix);
073            } finally {
074                lock.unlock();
075            }
076        }
077    
078        /**
079         * {@inheritDoc}
080         */
081        public String getPrefixForNamespaceUri( String namespaceUri,
082                                                boolean generateIfMissing ) {
083            CheckArg.isNotNull(namespaceUri, "namespaceUri");
084            String prefix = null;
085            Lock lock = this.registryLock.readLock();
086            try {
087                lock.lock();
088                prefix = delegate.getPrefixForNamespaceUri(namespaceUri, false);
089            } finally {
090                lock.unlock();
091            }
092            if (prefix == null && generateIfMissing) {
093                // Get a write lock ...
094                lock = this.registryLock.writeLock();
095                try {
096                    lock.lock();
097                    prefix = delegate.getPrefixForNamespaceUri(namespaceUri, true);
098                    return prefix;
099                } finally {
100                    lock.unlock();
101                }
102            }
103            return prefix;
104        }
105    
106        /**
107         * {@inheritDoc}
108         */
109        public boolean isRegisteredNamespaceUri( String namespaceUri ) {
110            CheckArg.isNotNull(namespaceUri, "namespaceUri");
111            Lock lock = this.registryLock.readLock();
112            try {
113                lock.lock();
114                return delegate.isRegisteredNamespaceUri(namespaceUri);
115            } finally {
116                lock.unlock();
117            }
118        }
119    
120        /**
121         * {@inheritDoc}
122         */
123        public String getDefaultNamespaceUri() {
124            Lock lock = this.registryLock.readLock();
125            try {
126                lock.lock();
127                return delegate.getDefaultNamespaceUri();
128            } finally {
129                lock.unlock();
130            }
131        }
132    
133        /**
134         * {@inheritDoc}
135         */
136        public String register( String prefix,
137                                String namespaceUri ) {
138            CheckArg.isNotNull(namespaceUri, "namespaceUri");
139            Lock lock = this.registryLock.writeLock();
140            try {
141                lock.lock();
142                return delegate.register(prefix, namespaceUri);
143            } finally {
144                lock.unlock();
145            }
146        }
147    
148        /**
149         * {@inheritDoc}
150         * 
151         * @see org.jboss.dna.graph.property.NamespaceRegistry#unregister(java.lang.String)
152         */
153        public boolean unregister( String namespaceUri ) {
154            CheckArg.isNotNull(namespaceUri, "namespaceUri");
155            Lock lock = this.registryLock.writeLock();
156            try {
157                lock.lock();
158                return delegate.unregister(namespaceUri);
159            } finally {
160                lock.unlock();
161            }
162        }
163    
164        /**
165         * {@inheritDoc}
166         */
167        public Set<String> getRegisteredNamespaceUris() {
168            Lock lock = this.registryLock.readLock();
169            try {
170                lock.lock();
171                return delegate.getRegisteredNamespaceUris();
172            } finally {
173                lock.unlock();
174            }
175        }
176    
177        /**
178         * {@inheritDoc}
179         * 
180         * @see org.jboss.dna.graph.property.NamespaceRegistry#getNamespaces()
181         */
182        public Set<Namespace> getNamespaces() {
183            Lock lock = this.registryLock.readLock();
184            try {
185                lock.lock();
186                return delegate.getNamespaces();
187            } finally {
188                lock.unlock();
189            }
190        }
191    
192        /**
193         * {@inheritDoc}
194         * 
195         * @see java.lang.Object#toString()
196         */
197        @Override
198        public String toString() {
199            List<Namespace> namespaces = new ArrayList<Namespace>(getNamespaces());
200            Collections.sort(namespaces);
201            return namespaces.toString();
202        }
203    
204    }