1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.modeshape.repository;
25
26 import java.io.File;
27 import java.io.FileInputStream;
28 import java.io.FileOutputStream;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.io.OutputStream;
32 import java.net.URL;
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Set;
40 import java.util.Stack;
41 import net.jcip.annotations.Immutable;
42 import net.jcip.annotations.NotThreadSafe;
43 import org.modeshape.common.collection.Problems;
44 import org.modeshape.common.collection.SimpleProblems;
45 import org.modeshape.common.component.ClassLoaderFactory;
46 import org.modeshape.common.component.StandardClassLoaderFactory;
47 import org.modeshape.common.util.CheckArg;
48 import org.modeshape.common.xml.StreamingContentHandler;
49 import org.modeshape.graph.ExecutionContext;
50 import org.modeshape.graph.Graph;
51 import org.modeshape.graph.Location;
52 import org.modeshape.graph.Node;
53 import org.modeshape.graph.Subgraph;
54 import org.modeshape.graph.SubgraphNode;
55 import org.modeshape.graph.Workspace;
56 import org.modeshape.graph.connector.RepositorySource;
57 import org.modeshape.graph.connector.inmemory.InMemoryRepositorySource;
58 import org.modeshape.graph.mimetype.MimeTypeDetector;
59 import org.modeshape.graph.observe.ObservationBus;
60 import org.modeshape.graph.property.Name;
61 import org.modeshape.graph.property.NamespaceRegistry;
62 import org.modeshape.graph.property.Path;
63 import org.modeshape.graph.property.PathExpression;
64 import org.modeshape.graph.property.PathNotFoundException;
65 import org.modeshape.graph.property.Property;
66 import org.modeshape.graph.property.ValueFactory;
67 import org.modeshape.graph.property.basic.RootPath;
68 import org.modeshape.graph.request.InvalidWorkspaceException;
69 import org.modeshape.graph.request.ReadBranchRequest;
70 import org.modeshape.graph.sequencer.StreamSequencer;
71 import org.xml.sax.ContentHandler;
72 import org.xml.sax.SAXException;
73 import org.xml.sax.helpers.AttributesImpl;
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 @NotThreadSafe
91 public class ModeShapeConfiguration {
92
93 public static final String DEFAULT_WORKSPACE_NAME = "";
94 public static final String DEFAULT_PATH = "/";
95 public static final String DEFAULT_CONFIGURATION_SOURCE_NAME = "ModeShape Configuration Repository";
96
97 private final ExecutionContext context;
98 private final Problems problems = new SimpleProblems();
99 private ConfigurationDefinition configurationContent;
100 private Graph.Batch changes;
101
102 private final Map<String, SequencerDefinition<? extends ModeShapeConfiguration>> sequencerDefinitions = new HashMap<String, SequencerDefinition<? extends ModeShapeConfiguration>>();
103 private final Map<String, RepositorySourceDefinition<? extends ModeShapeConfiguration>> repositorySourceDefinitions = new HashMap<String, RepositorySourceDefinition<? extends ModeShapeConfiguration>>();
104 private final Map<String, MimeTypeDetectorDefinition<? extends ModeShapeConfiguration>> mimeTypeDetectorDefinitions = new HashMap<String, MimeTypeDetectorDefinition<? extends ModeShapeConfiguration>>();
105 private ClusterDefinition<? extends ModeShapeConfiguration> clusterDefinition;
106
107
108
109
110 public ModeShapeConfiguration() {
111 this(new ExecutionContext());
112 }
113
114
115
116
117
118
119
120 public ModeShapeConfiguration( ExecutionContext context ) {
121 CheckArg.isNotNull(context, "context");
122 this.context = context;
123
124
125 InMemoryRepositorySource source = new InMemoryRepositorySource();
126 source.setName(DEFAULT_CONFIGURATION_SOURCE_NAME);
127 source.setDefaultWorkspaceName(DEFAULT_WORKSPACE_NAME);
128
129
130 configurationContent = new ConfigurationDefinition("dna", source, null, null, context, null);
131 }
132
133
134
135
136
137
138
139 public ModeShapeConfiguration withName( String name ) {
140 if (name != null) name = "dna";
141 configurationContent = configurationContent.with(name);
142 return this;
143 }
144
145
146
147
148
149
150
151
152
153
154 public ModeShapeConfiguration loadFrom( String pathToConfigurationFile ) throws IOException, SAXException {
155 CheckArg.isNotEmpty(pathToConfigurationFile, "pathToConfigurationFile");
156 return loadFrom(pathToConfigurationFile, DEFAULT_PATH);
157 }
158
159
160
161
162
163
164
165
166
167
168
169
170 public ModeShapeConfiguration loadFrom( String pathToConfigurationFile,
171 String path ) throws IOException, SAXException {
172 CheckArg.isNotEmpty(pathToConfigurationFile, "pathToConfigurationFile");
173 return loadFrom(new File(pathToConfigurationFile), path);
174 }
175
176
177
178
179
180
181
182
183
184
185 public ModeShapeConfiguration loadFrom( File configurationFile ) throws IOException, SAXException {
186 CheckArg.isNotNull(configurationFile, "configurationFile");
187 return loadFrom(configurationFile, DEFAULT_PATH);
188 }
189
190
191
192
193
194
195
196
197
198
199
200
201 public ModeShapeConfiguration loadFrom( File configurationFile,
202 String path ) throws IOException, SAXException {
203 CheckArg.isNotNull(configurationFile, "configurationFile");
204 InputStream stream = new FileInputStream(configurationFile);
205 try {
206 return loadFrom(stream, path);
207 } finally {
208 stream.close();
209 }
210 }
211
212
213
214
215
216
217
218
219
220
221 public ModeShapeConfiguration loadFrom( URL urlToConfigurationFile ) throws IOException, SAXException {
222 CheckArg.isNotNull(urlToConfigurationFile, "urlToConfigurationFile");
223 return loadFrom(urlToConfigurationFile, DEFAULT_PATH);
224 }
225
226
227
228
229
230
231
232
233
234
235
236
237 public ModeShapeConfiguration loadFrom( URL urlToConfigurationFile,
238 String path ) throws IOException, SAXException {
239 CheckArg.isNotNull(urlToConfigurationFile, "urlToConfigurationFile");
240 InputStream stream = urlToConfigurationFile.openStream();
241 try {
242 return loadFrom(stream, path);
243 } finally {
244 stream.close();
245 }
246 }
247
248
249
250
251
252
253
254
255
256
257 public ModeShapeConfiguration loadFrom( InputStream configurationFileInputStream ) throws IOException, SAXException {
258 CheckArg.isNotNull(configurationFileInputStream, "configurationFileInputStream");
259 return loadFrom(configurationFileInputStream, DEFAULT_PATH);
260 }
261
262
263
264
265
266
267
268
269
270
271
272
273 public ModeShapeConfiguration loadFrom( InputStream configurationFileInputStream,
274 String path ) throws IOException, SAXException {
275 CheckArg.isNotNull(configurationFileInputStream, "configurationFileInputStream");
276
277
278 InMemoryRepositorySource source = new InMemoryRepositorySource();
279 source.setName(DEFAULT_CONFIGURATION_SOURCE_NAME);
280 source.setDefaultWorkspaceName(DEFAULT_WORKSPACE_NAME);
281
282
283 Path pathToParent = path(path != null ? path : DEFAULT_PATH);
284 Graph graph = Graph.create(source, context);
285 graph.importXmlFrom(configurationFileInputStream).skippingRootElement(true).into(pathToParent);
286
287
288 configurationContent = configurationContent.with(pathToParent)
289 .with(source)
290 .withWorkspace(source.getDefaultWorkspaceName());
291 return this;
292 }
293
294
295
296
297
298
299
300
301
302
303
304 public ModeShapeConfiguration loadFrom( RepositorySource source ) {
305 return loadFrom(source, null, null);
306 }
307
308
309
310
311
312
313
314
315
316
317
318
319 public ModeShapeConfiguration loadFrom( RepositorySource source,
320 String workspaceName ) {
321 CheckArg.isNotNull(source, "source");
322 return loadFrom(source, workspaceName, null);
323 }
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338 public ModeShapeConfiguration loadFrom( RepositorySource source,
339 String workspaceName,
340 String pathInWorkspace ) {
341 CheckArg.isNotNull(source, "source");
342
343
344 Graph graph = Graph.create(source, context);
345 if (workspaceName != null) {
346 Workspace workspace = null;
347 try {
348 workspace = graph.useWorkspace(workspaceName);
349 } catch (InvalidWorkspaceException e) {
350
351 workspace = graph.createWorkspace().named(workspaceName);
352 }
353 assert workspace.getRoot() != null;
354 } else {
355 workspaceName = graph.getCurrentWorkspaceName();
356 }
357
358
359 Path path = pathInWorkspace != null ? path(pathInWorkspace) : path(DEFAULT_PATH);
360 Node parent = graph.getNodeAt(path);
361 assert parent != null;
362
363
364 configurationContent = configurationContent.with(source).withWorkspace(workspaceName).with(path);
365 return this;
366 }
367
368
369
370
371
372
373
374
375
376 public void storeTo( String file ) throws SAXException, IOException {
377 storeTo(new File(file));
378 }
379
380
381
382
383
384
385
386
387
388 public void storeTo( File file ) throws SAXException, IOException {
389 OutputStream os = null;
390 try {
391 os = new FileOutputStream(file);
392 storeTo(new StreamingContentHandler(os));
393 } finally {
394 if (os != null) os.close();
395 }
396 }
397
398
399
400
401
402
403
404
405 public void storeTo( OutputStream os ) throws SAXException {
406 storeTo(new StreamingContentHandler(os));
407 }
408
409
410
411
412
413
414
415
416 public void storeTo( ContentHandler handler ) throws SAXException {
417 Subgraph allContent = configurationGraph().getSubgraphOfDepth(ReadBranchRequest.NO_MAXIMUM_DEPTH).at("/");
418
419 Set<NamespaceRegistry.Namespace> namespaces = this.context.getNamespaceRegistry().getNamespaces();
420 Stack<String> mappedNamespacePrefixes = new Stack<String>();
421
422 handler.startDocument();
423
424 for (NamespaceRegistry.Namespace namespace : namespaces) {
425 handler.startPrefixMapping(namespace.getPrefix(), namespace.getNamespaceUri());
426 mappedNamespacePrefixes.push(namespace.getPrefix());
427 }
428
429 exportNode(handler, allContent, allContent.getRoot());
430 while (!mappedNamespacePrefixes.isEmpty()) {
431 handler.endPrefixMapping(mappedNamespacePrefixes.pop());
432 }
433
434 handler.endDocument();
435 }
436
437 private void exportNode( ContentHandler handler,
438 Subgraph subgraph,
439 SubgraphNode node ) throws SAXException {
440
441
442 NamespaceRegistry registry = this.context.getNamespaceRegistry();
443 ValueFactory<String> stringFactory = this.context.getValueFactories().getStringFactory();
444
445 AttributesImpl atts = new AttributesImpl();
446
447 for (Property prop : node.getProperties()) {
448 Name name = prop.getName();
449
450 StringBuilder buff = new StringBuilder();
451 boolean first = true;
452
453 for (Object rawValue : prop) {
454 if (first) {
455 first = false;
456 } else {
457 buff.append(",");
458 }
459 buff.append(stringFactory.create(rawValue));
460 }
461
462 atts.addAttribute(name.getNamespaceUri(), name.getLocalName(), name.getString(registry), "string", buff.toString());
463 }
464
465
466 Name nodeName;
467 Path nodePath = node.getLocation().getPath();
468 if (nodePath.isRoot()) {
469 nodeName = name("configuration");
470 } else {
471 nodeName = node.getLocation().getPath().getLastSegment().getName();
472 }
473 String uri = nodeName.getNamespaceUri();
474 String localName = nodeName.getLocalName();
475 String qName = nodeName.getString(registry);
476 handler.startElement(uri, localName, qName, atts);
477
478
479 for (Location childLocation : node.getChildren()) {
480 exportNode(handler, subgraph, subgraph.getNode(childLocation));
481 }
482
483
484 handler.endElement(uri, localName, qName);
485
486 }
487
488
489
490
491
492
493 public ConfigurationDefinition getConfigurationDefinition() {
494 return configurationContent;
495 }
496
497 protected ExecutionContext getExecutionContext() {
498 return configurationContent.getContext();
499 }
500
501 protected Path path() {
502 return configurationContent.getPath();
503 }
504
505 protected Path path( String path ) {
506 return context.getValueFactories().getPathFactory().create(path);
507 }
508
509 protected Name name( String name ) {
510 return context.getValueFactories().getNameFactory().create(name);
511 }
512
513
514
515
516
517
518 public Problems getProblems() {
519 return problems;
520 }
521
522 protected Graph configurationGraph() {
523 ConfigurationDefinition content = getConfigurationDefinition();
524 Graph graph = Graph.create(content.getRepositorySource(), content.getContext());
525 if (content.getWorkspace() != null) {
526 graph.useWorkspace(content.getWorkspace());
527 }
528
529 return graph;
530 }
531
532 protected Graph.Batch changes() {
533 if (changes == null) {
534 changes = configurationGraph().batch();
535 }
536 return changes;
537 }
538
539
540
541
542
543
544
545
546 public boolean hasChanges() {
547 Graph.Batch changes = this.changes;
548 return changes != null && changes.isExecuteRequired();
549 }
550
551
552
553
554
555
556
557 public ModeShapeConfiguration save() {
558 Graph.Batch changes = this.changes;
559 if (changes != null && changes.isExecuteRequired()) {
560 changes.execute();
561 }
562 this.changes = null;
563 sequencerDefinitions.clear();
564 mimeTypeDetectorDefinitions.clear();
565 repositorySourceDefinitions.clear();
566 return this;
567 }
568
569
570
571
572
573
574
575
576
577
578
579
580
581 public ModeShapeConfiguration withClassLoaderFactory( ClassLoaderFactory classLoaderFactory ) {
582 this.configurationContent = this.configurationContent.with(classLoaderFactory);
583 return this;
584 }
585
586 protected Set<String> getNamesOfComponentsUnder( Name parentName ) {
587 Set<String> names = new HashSet<String>();
588 try {
589 ConfigurationDefinition content = this.getConfigurationDefinition();
590 Path path = context.getValueFactories().getPathFactory().create(content.getPath(), parentName);
591 for (Location child : content.graph().getChildren().of(path)) {
592 names.add(child.getPath().getLastSegment().getString(context.getNamespaceRegistry()));
593 }
594 } catch (PathNotFoundException e) {
595
596 }
597 return names;
598 }
599
600
601
602
603
604
605 public Set<MimeTypeDetectorDefinition<? extends ModeShapeConfiguration>> mimeTypeDetectors() {
606
607 Set<String> names = getNamesOfComponentsUnder(ModeShapeLexicon.MIME_TYPE_DETECTORS);
608 names.addAll(this.mimeTypeDetectorDefinitions.keySet());
609 Set<MimeTypeDetectorDefinition<? extends ModeShapeConfiguration>> results = new HashSet<MimeTypeDetectorDefinition<? extends ModeShapeConfiguration>>();
610 for (String name : names) {
611 results.add(mimeTypeDetector(name));
612 }
613 return Collections.unmodifiableSet(results);
614 }
615
616
617
618
619
620
621 public Set<RepositorySourceDefinition<? extends ModeShapeConfiguration>> repositorySources() {
622
623 Set<String> names = getNamesOfComponentsUnder(ModeShapeLexicon.SOURCES);
624 names.addAll(this.repositorySourceDefinitions.keySet());
625 Set<RepositorySourceDefinition<? extends ModeShapeConfiguration>> results = new HashSet<RepositorySourceDefinition<? extends ModeShapeConfiguration>>();
626 for (String name : names) {
627 results.add(repositorySource(name));
628 }
629 return Collections.unmodifiableSet(results);
630 }
631
632
633
634
635
636
637 public Set<SequencerDefinition<? extends ModeShapeConfiguration>> sequencers() {
638
639 Set<String> names = getNamesOfComponentsUnder(ModeShapeLexicon.SEQUENCERS);
640 names.addAll(this.sequencerDefinitions.keySet());
641 Set<SequencerDefinition<? extends ModeShapeConfiguration>> results = new HashSet<SequencerDefinition<? extends ModeShapeConfiguration>>();
642 for (String name : names) {
643 results.add(sequencer(name));
644 }
645 return Collections.unmodifiableSet(results);
646 }
647
648
649
650
651
652
653
654
655 public MimeTypeDetectorDefinition<? extends ModeShapeConfiguration> mimeTypeDetector( String name ) {
656 return mimeTypeDetectorDefinition(this, name);
657 }
658
659
660
661
662
663
664
665
666 public RepositorySourceDefinition<? extends ModeShapeConfiguration> repositorySource( String name ) {
667 return repositorySourceDefinition(this, name);
668 }
669
670
671
672
673
674
675
676
677 public SequencerDefinition<? extends ModeShapeConfiguration> sequencer( String name ) {
678 return sequencerDefinition(this, name);
679 }
680
681
682
683
684
685
686 public ClusterDefinition<? extends ModeShapeConfiguration> clustering() {
687 return clusterDefinition(this);
688 }
689
690
691
692
693
694
695 public ModeShapeConfiguration and() {
696 return this;
697 }
698
699
700
701
702
703
704
705 public ModeShapeEngine build() {
706 save();
707 return new ModeShapeEngine(getExecutionContextForEngine(), getConfigurationDefinition());
708 }
709
710
711
712
713
714
715
716
717
718
719
720
721 protected ExecutionContext getExecutionContextForEngine() {
722 return getExecutionContext();
723 }
724
725
726
727
728
729
730 public interface Returnable<ReturnType> {
731
732
733
734
735
736 ReturnType and();
737 }
738
739
740
741
742
743
744 public interface Removable<ReturnType> {
745
746
747
748
749
750 ReturnType remove();
751 }
752
753
754
755
756
757
758 public interface SetDescription<ReturnType> {
759
760
761
762
763
764
765 ReturnType setDescription( String description );
766
767
768
769
770
771
772 String getDescription();
773 }
774
775
776
777
778
779
780
781 public interface SetProperties<ReturnType> {
782
783
784
785
786
787
788
789 ReturnType setProperty( String beanPropertyName,
790 int value );
791
792
793
794
795
796
797
798
799 ReturnType setProperty( String beanPropertyName,
800 long value );
801
802
803
804
805
806
807
808
809 ReturnType setProperty( String beanPropertyName,
810 short value );
811
812
813
814
815
816
817
818
819 ReturnType setProperty( String beanPropertyName,
820 boolean value );
821
822
823
824
825
826
827
828
829 ReturnType setProperty( String beanPropertyName,
830 float value );
831
832
833
834
835
836
837
838
839 ReturnType setProperty( String beanPropertyName,
840 double value );
841
842
843
844
845
846
847
848
849 ReturnType setProperty( String beanPropertyName,
850 String value );
851
852
853
854
855
856
857
858
859
860 ReturnType setProperty( String beanPropertyName,
861 String value,
862 String... additionalValues );
863
864
865
866
867
868
869
870
871 ReturnType setProperty( String beanPropertyName,
872 Object value );
873
874
875
876
877
878
879
880
881 ReturnType setProperty( String beanPropertyName,
882 Object[] values );
883
884
885
886
887
888
889
890 Property getProperty( String beanPropertyName );
891 }
892
893
894
895
896
897
898
899 public interface ChooseClass<ComponentClassType, ReturnType> {
900
901
902
903
904
905
906
907
908
909 LoadedFrom<ReturnType> usingClass( String classname );
910
911
912
913
914
915
916
917
918
919
920 ReturnType usingClass( Class<? extends ComponentClassType> clazz );
921 }
922
923
924
925
926
927
928 public interface LoadedFrom<ReturnType> {
929
930
931
932
933
934
935
936
937
938
939
940 ReturnType loadedFrom( String... classPathNames );
941
942
943
944
945
946
947
948
949
950 ReturnType loadedFromClasspath();
951 }
952
953
954
955
956 public interface HasName {
957
958
959
960
961
962 String getName();
963 }
964
965
966
967
968
969
970 public interface ClusterDefinition<ReturnType>
971 extends Returnable<ReturnType>, SetProperties<ClusterDefinition<ReturnType>>, Removable<ReturnType> {
972 }
973
974
975
976
977
978
979 public interface MimeTypeDetectorDefinition<ReturnType>
980 extends Returnable<ReturnType>, SetDescription<MimeTypeDetectorDefinition<ReturnType>>,
981 SetProperties<MimeTypeDetectorDefinition<ReturnType>>,
982 ChooseClass<MimeTypeDetector, MimeTypeDetectorDefinition<ReturnType>>, Removable<ReturnType> {
983 }
984
985
986
987
988
989
990 public interface RepositorySourceDefinition<ReturnType>
991 extends Returnable<ReturnType>, SetDescription<RepositorySourceDefinition<ReturnType>>,
992 SetProperties<RepositorySourceDefinition<ReturnType>>,
993 ChooseClass<RepositorySource, RepositorySourceDefinition<ReturnType>>, Removable<ReturnType>, HasName {
994
995
996
997
998
999
1000
1001
1002
1003 RepositorySourceDefinition<ReturnType> setRetryLimit( int retryLimit );
1004 }
1005
1006
1007
1008
1009
1010
1011 public interface SequencerDefinition<ReturnType>
1012 extends Returnable<ReturnType>, SetDescription<SequencerDefinition<ReturnType>>,
1013 SetProperties<SequencerDefinition<ReturnType>>, ChooseClass<StreamSequencer, SequencerDefinition<ReturnType>>,
1014 Removable<ReturnType> {
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024 PathExpressionOutput<ReturnType> sequencingFrom( String inputPathExpression );
1025
1026
1027
1028
1029
1030
1031
1032
1033 SequencerDefinition<ReturnType> sequencingFrom( PathExpression inputPathExpression );
1034
1035
1036
1037
1038
1039
1040 Set<PathExpression> getPathExpressions();
1041 }
1042
1043
1044
1045
1046
1047
1048
1049 public interface PathExpressionOutput<ReturnType> {
1050
1051
1052
1053
1054
1055
1056
1057 SequencerDefinition<ReturnType> andOutputtingTo( String outputExpression );
1058 }
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068 @SuppressWarnings( "unchecked" )
1069 protected <ReturnType extends ModeShapeConfiguration> MimeTypeDetectorDefinition<ReturnType> mimeTypeDetectorDefinition( ReturnType returnObject,
1070 String name ) {
1071 MimeTypeDetectorDefinition<ReturnType> definition = (MimeTypeDetectorDefinition<ReturnType>)mimeTypeDetectorDefinitions.get(name);
1072 if (definition == null) {
1073 definition = new MimeTypeDetectorBuilder<ReturnType>(returnObject, changes(), path(),
1074 ModeShapeLexicon.MIME_TYPE_DETECTORS, name(name));
1075 mimeTypeDetectorDefinitions.put(name, definition);
1076 }
1077 return definition;
1078 }
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088 @SuppressWarnings( "unchecked" )
1089 protected <ReturnType extends ModeShapeConfiguration> RepositorySourceDefinition<ReturnType> repositorySourceDefinition( ReturnType returnObject,
1090 String name ) {
1091 RepositorySourceDefinition<ReturnType> definition = (RepositorySourceDefinition<ReturnType>)repositorySourceDefinitions.get(name);
1092 if (definition == null) {
1093 definition = new SourceBuilder<ReturnType>(returnObject, changes(), path(), ModeShapeLexicon.SOURCES, name(name));
1094 repositorySourceDefinitions.put(name, definition);
1095 }
1096 return definition;
1097 }
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107 @SuppressWarnings( "unchecked" )
1108 protected <ReturnType extends ModeShapeConfiguration> SequencerDefinition<ReturnType> sequencerDefinition( ReturnType returnObject,
1109 String name ) {
1110 SequencerDefinition<ReturnType> definition = (SequencerDefinition<ReturnType>)sequencerDefinitions.get(name);
1111 if (definition == null) {
1112 definition = new SequencerBuilder<ReturnType>(returnObject, changes(), path(), ModeShapeLexicon.SEQUENCERS,
1113 name(name));
1114 sequencerDefinitions.put(name, definition);
1115 }
1116 return definition;
1117 }
1118
1119
1120
1121
1122
1123
1124
1125
1126 @SuppressWarnings( "unchecked" )
1127 protected <ReturnType extends ModeShapeConfiguration> ClusterDefinition<ReturnType> clusterDefinition( ReturnType returnObject ) {
1128 if (clusterDefinition == null) {
1129 clusterDefinition = new ClusterBuilder<ReturnType>(returnObject, changes(), path(), ModeShapeLexicon.CLUSTERING);
1130 }
1131 return (ClusterDefinition<ReturnType>)clusterDefinition;
1132 }
1133
1134 protected static class BaseReturnable<ReturnType> implements Returnable<ReturnType> {
1135 protected final ReturnType returnObject;
1136
1137 protected BaseReturnable( ReturnType returnObject ) {
1138 this.returnObject = returnObject;
1139 }
1140
1141
1142
1143
1144
1145
1146 public ReturnType and() {
1147 return returnObject;
1148 }
1149 }
1150
1151
1152
1153
1154
1155
1156
1157 protected static abstract class GraphReturnable<ReturnType, ThisType> extends BaseReturnable<ReturnType>
1158 implements SetDescription<ThisType>, SetProperties<ThisType>, Removable<ReturnType> {
1159 protected final ExecutionContext context;
1160 protected final Graph.Batch batch;
1161 protected final Path path;
1162 private Map<Name, Property> properties = new HashMap<Name, Property>();
1163
1164 protected GraphReturnable( ReturnType returnObject,
1165 Graph.Batch batch,
1166 Path path,
1167 Name... names ) {
1168 super(returnObject);
1169 assert batch != null;
1170 assert path != null;
1171 assert names.length > 0;
1172 this.context = batch.getGraph().getContext();
1173 this.batch = batch;
1174
1175 createIfMissing(path, names).and();
1176 this.path = context.getValueFactories().getPathFactory().create(path, names);
1177 try {
1178 properties = batch.getGraph().getPropertiesByName().on(this.path);
1179 } catch (PathNotFoundException e) {
1180
1181 properties = new HashMap<Name, Property>();
1182 }
1183 }
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193 protected Graph.Create<Graph.Batch> createIfMissing( Name child,
1194 String... segments ) {
1195 Path nodePath = context.getValueFactories().getPathFactory().create(path, child);
1196 Graph.Create<Graph.Batch> result = batch.create(nodePath).orUpdate();
1197 for (String name : segments) {
1198 result.and();
1199 nodePath = context.getValueFactories().getPathFactory().create(nodePath, name);
1200 result = batch.create(nodePath).orUpdate();
1201 }
1202 return result;
1203 }
1204
1205
1206
1207
1208
1209
1210
1211
1212 protected Graph.Create<Graph.Batch> createIfMissing( Name segment ) {
1213 Path nodePath = context.getValueFactories().getPathFactory().create(path, segment);
1214 Graph.Create<Graph.Batch> result = batch.create(nodePath).orUpdate();
1215 return result;
1216 }
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226 protected Graph.Create<Graph.Batch> createIfMissing( Path path,
1227 Name... segments ) {
1228 Path nodePath = path;
1229 Graph.Create<Graph.Batch> result = null;
1230 for (Name name : segments) {
1231 if (result != null) result.and();
1232 nodePath = context.getValueFactories().getPathFactory().create(nodePath, name);
1233 result = batch.create(nodePath).orUpdate();
1234 }
1235 return result;
1236 }
1237
1238 protected Path subpath( Name... segments ) {
1239 return context.getValueFactories().getPathFactory().create(path, segments);
1240 }
1241
1242 protected abstract ThisType thisType();
1243
1244 public String getName() {
1245 return path.getLastSegment().getName().getString(context.getNamespaceRegistry());
1246 }
1247
1248 public ThisType setDescription( String description ) {
1249 return setProperty(ModeShapeLexicon.DESCRIPTION, description);
1250 }
1251
1252 public String getDescription() {
1253 Property property = getProperty(ModeShapeLexicon.DESCRIPTION);
1254 if (property != null && !property.isEmpty()) {
1255 return context.getValueFactories().getStringFactory().create(property.getFirstValue());
1256 }
1257 return null;
1258 }
1259
1260 protected ThisType setProperty( Name propertyName,
1261 Object value ) {
1262
1263 batch.set(propertyName).on(path).to(value).and();
1264
1265 properties.put(propertyName, context.getPropertyFactory().create(propertyName, value));
1266 return thisType();
1267 }
1268
1269 public ThisType setProperty( String propertyName,
1270 Object value ) {
1271 return setProperty(context.getValueFactories().getNameFactory().create(propertyName), value);
1272 }
1273
1274 public ThisType setProperty( Name propertyName,
1275 Object[] values ) {
1276
1277 batch.set(propertyName).on(path).to(values).and();
1278
1279 properties.put(propertyName, context.getPropertyFactory().create(propertyName, values));
1280 return thisType();
1281 }
1282
1283 public ThisType setProperty( String propertyName,
1284 Object[] values ) {
1285 return setProperty(context.getValueFactories().getNameFactory().create(propertyName), values);
1286 }
1287
1288 public ThisType setProperty( String beanPropertyName,
1289 boolean value ) {
1290 return setProperty(beanPropertyName, (Object)value);
1291 }
1292
1293 public ThisType setProperty( String beanPropertyName,
1294 int value ) {
1295 return setProperty(beanPropertyName, (Object)value);
1296 }
1297
1298 public ThisType setProperty( String beanPropertyName,
1299 short value ) {
1300 return setProperty(beanPropertyName, (Object)value);
1301 }
1302
1303 public ThisType setProperty( String beanPropertyName,
1304 long value ) {
1305 return setProperty(beanPropertyName, (Object)value);
1306 }
1307
1308 public ThisType setProperty( String beanPropertyName,
1309 double value ) {
1310 return setProperty(beanPropertyName, (Object)value);
1311 }
1312
1313 public ThisType setProperty( String beanPropertyName,
1314 float value ) {
1315 return setProperty(beanPropertyName, (Object)value);
1316 }
1317
1318 public ThisType setProperty( String beanPropertyName,
1319 String value ) {
1320 return setProperty(beanPropertyName, (Object)value);
1321 }
1322
1323 public ThisType setProperty( String beanPropertyName,
1324 String firstValue,
1325 String... additionalValues ) {
1326 Object[] values = new Object[1 + additionalValues.length];
1327 values[0] = firstValue;
1328 System.arraycopy(additionalValues, 0, values, 1, additionalValues.length);
1329 return setProperty(beanPropertyName, values);
1330 }
1331
1332 public Property getProperty( String beanPropertyName ) {
1333 return properties.get(context.getValueFactories().getNameFactory().create(beanPropertyName));
1334 }
1335
1336 public Property getProperty( Name beanPropertyName ) {
1337 return properties.get(beanPropertyName);
1338 }
1339
1340 public ReturnType remove() {
1341 batch.delete(path);
1342 properties.clear();
1343 return and();
1344 }
1345 }
1346
1347
1348
1349
1350
1351
1352
1353
1354 protected static abstract class GraphComponentBuilder<ReturnType, ThisType, ComponentType>
1355 extends GraphReturnable<ReturnType, ThisType> implements ChooseClass<ComponentType, ThisType> {
1356 protected GraphComponentBuilder( ReturnType returnObject,
1357 Graph.Batch batch,
1358 Path path,
1359 Name... names ) {
1360 super(returnObject, batch, path, names);
1361 }
1362
1363 public LoadedFrom<ThisType> usingClass( final String classname ) {
1364 return new LoadedFrom<ThisType>() {
1365 public ThisType loadedFromClasspath() {
1366 return setProperty(ModeShapeLexicon.CLASSNAME, classname);
1367 }
1368
1369 public ThisType loadedFrom( String... classpath ) {
1370 List<String> classpaths = new ArrayList<String>();
1371
1372 for (String value : classpath) {
1373 if (value == null) continue;
1374 value = value.trim();
1375 if (value.length() == 0) continue;
1376 if (!classpaths.contains(value)) classpaths.add(value);
1377 }
1378 if (classpaths.size() != 0) {
1379 classpath = classpaths.toArray(new String[classpaths.size()]);
1380 setProperty(ModeShapeLexicon.CLASSPATH, classpath);
1381 }
1382 return setProperty(ModeShapeLexicon.CLASSNAME, classname);
1383 }
1384 };
1385 }
1386
1387 public ThisType usingClass( Class<? extends ComponentType> componentClass ) {
1388 return setProperty(ModeShapeLexicon.CLASSNAME, componentClass.getCanonicalName());
1389 }
1390 }
1391
1392 protected static class MimeTypeDetectorBuilder<ReturnType>
1393 extends GraphComponentBuilder<ReturnType, MimeTypeDetectorDefinition<ReturnType>, MimeTypeDetector>
1394 implements MimeTypeDetectorDefinition<ReturnType> {
1395 protected MimeTypeDetectorBuilder( ReturnType returnObject,
1396 Graph.Batch batch,
1397 Path path,
1398 Name... names ) {
1399 super(returnObject, batch, path, names);
1400 }
1401
1402 @Override
1403 protected MimeTypeDetectorBuilder<ReturnType> thisType() {
1404 return this;
1405 }
1406
1407 }
1408
1409 protected static class SourceBuilder<ReturnType>
1410 extends GraphComponentBuilder<ReturnType, RepositorySourceDefinition<ReturnType>, RepositorySource>
1411 implements RepositorySourceDefinition<ReturnType> {
1412 protected SourceBuilder( ReturnType returnObject,
1413 Graph.Batch batch,
1414 Path path,
1415 Name... names ) {
1416 super(returnObject, batch, path, names);
1417 }
1418
1419 @Override
1420 protected RepositorySourceDefinition<ReturnType> thisType() {
1421 return this;
1422 }
1423
1424 public RepositorySourceDefinition<ReturnType> setRetryLimit( int retryLimit ) {
1425 return setProperty(ModeShapeLexicon.RETRY_LIMIT, retryLimit);
1426 }
1427
1428 @Override
1429 public RepositorySourceDefinition<ReturnType> setProperty( String propertyName,
1430 Object value ) {
1431 Name name = context.getValueFactories().getNameFactory().create(propertyName);
1432
1433 if (name.getLocalName().equals(ModeShapeLexicon.RETRY_LIMIT.getLocalName())) name = ModeShapeLexicon.RETRY_LIMIT;
1434 if (name.getLocalName().equals(ModeShapeLexicon.DESCRIPTION.getLocalName())) name = ModeShapeLexicon.DESCRIPTION;
1435 return super.setProperty(name, value);
1436 }
1437
1438 @Override
1439 public Property getProperty( Name name ) {
1440
1441 if (name.getLocalName().equals(ModeShapeLexicon.RETRY_LIMIT.getLocalName())) name = ModeShapeLexicon.RETRY_LIMIT;
1442 if (name.getLocalName().equals(ModeShapeLexicon.DESCRIPTION.getLocalName())) name = ModeShapeLexicon.DESCRIPTION;
1443 return super.getProperty(name);
1444 }
1445 }
1446
1447 protected static class SequencerBuilder<ReturnType>
1448 extends GraphComponentBuilder<ReturnType, SequencerDefinition<ReturnType>, StreamSequencer>
1449 implements SequencerDefinition<ReturnType> {
1450
1451 protected SequencerBuilder( ReturnType returnObject,
1452 Graph.Batch batch,
1453 Path path,
1454 Name... names ) {
1455 super(returnObject, batch, path, names);
1456 }
1457
1458 @Override
1459 protected SequencerDefinition<ReturnType> thisType() {
1460 return this;
1461 }
1462
1463 public Set<PathExpression> getPathExpressions() {
1464 Set<PathExpression> expressions = new HashSet<PathExpression>();
1465 try {
1466 Property existingExpressions = getProperty(ModeShapeLexicon.PATH_EXPRESSION);
1467 if (existingExpressions != null) {
1468 for (Object existing : existingExpressions.getValuesAsArray()) {
1469 String existingExpression = context.getValueFactories().getStringFactory().create(existing);
1470 expressions.add(PathExpression.compile(existingExpression));
1471 }
1472 }
1473 } catch (PathNotFoundException e) {
1474
1475 }
1476 return expressions;
1477 }
1478
1479 public SequencerDefinition<ReturnType> sequencingFrom( PathExpression expression ) {
1480 CheckArg.isNotNull(expression, "expression");
1481 Set<PathExpression> compiledExpressions = getPathExpressions();
1482 compiledExpressions.add(expression);
1483 String[] strings = new String[compiledExpressions.size()];
1484 int index = 0;
1485 for (PathExpression compiledExpression : compiledExpressions) {
1486 strings[index++] = compiledExpression.getExpression();
1487 }
1488 setProperty(ModeShapeLexicon.PATH_EXPRESSION, strings);
1489 return this;
1490 }
1491
1492 public PathExpressionOutput<ReturnType> sequencingFrom( final String fromPathExpression ) {
1493 CheckArg.isNotEmpty(fromPathExpression, "fromPathExpression");
1494 return new PathExpressionOutput<ReturnType>() {
1495 public SequencerDefinition<ReturnType> andOutputtingTo( String into ) {
1496 CheckArg.isNotEmpty(into, "into");
1497 return sequencingFrom(PathExpression.compile(fromPathExpression + " => " + into));
1498 }
1499 };
1500 }
1501 }
1502
1503 protected static class ClusterBuilder<ReturnType>
1504 extends GraphComponentBuilder<ReturnType, ClusterDefinition<ReturnType>, ObservationBus>
1505 implements ClusterDefinition<ReturnType> {
1506
1507 protected ClusterBuilder( ReturnType returnObject,
1508 Graph.Batch batch,
1509 Path path,
1510 Name... names ) {
1511 super(returnObject, batch, path, names);
1512 }
1513
1514 @Override
1515 protected ClusterDefinition<ReturnType> thisType() {
1516 return this;
1517 }
1518 }
1519
1520
1521
1522
1523 @Immutable
1524 public static class ConfigurationDefinition {
1525 private final String name;
1526 private final ClassLoaderFactory classLoaderFactory;
1527 private final RepositorySource source;
1528 private final Path path;
1529 private final String workspace;
1530 private final ExecutionContext context;
1531 private Graph graph;
1532
1533 protected ConfigurationDefinition( String configurationName,
1534 RepositorySource source,
1535 String workspace,
1536 Path path,
1537 ExecutionContext context,
1538 ClassLoaderFactory classLoaderFactory ) {
1539 assert configurationName != null;
1540 assert source != null;
1541 this.name = configurationName;
1542 this.source = source;
1543 this.path = path != null ? path : RootPath.INSTANCE;
1544 this.workspace = workspace;
1545 this.context = context;
1546 this.classLoaderFactory = classLoaderFactory != null ? classLoaderFactory : new StandardClassLoaderFactory();
1547 }
1548
1549
1550
1551
1552
1553
1554 public String getName() {
1555 return name;
1556 }
1557
1558
1559
1560
1561
1562
1563 public RepositorySource getRepositorySource() {
1564 return source;
1565 }
1566
1567
1568
1569
1570
1571
1572 public Path getPath() {
1573 return path;
1574 }
1575
1576
1577
1578
1579
1580
1581 public String getWorkspace() {
1582 return workspace;
1583 }
1584
1585
1586
1587
1588 public ExecutionContext getContext() {
1589 return context;
1590 }
1591
1592
1593
1594
1595 public ClassLoaderFactory getClassLoaderFactory() {
1596 return classLoaderFactory;
1597 }
1598
1599
1600
1601
1602
1603
1604
1605 public ConfigurationDefinition with( String name ) {
1606 if (name == null) name = this.name;
1607 return new ConfigurationDefinition(name, source, workspace, path, context, classLoaderFactory);
1608 }
1609
1610
1611
1612
1613
1614
1615
1616 public ConfigurationDefinition with( Path path ) {
1617 return new ConfigurationDefinition(name, source, workspace, path, context, classLoaderFactory);
1618 }
1619
1620
1621
1622
1623
1624
1625
1626
1627 public ConfigurationDefinition withWorkspace( String workspace ) {
1628 return new ConfigurationDefinition(name, source, workspace, path, context, classLoaderFactory);
1629 }
1630
1631
1632
1633
1634
1635
1636
1637
1638 public ConfigurationDefinition with( ClassLoaderFactory classLoaderFactory ) {
1639 CheckArg.isNotNull(source, "source");
1640 return new ConfigurationDefinition(name, source, workspace, path, context, classLoaderFactory);
1641 }
1642
1643
1644
1645
1646
1647
1648
1649
1650 public ConfigurationDefinition with( RepositorySource source ) {
1651 return new ConfigurationDefinition(name, source, workspace, path, context, classLoaderFactory);
1652 }
1653
1654
1655
1656
1657
1658
1659 public Graph graph() {
1660 if (graph == null) {
1661 graph = Graph.create(source, context);
1662 if (workspace != null) graph.useWorkspace(workspace);
1663 }
1664 return graph;
1665 }
1666 }
1667 }