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 * Unless otherwise indicated, all code in JBoss DNA is licensed 010 * 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.repository; 025 026 import java.util.Collections; 027 import java.util.HashMap; 028 import java.util.Map; 029 import org.jboss.dna.common.util.CheckArg; 030 import org.jboss.dna.graph.ExecutionContext; 031 import org.jboss.dna.graph.Graph; 032 import org.jboss.dna.graph.Node; 033 import org.jboss.dna.graph.connector.RepositorySource; 034 import org.jboss.dna.graph.mimetype.MimeTypeDetector; 035 import org.jboss.dna.graph.property.Name; 036 import org.jboss.dna.graph.property.Path; 037 import org.jboss.dna.repository.Configurator.ChooseClass; 038 import org.jboss.dna.repository.Configurator.ConfigRepositoryDetails; 039 import org.jboss.dna.repository.Configurator.ConfigurationRepository; 040 import org.jboss.dna.repository.Configurator.MimeTypeDetectorDetails; 041 import org.jboss.dna.repository.Configurator.RepositoryDetails; 042 import org.jboss.dna.repository.Configurator.SequencerDetails; 043 import org.jboss.dna.repository.sequencer.Sequencer; 044 045 /** 046 * 047 */ 048 public class DnaConfiguration 049 implements Configurator.Initializer<DnaConfiguration>, Configurator.SequencerConfigurator<DnaConfiguration>, 050 Configurator.RepositoryConfigurator<DnaConfiguration>, Configurator.MimeDetectorConfigurator<DnaConfiguration>, 051 Configurator.Builder<DnaEngine> { 052 053 protected static final Map<String, Name> NAMES_TO_MAP; 054 static { 055 Map<String, Name> names = new HashMap<String, Name>(); 056 names.put(DnaLexicon.READABLE_NAME.getLocalName(), DnaLexicon.READABLE_NAME); 057 names.put(DnaLexicon.DESCRIPTION.getLocalName(), DnaLexicon.DESCRIPTION); 058 names.put(DnaLexicon.DEFAULT_CACHE_POLICY.getLocalName(), DnaLexicon.DEFAULT_CACHE_POLICY); 059 names.put(DnaLexicon.RETRY_LIMIT.getLocalName(), DnaLexicon.RETRY_LIMIT); 060 names.put(DnaLexicon.PATH_EXPRESSIONS.getLocalName(), DnaLexicon.PATH_EXPRESSIONS); 061 names.put(DnaLexicon.CLASSNAME.getLocalName(), DnaLexicon.CLASSNAME); 062 names.put(DnaLexicon.CLASSPATH.getLocalName(), DnaLexicon.CLASSPATH); 063 NAMES_TO_MAP = Collections.unmodifiableMap(names); 064 } 065 066 private final Builder<DnaConfiguration> builder; 067 068 /** 069 * Create a new configuration for DNA. 070 */ 071 public DnaConfiguration() { 072 this(new ExecutionContext()); 073 } 074 075 /** 076 * Specify a new {@link ExecutionContext} that should be used for this DNA instance. 077 * 078 * @param context the new context, or null if a default-constructed execution context should be used 079 * @throws IllegalArgumentException if the supplied context reference is null 080 */ 081 public DnaConfiguration( ExecutionContext context ) { 082 this.builder = new Builder<DnaConfiguration>(context, this); 083 } 084 085 /** 086 * Get the execution context used by this configurator. 087 * 088 * @return the execution context; never null 089 */ 090 public final ExecutionContext getExecutionContext() { 091 return builder.getExecutionContext(); 092 } 093 094 /** 095 * {@inheritDoc} 096 * 097 * @see org.jboss.dna.repository.Configurator.Initializer#withConfigurationRepository() 098 */ 099 public ChooseClass<RepositorySource, ConfigRepositoryDetails<DnaConfiguration>> withConfigurationRepository() { 100 return builder.withConfigurationRepository(); 101 } 102 103 /** 104 * {@inheritDoc} 105 * 106 * @see org.jboss.dna.repository.Configurator.RepositoryConfigurator#addRepository(java.lang.String) 107 */ 108 public ChooseClass<RepositorySource, RepositoryDetails<DnaConfiguration>> addRepository( String id ) { 109 return builder.addRepository(id); 110 } 111 112 /** 113 * {@inheritDoc} 114 * 115 * @see org.jboss.dna.repository.Configurator.RepositoryConfigurator#addRepository(org.jboss.dna.graph.connector.RepositorySource) 116 */ 117 public DnaConfiguration addRepository( RepositorySource source ) { 118 return builder.addRepository(source); 119 } 120 121 /** 122 * {@inheritDoc} 123 * 124 * @see org.jboss.dna.repository.Configurator.SequencerConfigurator#addSequencer(java.lang.String) 125 */ 126 public ChooseClass<Sequencer, SequencerDetails<DnaConfiguration>> addSequencer( String id ) { 127 return builder.addSequencer(id); 128 } 129 130 /** 131 * {@inheritDoc} 132 * 133 * @see org.jboss.dna.repository.Configurator.MimeDetectorConfigurator#addMimeTypeDetector(java.lang.String) 134 */ 135 public ChooseClass<MimeTypeDetector, MimeTypeDetectorDetails<DnaConfiguration>> addMimeTypeDetector( String id ) { 136 return builder.addMimeTypeDetector(id); 137 } 138 139 /** 140 * Save any changes that have been made so far to the configuration. This method does nothing if no changes have been made. 141 * 142 * @return this configuration object for method chaining purposes; never null 143 */ 144 public DnaConfiguration save() { 145 return builder.save(); 146 } 147 148 /** 149 * {@inheritDoc} 150 * 151 * @see org.jboss.dna.repository.Configurator.Builder#build() 152 */ 153 public DnaEngine build() throws DnaConfigurationException { 154 save(); 155 return new DnaEngine(builder.getExecutionContext(), builder.configurationSource); 156 } 157 158 protected Graph graph() { 159 return builder.graph(); 160 } 161 162 protected ConfigurationRepository configurationRepository() { 163 return builder.configurationSource; 164 } 165 166 public static class Builder<ReturnType> extends Configurator<ReturnType> 167 implements Configurator.Initializer<ReturnType>, Configurator.SequencerConfigurator<ReturnType>, 168 Configurator.RepositoryConfigurator<ReturnType>, Configurator.MimeDetectorConfigurator<ReturnType> { 169 170 private Path sourcesPath; 171 private Path sequencersPath; 172 private Path detectorsPath; 173 174 /** 175 * Specify a new {@link ExecutionContext} that should be used for this DNA instance. 176 * 177 * @param context the new context, or null if a default-constructed execution context should be used 178 * @param builder the builder object returned from all the methods 179 * @throws IllegalArgumentException if the supplied context reference is null 180 */ 181 public Builder( ExecutionContext context, 182 ReturnType builder ) { 183 super(context, builder); 184 } 185 186 public DnaEngine buildDnaEngine() { 187 return new DnaEngine(context, configurationSource); 188 } 189 190 public ConfigurationRepository getConfigurationRepository() { 191 return configurationSource; 192 } 193 194 protected Path sourcesPath() { 195 // Make sure the "dna:sources" node is there 196 if (sourcesPath == null) { 197 Path path = pathFactory().create(this.configurationSource.getPath(), DnaLexicon.SOURCES); 198 Node node = graph().createIfMissing(path).andReturn(); 199 this.sourcesPath = node.getLocation().getPath(); 200 } 201 return this.sourcesPath; 202 } 203 204 protected Path sequencersPath() { 205 // Make sure the "dna:sequencers" node is there 206 if (sequencersPath == null) { 207 Path path = pathFactory().create(this.configurationSource.getPath(), DnaLexicon.SEQUENCERS); 208 Node node = graph().createIfMissing(path).andReturn(); 209 this.sequencersPath = node.getLocation().getPath(); 210 } 211 return this.sequencersPath; 212 } 213 214 protected Path detectorsPath() { 215 // Make sure the "dna:mimeTypeDetectors" node is there 216 if (detectorsPath == null) { 217 Path path = pathFactory().create(this.configurationSource.getPath(), DnaLexicon.MIME_TYPE_DETECTORS); 218 Node node = graph().createIfMissing(path).andReturn(); 219 this.detectorsPath = node.getLocation().getPath(); 220 } 221 return this.detectorsPath; 222 } 223 224 /** 225 * {@inheritDoc} 226 * 227 * @see org.jboss.dna.repository.Configurator.Initializer#withConfigurationRepository() 228 */ 229 public ChooseClass<RepositorySource, ConfigRepositoryDetails<ReturnType>> withConfigurationRepository() { 230 return new ConfigurationRepositoryClassChooser<ReturnType>(builder); 231 } 232 233 /** 234 * {@inheritDoc} 235 * 236 * @see org.jboss.dna.repository.Configurator.SequencerConfigurator#addSequencer(java.lang.String) 237 */ 238 public ChooseClass<Sequencer, SequencerDetails<ReturnType>> addSequencer( String id ) { 239 CheckArg.isNotEmpty(id, "id"); 240 // Now create the "dna:sequencer" node with the supplied id ... 241 Path path = createOrReplaceNode(sequencersPath(), id); 242 SequencerDetails<ReturnType> details = new GraphSequencerDetails<ReturnType>(path, builder); 243 return new ClassChooser<Sequencer, SequencerDetails<ReturnType>>(path, details); 244 } 245 246 /** 247 * {@inheritDoc} 248 * 249 * @see org.jboss.dna.repository.Configurator.RepositoryConfigurator#addRepository(java.lang.String) 250 */ 251 public ChooseClass<RepositorySource, RepositoryDetails<ReturnType>> addRepository( String id ) { 252 CheckArg.isNotEmpty(id, "id"); 253 // Now create the "dna:source" node with the supplied id ... 254 Path path = createOrReplaceNode(sourcesPath(), id); 255 RepositoryDetails<ReturnType> details = new GraphRepositoryDetails<ReturnType>(path, builder); 256 return new ClassChooser<RepositorySource, RepositoryDetails<ReturnType>>(path, details); 257 } 258 259 /** 260 * {@inheritDoc} 261 * 262 * @see org.jboss.dna.repository.Configurator.RepositoryConfigurator#addRepository(org.jboss.dna.graph.connector.RepositorySource) 263 */ 264 public ReturnType addRepository( RepositorySource source ) { 265 CheckArg.isNotNull(source, "source"); 266 CheckArg.isNotEmpty(source.getName(), "source.getName()"); 267 String name = source.getName(); 268 RepositoryDetails<ReturnType> details = addRepository(source.getName()).usingClass(source.getClass().getName()) 269 .loadedFromClasspath(); 270 // Record all of the bean properties ... 271 Path sourcePath = pathFactory().create(sourcesPath(), name); 272 recordBeanPropertiesInGraph(sourcePath, source); 273 return details.and(); 274 } 275 276 /** 277 * {@inheritDoc} 278 * 279 * @see org.jboss.dna.repository.Configurator.MimeDetectorConfigurator#addMimeTypeDetector(java.lang.String) 280 */ 281 public ChooseClass<MimeTypeDetector, MimeTypeDetectorDetails<ReturnType>> addMimeTypeDetector( String id ) { 282 CheckArg.isNotEmpty(id, "id"); 283 // Now create the "dna:sequencer" node with the supplied id ... 284 Path detectorPath = createOrReplaceNode(detectorsPath(), id); 285 MimeTypeDetectorDetails<ReturnType> details = new GraphMimeTypeDetectorDetails<ReturnType>(detectorPath, builder); 286 return new ClassChooser<MimeTypeDetector, MimeTypeDetectorDetails<ReturnType>>(detectorPath, details); 287 } 288 289 /** 290 * {@inheritDoc} 291 * 292 * @see org.jboss.dna.repository.Configurator#nameFor(java.lang.String) 293 */ 294 @Override 295 protected Name nameFor( String name ) { 296 Name result = NAMES_TO_MAP.get(name); 297 if (result == null) result = context.getValueFactories().getNameFactory().create(name); 298 return result; 299 } 300 } 301 302 }