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 }