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 DynamoDBStoreConfigurationParser17 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}