001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.config.store; 018 019import static org.apache.juneau.commons.utils.AssertionUtils.*; 020import static org.apache.juneau.commons.utils.Utils.*; 021 022import java.io.*; 023import java.lang.annotation.*; 024import java.util.concurrent.*; 025 026import org.apache.juneau.*; 027import org.apache.juneau.commons.collections.*; 028 029/** 030 * Filesystem-based storage location for configuration files. 031 * 032 * <p> 033 * Points to a file system directory containing configuration files. 034 * 035 * <h5 class='section'>Notes:</h5><ul> 036 * <li class='note'>This class is thread safe and reusable. 037 * </ul> 038 */ 039@SuppressWarnings("resource") 040public class MemoryStore extends ConfigStore { 041 /** 042 * Builder class. 043 */ 044 public static class Builder extends ConfigStore.Builder { 045 046 /** 047 * Constructor, default settings. 048 */ 049 protected Builder() {} 050 051 /** 052 * Copy constructor. 053 * 054 * @param copyFrom The builder to copy from. 055 * <br>Cannot be <jk>null</jk>. 056 */ 057 protected Builder(Builder copyFrom) { 058 super(assertArgNotNull("copyFrom", copyFrom)); 059 } 060 061 /** 062 * Copy constructor. 063 * 064 * @param copyFrom The bean to copy from. 065 * <br>Cannot be <jk>null</jk>. 066 */ 067 protected Builder(MemoryStore copyFrom) { 068 super(assertArgNotNull("copyFrom", copyFrom)); 069 type(copyFrom.getClass()); 070 } 071 072 @Override /* Overridden from Builder */ 073 public Builder annotations(Annotation...values) { 074 super.annotations(values); 075 return this; 076 } 077 078 @Override /* Overridden from Builder */ 079 public Builder apply(AnnotationWorkList work) { 080 super.apply(work); 081 return this; 082 } 083 084 @Override /* Overridden from Builder */ 085 public Builder applyAnnotations(Class<?>...from) { 086 super.applyAnnotations(from); 087 return this; 088 } 089 090 @Override /* Overridden from Builder */ 091 public Builder applyAnnotations(Object...from) { 092 super.applyAnnotations(from); 093 return this; 094 } 095 096 @Override /* Overridden from Context.Builder */ 097 public MemoryStore build() { 098 return build(MemoryStore.class); 099 } 100 101 @Override /* Overridden from Builder */ 102 public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) { 103 super.cache(value); 104 return this; 105 } 106 107 @Override /* Overridden from Context.Builder */ 108 public Builder copy() { 109 return new Builder(this); 110 } 111 112 @Override /* Overridden from Builder */ 113 public Builder debug() { 114 super.debug(); 115 return this; 116 } 117 118 @Override /* Overridden from Builder */ 119 public Builder debug(boolean value) { 120 super.debug(value); 121 return this; 122 } 123 124 @Override /* Overridden from Builder */ 125 public Builder impl(Context value) { 126 super.impl(value); 127 return this; 128 } 129 130 @Override /* Overridden from Builder */ 131 public Builder type(Class<? extends org.apache.juneau.Context> value) { 132 super.type(value); 133 return this; 134 } 135 } 136 137 /** Default memory store, all default values.*/ 138 public static final MemoryStore DEFAULT = MemoryStore.create().build(); 139 140 /** 141 * Creates a new builder for this object. 142 * 143 * @return A new builder. 144 */ 145 public static Builder create() { 146 return new Builder(); 147 } 148 149 private final ConcurrentHashMap<String,String> cache = new ConcurrentHashMap<>(); 150 151 /** 152 * Constructor. 153 * 154 * @param builder The builder for this object. 155 */ 156 public MemoryStore(Builder builder) { 157 super(builder); 158 } 159 160 /** 161 * No-op. 162 */ 163 @Override /* Overridden from Closeable */ 164 public void close() throws IOException { 165 // No-op 166 } 167 168 @Override /* Overridden from Context */ 169 public Builder copy() { 170 return new Builder(this); 171 } 172 173 @Override /* Overridden from ConfigStore */ 174 public synchronized boolean exists(String name) { 175 return cache.containsKey(name); 176 } 177 178 @Override /* Overridden from ConfigStore */ 179 public synchronized String read(String name) { 180 return emptyIfNull(cache.get(name)); 181 } 182 183 @Override /* Overridden from ConfigStore */ 184 public synchronized MemoryStore update(String name, String newContents) { 185 if (newContents == null) 186 cache.remove(name); 187 else 188 cache.put(name, newContents); 189 super.update(name, newContents); // Trigger any listeners. 190 return this; 191 } 192 193 @Override /* Overridden from ConfigStore */ 194 public synchronized String write(String name, String expectedContents, String newContents) { 195 196 // This is a no-op. 197 if (eq(expectedContents, newContents)) 198 return null; 199 200 var currentContents = read(name); 201 202 if (nn(expectedContents) && neq(currentContents, expectedContents)) 203 return currentContents; 204 205 update(name, newContents); 206 207 return null; 208 } 209}