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 }