001package com.nimbusds.infinispan.persistence.dynamodb.config;
002
003
004import java.util.Arrays;
005import java.util.HashSet;
006import java.util.Set;
007import javax.xml.stream.XMLStreamConstants;
008import javax.xml.stream.XMLStreamException;
009
010import static org.infinispan.commons.util.StringPropertyReplacer.replaceProperties;
011
012import com.amazonaws.regions.Regions;
013import org.infinispan.commons.CacheConfigurationException;
014import org.infinispan.configuration.cache.ConfigurationBuilder;
015import org.infinispan.configuration.cache.PersistenceConfigurationBuilder;
016import org.infinispan.configuration.parsing.*;
017import org.kohsuke.MetaInfServices;
018
019
020/**
021 * XML configuration parser for XML schema v1.8.
022 */
023@MetaInfServices
024@Namespaces({
025        @Namespace(uri = "urn:infinispan:config:store:dynamodb:1.8", root = "dynamodb-store"),
026        @Namespace(root = "dynamodb-store")
027})
028public class DynamoDBStoreConfigurationParser_1_8 implements ConfigurationParser {
029        
030        
031        @Override
032        public void readElement(final XMLExtendedStreamReader reader, final ConfigurationBuilderHolder holder)
033                throws XMLStreamException {
034                ConfigurationBuilder builder = holder.getCurrentConfigurationBuilder();
035                
036                Element element = Element.forName(reader.getLocalName());
037                switch (element) {
038                        case DYNAMODB_STORE: {
039                                this.parseDynamoDBStore(reader, builder.persistence(), holder.getClassLoader());
040                                break;
041                        }
042                        default: {
043                                throw ParseUtils.unexpectedElement(reader);
044                        }
045                }
046        }
047        
048        
049        /**
050         * Parses a DynamoDB store XML element.
051         */
052        private void parseDynamoDBStore(final XMLExtendedStreamReader reader,
053                                        final PersistenceConfigurationBuilder persistenceBuilder,
054                                        final ClassLoader classLoader)
055                throws XMLStreamException {
056                
057                DynamoDBStoreConfigurationBuilder builder = new DynamoDBStoreConfigurationBuilder(persistenceBuilder);
058                
059                this.parseDynamoDBStoreAttributes(reader, builder, classLoader);
060                
061                while (reader.hasNext() && (reader.nextTag() != XMLStreamConstants.END_ELEMENT)) {
062                        Element element = Element.forName(reader.getLocalName());
063                        switch (element) {
064                                default: {
065                                        Parser.parseStoreElement(reader, builder);
066                                        break;
067                                }
068                        }
069                }
070                
071                persistenceBuilder.addStore(builder);
072        }
073        
074        
075        /**
076         * Parses the attributes of an XML store element.
077         */
078        private void parseDynamoDBStoreAttributes(final XMLExtendedStreamReader reader,
079                                                  final DynamoDBStoreConfigurationBuilder builder,
080                                                  final ClassLoader classLoader)
081                throws XMLStreamException {
082                
083                for (int i = 0; i < reader.getAttributeCount(); i++) {
084                        ParseUtils.requireNoNamespaceAttribute(reader, i);
085                        String value = replaceProperties(reader.getAttributeValue(i));
086                        Attribute attribute = Attribute.forName(reader.getAttributeLocalName(i));
087                        switch (attribute) {
088                                
089                                case ENDPOINT:
090                                        builder.endpoint(value);
091                                        break;
092                                        
093                                case REGION:
094                                        try {
095                                                builder.region(Regions.fromName(value));
096                                        } catch (Exception e) {
097                                                throw new CacheConfigurationException(e);
098                                        }
099                                        break;
100                                
101                                case ITEM_TRANSFORMER:
102                                        try {
103                                                builder.itemTransformerClass(classLoader.loadClass(value));
104                                        } catch (ClassNotFoundException e) {
105                                                throw new CacheConfigurationException(e);
106                                        }
107                                        break;
108                                        
109                                case QUERY_EXECUTOR:
110                                        try {
111                                                builder.queryExecutorClass(classLoader.loadClass(value));
112                                        } catch (ClassNotFoundException e) {
113                                                throw new CacheConfigurationException(e);
114                                        }
115                                        
116                                case INDEXED_ATTRIBUTES:
117                                        builder.indexedAttributes(parseStringSet(value));
118                                        break;
119                                        
120                                case CONSISTENT_READS:
121                                        builder.consistentReads(Boolean.parseBoolean(value));
122                                        break;
123                                        
124                                case READ_CAPACITY:
125                                        try {
126                                                builder.readCapacity(Long.parseLong(value));
127                                        } catch (NumberFormatException e) {
128                                                throw new CacheConfigurationException(e);
129                                        }
130                                        break;
131                                        
132                                case WRITE_CAPACITY:
133                                        try {
134                                                builder.writeCapacity(Long.parseLong(value));
135                                        } catch (NumberFormatException e) {
136                                                throw new CacheConfigurationException(e);
137                                        }
138                                        break;
139                                
140                                case ENCRYPTION_AT_REST:
141                                        builder.tableWithEncryptionAtRest(Boolean.parseBoolean(value));
142                                        break;
143                                
144                                case TABLE_PREFIX:
145                                        builder.tablePrefix(value);
146                                        break;
147                                        
148                                case APPLY_RANGE_KEY:
149                                        builder.applyRangeKey(value);
150                                        break;
151                                        
152                                case RANGE_KEY_VALUE:
153                                        builder.rangeKeyValue(value);
154                                        break;
155                                        
156                                case ENABLE_STREAM:
157                                        builder.enableStream(Boolean.parseBoolean(value));
158                                        break;
159                                        
160                                case ENABLE_CONTINUOUS_BACKUPS:
161                                        builder.enableContinuousBackups(Boolean.parseBoolean(value));
162                                        break;
163                                        
164                                case ENABLE_TTL:
165                                        builder.enableTTL(Boolean.parseBoolean(value));
166                                        break;
167                                        
168                                case PURGE_LIMIT:
169                                        try {
170                                                builder.purgeLimit(Integer.parseInt(value));
171                                        } catch (NumberFormatException e) {
172                                                throw new CacheConfigurationException(e);
173                                        }
174                                        break;
175                                        
176                                case HTTP_PROXY_HOST:
177                                        if (value != null && ! value.trim().isEmpty()) {
178                                                builder.httpProxyHost(value);
179                                        }
180                                        break;
181                                        
182                                case HTTP_PROXY_PORT:
183                                        try {
184                                                builder.httpProxyPort(Integer.parseInt(value));
185                                        } catch (NumberFormatException e) {
186                                                throw new CacheConfigurationException(e);
187                                        }
188                                        break;
189                                        
190                                case HMAC_SHA256_KEY:
191                                        if (value != null && ! value.trim().isEmpty()) {
192                                                builder.hmacSHA256Key(value);
193                                        }
194                                        break;
195                                
196                                default: {
197                                        Parser.parseStoreAttribute(reader, i, builder);
198                                        break;
199                                }
200                        }
201                }
202        }
203        
204        
205        @Override
206        public Namespace[] getNamespaces() {
207                return ParseUtils.getNamespaceAnnotations(getClass());
208        }
209        
210        
211        /**
212         * Splits a string of comma and / or white space separated strings
213         * into a string set.
214         *
215         * @param s The string to split, {@code null} if not specified.
216         *
217         * @return The string set, {@code null} if not specified.
218         */
219        static Set<String> parseStringSet(final String s) {
220                
221                if (null == s || s.trim().isEmpty()) {
222                        return null;
223                }
224                
225                return new HashSet<>(Arrays.asList(s.replaceAll("^[,\\s]+", "").split("[,\\s]+")));
226        }
227}