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.connector.jbosscache; 025 026 import java.io.ByteArrayInputStream; 027 import java.io.ByteArrayOutputStream; 028 import java.io.IOException; 029 import java.io.ObjectInputStream; 030 import java.io.ObjectOutputStream; 031 import java.util.Enumeration; 032 import java.util.HashMap; 033 import java.util.HashSet; 034 import java.util.Hashtable; 035 import java.util.List; 036 import java.util.Map; 037 import java.util.Set; 038 import java.util.UUID; 039 import javax.naming.BinaryRefAddr; 040 import javax.naming.Context; 041 import javax.naming.InitialContext; 042 import javax.naming.NamingException; 043 import javax.naming.RefAddr; 044 import javax.naming.Reference; 045 import javax.naming.Referenceable; 046 import javax.naming.StringRefAddr; 047 import javax.naming.spi.ObjectFactory; 048 import net.jcip.annotations.ThreadSafe; 049 import org.jboss.cache.Cache; 050 import org.jboss.cache.CacheFactory; 051 import org.jboss.cache.DefaultCacheFactory; 052 import org.jboss.dna.common.i18n.I18n; 053 import org.jboss.dna.common.util.StringUtil; 054 import org.jboss.dna.graph.DnaLexicon; 055 import org.jboss.dna.graph.cache.CachePolicy; 056 import org.jboss.dna.graph.connector.RepositoryConnection; 057 import org.jboss.dna.graph.connector.RepositoryContext; 058 import org.jboss.dna.graph.connector.RepositorySource; 059 import org.jboss.dna.graph.connector.RepositorySourceCapabilities; 060 import org.jboss.dna.graph.connector.RepositorySourceException; 061 import org.jboss.dna.graph.property.Name; 062 063 /** 064 * A repository source that uses a JBoss Cache instance to manage the content. This source is capable of using an existing 065 * {@link Cache} instance or creating a new instance. This process is controlled entirely by the JavaBean properties of the 066 * JBossCacheSource instance. 067 * <p> 068 * This source first attempts to find an existing cache in {@link #getCacheJndiName() JNDI}. If none is found, then it attempts to 069 * create a cache instance using the {@link CacheFactory} found in {@link #getCacheFactoryJndiName() JNDI} (or the 070 * {@link DefaultCacheFactory} if no such factory is available) and the {@link #getCacheConfigurationName() cache configuration 071 * name} if supplied or the default configuration if not set. 072 * </p> 073 * <p> 074 * Like other {@link RepositorySource} classes, instances of JBossCacheSource can be placed into JNDI and do support the creation 075 * of {@link Referenceable JNDI referenceable} objects and resolution of references into JBossCacheSource. 076 * </p> 077 * 078 * @author Randall Hauch 079 */ 080 @ThreadSafe 081 public class JBossCacheSource implements RepositorySource, ObjectFactory { 082 083 private static final long serialVersionUID = 2L; 084 /** 085 * The default limit is {@value} for retrying {@link RepositoryConnection connection} calls to the underlying source. 086 */ 087 public static final int DEFAULT_RETRY_LIMIT = 0; 088 public static final String DEFAULT_UUID_PROPERTY_NAME = DnaLexicon.UUID.getString(); 089 090 /** 091 * The initial {@link #getNameOfDefaultWorkspace() name of the default workspace} is "{@value} ", unless otherwise specified. 092 */ 093 public static final String DEFAULT_NAME_OF_DEFAULT_WORKSPACE = "default"; 094 095 protected static final String ROOT_NODE_UUID = "rootNodeUuid"; 096 protected static final String SOURCE_NAME = "sourceName"; 097 protected static final String DEFAULT_CACHE_POLICY = "defaultCachePolicy"; 098 protected static final String CACHE_CONFIGURATION_NAME = "cacheConfigurationName"; 099 protected static final String CACHE_FACTORY_JNDI_NAME = "cacheFactoryJndiName"; 100 protected static final String CACHE_JNDI_NAME = "cacheJndiName"; 101 protected static final String RETRY_LIMIT = "retryLimit"; 102 protected static final String DEFAULT_WORKSPACE = "defaultWorkspace"; 103 protected static final String PREDEFINED_WORKSPACE_NAMES = "predefinedWorkspaceNames"; 104 protected static final String ALLOW_CREATING_WORKSPACES = "allowCreatingWorkspaces"; 105 106 private volatile String name; 107 private volatile UUID rootNodeUuid = UUID.randomUUID(); 108 private volatile CachePolicy defaultCachePolicy; 109 private volatile String cacheConfigurationName; 110 private volatile String cacheFactoryJndiName; 111 private volatile String cacheJndiName; 112 private volatile int retryLimit = DEFAULT_RETRY_LIMIT; 113 private volatile String defaultWorkspace; 114 private volatile String[] predefinedWorkspaces = new String[] {}; 115 private volatile RepositorySourceCapabilities capabilities = new RepositorySourceCapabilities(true, true, false, true, false); 116 private transient JBossCacheWorkspaces workspaces; 117 private transient Context jndiContext; 118 119 /** 120 * Create a repository source instance. 121 */ 122 public JBossCacheSource() { 123 } 124 125 /** 126 * {@inheritDoc} 127 * 128 * @see org.jboss.dna.graph.connector.RepositorySource#initialize(org.jboss.dna.graph.connector.RepositoryContext) 129 */ 130 public void initialize( RepositoryContext context ) throws RepositorySourceException { 131 } 132 133 /** 134 * {@inheritDoc} 135 */ 136 public String getName() { 137 return this.name; 138 } 139 140 /** 141 * {@inheritDoc} 142 * 143 * @see org.jboss.dna.graph.connector.RepositorySource#getCapabilities() 144 */ 145 public RepositorySourceCapabilities getCapabilities() { 146 return capabilities; 147 } 148 149 /** 150 * {@inheritDoc} 151 * 152 * @see org.jboss.dna.graph.connector.RepositorySource#getRetryLimit() 153 */ 154 public int getRetryLimit() { 155 return retryLimit; 156 } 157 158 /** 159 * {@inheritDoc} 160 * 161 * @see org.jboss.dna.graph.connector.RepositorySource#setRetryLimit(int) 162 */ 163 public synchronized void setRetryLimit( int limit ) { 164 retryLimit = limit < 0 ? 0 : limit; 165 } 166 167 /** 168 * Set the name of this source 169 * 170 * @param name the name for this source 171 */ 172 public synchronized void setName( String name ) { 173 if (this.name == name || this.name != null && this.name.equals(name)) return; // unchanged 174 this.name = name; 175 } 176 177 /** 178 * Get the default cache policy for this source, or null if the global default cache policy should be used 179 * 180 * @return the default cache policy, or null if this source has no explicit default cache policy 181 */ 182 public CachePolicy getDefaultCachePolicy() { 183 return defaultCachePolicy; 184 } 185 186 /** 187 * @param defaultCachePolicy Sets defaultCachePolicy to the specified value. 188 */ 189 public synchronized void setDefaultCachePolicy( CachePolicy defaultCachePolicy ) { 190 if (this.defaultCachePolicy == defaultCachePolicy || this.defaultCachePolicy != null 191 && this.defaultCachePolicy.equals(defaultCachePolicy)) return; // unchanged 192 this.defaultCachePolicy = defaultCachePolicy; 193 } 194 195 /** 196 * Get the name in JNDI of a {@link Cache} instance that should be used by this source. 197 * <p> 198 * This source first attempts to find an existing cache in {@link #getCacheJndiName() JNDI}. If none is found, then it 199 * attempts to create a cache instance using the {@link CacheFactory} found in {@link #getCacheFactoryJndiName() JNDI} (or the 200 * {@link DefaultCacheFactory} if no such factory is available) and the {@link #getCacheConfigurationName() cache 201 * configuration name} if supplied or the default configuration if not set. 202 * </p> 203 * 204 * @return the JNDI name of the {@link Cache} instance that should be used, or null if the cache is to be created with a cache 205 * factory {@link #getCacheFactoryJndiName() found in JNDI} using the specified {@link #getCacheConfigurationName() 206 * cache configuration name}. 207 * @see #setCacheJndiName(String) 208 * @see #getCacheConfigurationName() 209 * @see #getCacheFactoryJndiName() 210 */ 211 public String getCacheJndiName() { 212 return cacheJndiName; 213 } 214 215 /** 216 * Set the name in JNDI of a {@link Cache} instance that should be used by this source. 217 * <p> 218 * This source first attempts to find an existing cache in {@link #getCacheJndiName() JNDI}. If none is found, then it 219 * attempts to create a cache instance using the {@link CacheFactory} found in {@link #getCacheFactoryJndiName() JNDI} (or the 220 * {@link DefaultCacheFactory} if no such factory is available) and the {@link #getCacheConfigurationName() cache 221 * configuration name} if supplied or the default configuration if not set. 222 * </p> 223 * 224 * @param cacheJndiName the JNDI name of the {@link Cache} instance that should be used, or null if the cache is to be created 225 * with a cache factory {@link #getCacheFactoryJndiName() found in JNDI} using the specified 226 * {@link #getCacheConfigurationName() cache configuration name}. 227 * @see #getCacheJndiName() 228 * @see #getCacheConfigurationName() 229 * @see #getCacheFactoryJndiName() 230 */ 231 public synchronized void setCacheJndiName( String cacheJndiName ) { 232 if (this.cacheJndiName == cacheJndiName || this.cacheJndiName != null && this.cacheJndiName.equals(cacheJndiName)) return; // unchanged 233 this.cacheJndiName = cacheJndiName; 234 } 235 236 /** 237 * Get the name in JNDI of a {@link CacheFactory} instance that should be used to create the cache for this source. 238 * <p> 239 * This source first attempts to find an existing cache in {@link #getCacheJndiName() JNDI}. If none is found, then it 240 * attempts to create a cache instance using the {@link CacheFactory} found in {@link #getCacheFactoryJndiName() JNDI} (or the 241 * {@link DefaultCacheFactory} if no such factory is available) and the {@link #getCacheConfigurationName() cache 242 * configuration name} if supplied or the default configuration if not set. 243 * </p> 244 * 245 * @return the JNDI name of the {@link CacheFactory} instance that should be used, or null if the {@link DefaultCacheFactory} 246 * should be used if a cache is to be created 247 * @see #setCacheFactoryJndiName(String) 248 * @see #getCacheConfigurationName() 249 * @see #getCacheJndiName() 250 */ 251 public String getCacheFactoryJndiName() { 252 return cacheFactoryJndiName; 253 } 254 255 /** 256 * Set the name in JNDI of a {@link CacheFactory} instance that should be used to obtain the {@link Cache} instance used by 257 * this source. 258 * <p> 259 * This source first attempts to find an existing cache in {@link #getCacheJndiName() JNDI}. If none is found, then it 260 * attempts to create a cache instance using the {@link CacheFactory} found in {@link #getCacheFactoryJndiName() JNDI} (or the 261 * {@link DefaultCacheFactory} if no such factory is available) and the {@link #getCacheConfigurationName() cache 262 * configuration name} if supplied or the default configuration if not set. 263 * </p> 264 * 265 * @param jndiName the JNDI name of the {@link CacheFactory} instance that should be used, or null if the 266 * {@link DefaultCacheFactory} should be used if a cache is to be created 267 * @see #setCacheFactoryJndiName(String) 268 * @see #getCacheConfigurationName() 269 * @see #getCacheJndiName() 270 */ 271 public synchronized void setCacheFactoryJndiName( String jndiName ) { 272 if (this.cacheFactoryJndiName == jndiName || this.cacheFactoryJndiName != null 273 && this.cacheFactoryJndiName.equals(jndiName)) return; // unchanged 274 this.cacheFactoryJndiName = jndiName; 275 } 276 277 /** 278 * Get the name of the configuration that should be used if a {@link Cache cache} is to be created using the 279 * {@link CacheFactory} found in JNDI or the {@link DefaultCacheFactory} if needed. 280 * <p> 281 * This source first attempts to find an existing cache in {@link #getCacheJndiName() JNDI}. If none is found, then it 282 * attempts to create a cache instance using the {@link CacheFactory} found in {@link #getCacheFactoryJndiName() JNDI} (or the 283 * {@link DefaultCacheFactory} if no such factory is available) and the {@link #getCacheConfigurationName() cache 284 * configuration name} if supplied or the default configuration if not set. 285 * </p> 286 * 287 * @return the name of the configuration that should be passed to the {@link CacheFactory}, or null if the default 288 * configuration should be used 289 * @see #setCacheConfigurationName(String) 290 * @see #getCacheFactoryJndiName() 291 * @see #getCacheJndiName() 292 */ 293 public String getCacheConfigurationName() { 294 return cacheConfigurationName; 295 } 296 297 /** 298 * Get the name of the configuration that should be used if a {@link Cache cache} is to be created using the 299 * {@link CacheFactory} found in JNDI or the {@link DefaultCacheFactory} if needed. 300 * <p> 301 * This source first attempts to find an existing cache in {@link #getCacheJndiName() JNDI}. If none is found, then it 302 * attempts to create a cache instance using the {@link CacheFactory} found in {@link #getCacheFactoryJndiName() JNDI} (or the 303 * {@link DefaultCacheFactory} if no such factory is available) and the {@link #getCacheConfigurationName() cache 304 * configuration name} if supplied or the default configuration if not set. 305 * </p> 306 * 307 * @param cacheConfigurationName the name of the configuration that should be passed to the {@link CacheFactory}, or null if 308 * the default configuration should be used 309 * @see #getCacheConfigurationName() 310 * @see #getCacheFactoryJndiName() 311 * @see #getCacheJndiName() 312 */ 313 public synchronized void setCacheConfigurationName( String cacheConfigurationName ) { 314 if (this.cacheConfigurationName == cacheConfigurationName || this.cacheConfigurationName != null 315 && this.cacheConfigurationName.equals(cacheConfigurationName)) return; // unchanged 316 this.cacheConfigurationName = cacheConfigurationName; 317 } 318 319 /** 320 * Get the UUID of the root node for the cache. If the cache exists, this UUID is not used but is instead set to the UUID of 321 * the existing root node. 322 * 323 * @return the UUID of the root node for the cache. 324 */ 325 public String getRootNodeUuid() { 326 return this.rootNodeUuid.toString(); 327 } 328 329 /** 330 * Get the UUID of the root node for the cache. If the cache exists, this UUID is not used but is instead set to the UUID of 331 * the existing root node. 332 * 333 * @return the UUID of the root node for the cache. 334 */ 335 public UUID getRootNodeUuidObject() { 336 return this.rootNodeUuid; 337 } 338 339 /** 340 * Set the UUID of the root node in this repository. If the cache exists, this UUID is not used but is instead set to the UUID 341 * of the existing root node. 342 * 343 * @param rootNodeUuid the UUID of the root node for the cache, or null if the UUID should be randomly generated 344 */ 345 public synchronized void setRootNodeUuid( String rootNodeUuid ) { 346 UUID uuid = null; 347 if (rootNodeUuid == null) uuid = UUID.randomUUID(); 348 else uuid = UUID.fromString(rootNodeUuid); 349 if (this.rootNodeUuid.equals(uuid)) return; // unchanged 350 this.rootNodeUuid = uuid; 351 } 352 353 /** 354 * Get the name of the default workspace. 355 * 356 * @return the name of the workspace that should be used by default; never null 357 */ 358 public String getNameOfDefaultWorkspace() { 359 return defaultWorkspace; 360 } 361 362 /** 363 * Set the name of the workspace that should be used when clients don't specify a workspace. 364 * 365 * @param nameOfDefaultWorkspace the name of the workspace that should be used by default, or null if the 366 * {@link #DEFAULT_NAME_OF_DEFAULT_WORKSPACE default name} should be used 367 */ 368 public synchronized void setNameOfDefaultWorkspace( String nameOfDefaultWorkspace ) { 369 this.defaultWorkspace = nameOfDefaultWorkspace != null ? nameOfDefaultWorkspace : DEFAULT_NAME_OF_DEFAULT_WORKSPACE; 370 } 371 372 /** 373 * Gets the names of the workspaces that are available when this source is created. 374 * 375 * @return the names of the workspaces that this source starts with, or null if there are no such workspaces 376 * @see #setPredefinedWorkspaceNames(String[]) 377 * @see #setCreatingWorkspacesAllowed(boolean) 378 */ 379 public synchronized String[] getPredefinedWorkspaceNames() { 380 String[] copy = new String[predefinedWorkspaces.length]; 381 System.arraycopy(predefinedWorkspaces, 0, copy, 0, predefinedWorkspaces.length); 382 return copy; 383 } 384 385 /** 386 * Sets the names of the workspaces that are available when this source is created. 387 * 388 * @param predefinedWorkspaceNames the names of the workspaces that this source should start with, or null if there are no 389 * such workspaces 390 * @see #setCreatingWorkspacesAllowed(boolean) 391 * @see #getPredefinedWorkspaceNames() 392 */ 393 public synchronized void setPredefinedWorkspaceNames( String[] predefinedWorkspaceNames ) { 394 this.predefinedWorkspaces = predefinedWorkspaceNames; 395 } 396 397 /** 398 * Get whether this source allows workspaces to be created dynamically. 399 * 400 * @return true if this source allows workspaces to be created by clients, or false if the 401 * {@link #getPredefinedWorkspaceNames() set of workspaces} is fixed 402 * @see #setPredefinedWorkspaceNames(String[]) 403 * @see #getPredefinedWorkspaceNames() 404 * @see #setCreatingWorkspacesAllowed(boolean) 405 */ 406 public boolean isCreatingWorkspacesAllowed() { 407 return capabilities.supportsCreatingWorkspaces(); 408 } 409 410 /** 411 * Set whether this source allows workspaces to be created dynamically. 412 * 413 * @param allowWorkspaceCreation true if this source allows workspaces to be created by clients, or false if the 414 * {@link #getPredefinedWorkspaceNames() set of workspaces} is fixed 415 * @see #setPredefinedWorkspaceNames(String[]) 416 * @see #getPredefinedWorkspaceNames() 417 * @see #isCreatingWorkspacesAllowed() 418 */ 419 public synchronized void setCreatingWorkspacesAllowed( boolean allowWorkspaceCreation ) { 420 capabilities = new RepositorySourceCapabilities(true, capabilities.supportsUpdates(), false, allowWorkspaceCreation, 421 capabilities.supportsReferences()); 422 } 423 424 /** 425 * {@inheritDoc} 426 * 427 * @see org.jboss.dna.graph.connector.RepositorySource#getConnection() 428 */ 429 @SuppressWarnings( "unchecked" ) 430 public synchronized RepositoryConnection getConnection() throws RepositorySourceException { 431 if (getName() == null) { 432 I18n msg = JBossCacheConnectorI18n.propertyIsRequired; 433 throw new RepositorySourceException(getName(), msg.text("name")); 434 } 435 if (this.workspaces == null) { 436 Context context = getContext(); 437 if (context == null) { 438 try { 439 context = new InitialContext(); 440 } catch (NamingException err) { 441 throw new RepositorySourceException(name, err); 442 } 443 } 444 445 // Look for a cache factory in JNDI ... 446 CacheFactory<Name, Object> cacheFactory = null; 447 String jndiName = getCacheFactoryJndiName(); 448 if (jndiName != null && jndiName.trim().length() != 0) { 449 Object object = null; 450 try { 451 object = context.lookup(jndiName); 452 if (object != null) cacheFactory = (CacheFactory<Name, Object>)object; 453 } catch (ClassCastException err) { 454 I18n msg = JBossCacheConnectorI18n.objectFoundInJndiWasNotCacheFactory; 455 String className = object != null ? object.getClass().getName() : "null"; 456 throw new RepositorySourceException(getName(), msg.text(jndiName, this.getName(), className), err); 457 } catch (Throwable err) { 458 if (err instanceof RuntimeException) throw (RuntimeException)err; 459 throw new RepositorySourceException(getName(), err); 460 } 461 } 462 if (cacheFactory == null) cacheFactory = new DefaultCacheFactory<Name, Object>(); 463 464 // Get the default cache configuration name 465 String configName = this.getCacheConfigurationName(); 466 467 // Create the set of initial names ... 468 Set<String> initialNames = new HashSet<String>(); 469 for (String initialName : getPredefinedWorkspaceNames()) 470 initialNames.add(initialName); 471 472 // Now create the workspace manager ... 473 this.workspaces = new JBossCacheWorkspaces(getName(), cacheFactory, configName, initialNames, context); 474 } 475 476 return new JBossCacheConnection(this, this.workspaces); 477 } 478 479 protected Context getContext() { 480 return this.jndiContext; 481 } 482 483 protected synchronized void setContext( Context context ) { 484 this.jndiContext = context; 485 } 486 487 /** 488 * {@inheritDoc} 489 */ 490 @Override 491 public boolean equals( Object obj ) { 492 if (obj == this) return true; 493 if (obj instanceof JBossCacheSource) { 494 JBossCacheSource that = (JBossCacheSource)obj; 495 if (this.getName() == null) { 496 if (that.getName() != null) return false; 497 } else { 498 if (!this.getName().equals(that.getName())) return false; 499 } 500 return true; 501 } 502 return false; 503 } 504 505 /** 506 * {@inheritDoc} 507 */ 508 public synchronized Reference getReference() { 509 String className = getClass().getName(); 510 String factoryClassName = this.getClass().getName(); 511 Reference ref = new Reference(className, factoryClassName, null); 512 513 ref.add(new StringRefAddr(SOURCE_NAME, getName())); 514 ref.add(new StringRefAddr(ROOT_NODE_UUID, getRootNodeUuid().toString())); 515 ref.add(new StringRefAddr(CACHE_JNDI_NAME, getCacheJndiName())); 516 ref.add(new StringRefAddr(CACHE_FACTORY_JNDI_NAME, getCacheFactoryJndiName())); 517 ref.add(new StringRefAddr(CACHE_CONFIGURATION_NAME, getCacheConfigurationName())); 518 ref.add(new StringRefAddr(RETRY_LIMIT, Integer.toString(getRetryLimit()))); 519 ref.add(new StringRefAddr(DEFAULT_WORKSPACE, getNameOfDefaultWorkspace())); 520 ref.add(new StringRefAddr(ALLOW_CREATING_WORKSPACES, Boolean.toString(isCreatingWorkspacesAllowed()))); 521 String[] workspaceNames = getPredefinedWorkspaceNames(); 522 if (workspaceNames != null && workspaceNames.length != 0) { 523 ref.add(new StringRefAddr(PREDEFINED_WORKSPACE_NAMES, StringUtil.combineLines(workspaceNames))); 524 } 525 if (getDefaultCachePolicy() != null) { 526 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 527 CachePolicy policy = getDefaultCachePolicy(); 528 try { 529 ObjectOutputStream oos = new ObjectOutputStream(baos); 530 oos.writeObject(policy); 531 ref.add(new BinaryRefAddr(DEFAULT_CACHE_POLICY, baos.toByteArray())); 532 } catch (IOException e) { 533 I18n msg = JBossCacheConnectorI18n.errorSerializingCachePolicyInSource; 534 throw new RepositorySourceException(getName(), msg.text(policy.getClass().getName(), getName()), e); 535 } 536 } 537 return ref; 538 } 539 540 /** 541 * {@inheritDoc} 542 */ 543 public Object getObjectInstance( Object obj, 544 javax.naming.Name name, 545 Context nameCtx, 546 Hashtable<?, ?> environment ) throws Exception { 547 if (obj instanceof Reference) { 548 Map<String, Object> values = new HashMap<String, Object>(); 549 Reference ref = (Reference)obj; 550 Enumeration<?> en = ref.getAll(); 551 while (en.hasMoreElements()) { 552 RefAddr subref = (RefAddr)en.nextElement(); 553 if (subref instanceof StringRefAddr) { 554 String key = subref.getType(); 555 Object value = subref.getContent(); 556 if (value != null) values.put(key, value.toString()); 557 } else if (subref instanceof BinaryRefAddr) { 558 String key = subref.getType(); 559 Object value = subref.getContent(); 560 if (value instanceof byte[]) { 561 // Deserialize ... 562 ByteArrayInputStream bais = new ByteArrayInputStream((byte[])value); 563 ObjectInputStream ois = new ObjectInputStream(bais); 564 value = ois.readObject(); 565 values.put(key, value); 566 } 567 } 568 } 569 String sourceName = (String)values.get(SOURCE_NAME); 570 String rootNodeUuidString = (String)values.get(ROOT_NODE_UUID); 571 String cacheJndiName = (String)values.get(CACHE_JNDI_NAME); 572 String cacheFactoryJndiName = (String)values.get(CACHE_FACTORY_JNDI_NAME); 573 String cacheConfigurationName = (String)values.get(CACHE_CONFIGURATION_NAME); 574 Object defaultCachePolicy = values.get(DEFAULT_CACHE_POLICY); 575 String retryLimit = (String)values.get(RETRY_LIMIT); 576 String defaultWorkspace = (String)values.get(DEFAULT_WORKSPACE); 577 String createWorkspaces = (String)values.get(ALLOW_CREATING_WORKSPACES); 578 579 String combinedWorkspaceNames = (String)values.get(PREDEFINED_WORKSPACE_NAMES); 580 String[] workspaceNames = null; 581 if (combinedWorkspaceNames != null) { 582 List<String> paths = StringUtil.splitLines(combinedWorkspaceNames); 583 workspaceNames = paths.toArray(new String[paths.size()]); 584 } 585 586 // Create the source instance ... 587 JBossCacheSource source = new JBossCacheSource(); 588 if (sourceName != null) source.setName(sourceName); 589 if (rootNodeUuidString != null) source.setRootNodeUuid(rootNodeUuidString); 590 if (cacheJndiName != null) source.setCacheJndiName(cacheJndiName); 591 if (cacheFactoryJndiName != null) source.setCacheFactoryJndiName(cacheFactoryJndiName); 592 if (cacheConfigurationName != null) source.setCacheConfigurationName(cacheConfigurationName); 593 if (defaultCachePolicy instanceof CachePolicy) { 594 source.setDefaultCachePolicy((CachePolicy)defaultCachePolicy); 595 } 596 if (retryLimit != null) source.setRetryLimit(Integer.parseInt(retryLimit)); 597 if (defaultWorkspace != null) source.setNameOfDefaultWorkspace(defaultWorkspace); 598 if (createWorkspaces != null) source.setCreatingWorkspacesAllowed(Boolean.parseBoolean(createWorkspaces)); 599 if (workspaceNames != null && workspaceNames.length != 0) source.setPredefinedWorkspaceNames(workspaceNames); 600 return source; 601 } 602 return null; 603 } 604 }