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 }