1 5 package com.tc.config.schema.setup; 6 7 import org.apache.xmlbeans.XmlObject; 8 import org.apache.xmlbeans.XmlOptions; 9 10 import com.tc.capabilities.AbstractCapabilitiesFactory; 11 import com.tc.capabilities.Capabilities; 12 import com.tc.config.schema.IllegalConfigurationChangeHandler; 13 import com.tc.config.schema.NewCommonL2Config; 14 import com.tc.config.schema.NewCommonL2ConfigObject; 15 import com.tc.config.schema.NewSystemConfig; 16 import com.tc.config.schema.NewSystemConfigObject; 17 import com.tc.config.schema.defaults.DefaultValueProvider; 18 import com.tc.config.schema.repository.ChildBeanFetcher; 19 import com.tc.config.schema.repository.ChildBeanRepository; 20 import com.tc.config.schema.utils.XmlObjectComparator; 21 import com.tc.logging.TCLogger; 22 import com.tc.logging.TCLogging; 23 import com.tc.object.config.schema.NewL2DSOConfig; 24 import com.tc.object.config.schema.NewL2DSOConfigObject; 25 import com.tc.object.config.schema.PersistenceMode; 26 import com.tc.util.Assert; 27 import com.terracottatech.config.Application; 28 import com.terracottatech.config.Client; 29 import com.terracottatech.config.Server; 30 import com.terracottatech.config.Servers; 31 import com.terracottatech.config.System; 32 import com.terracottatech.config.TcConfigDocument; 33 34 import java.io.ByteArrayInputStream ; 35 import java.io.IOException ; 36 import java.io.InputStream ; 37 import java.io.StringWriter ; 38 import java.io.UnsupportedEncodingException ; 39 import java.lang.reflect.Array ; 40 import java.util.HashMap ; 41 import java.util.HashSet ; 42 import java.util.Map ; 43 import java.util.Set ; 44 45 48 public class StandardL2TVSConfigurationSetupManager extends BaseTVSConfigurationSetupManager implements 49 L2TVSConfigurationSetupManager { 50 51 private static TCLogger logger = TCLogging.getLogger(StandardL2TVSConfigurationSetupManager.class); 52 53 private final ConfigurationCreator configurationCreator; 54 55 private NewSystemConfig systemConfig; 56 private final Map l2ConfigData; 57 58 private final String thisL2Identifier; 59 private L2ConfigData myConfigData; 60 61 public StandardL2TVSConfigurationSetupManager(ConfigurationCreator configurationCreator, String thisL2Identifier, 62 DefaultValueProvider defaultValueProvider, 63 XmlObjectComparator xmlObjectComparator, 64 IllegalConfigurationChangeHandler illegalConfigChangeHandler) 65 throws ConfigurationSetupException { 66 super(defaultValueProvider, xmlObjectComparator, illegalConfigChangeHandler); 67 68 Assert.assertNotNull(configurationCreator); 69 Assert.assertNotNull(defaultValueProvider); 70 Assert.assertNotNull(xmlObjectComparator); 71 72 this.configurationCreator = configurationCreator; 73 74 this.systemConfig = null; 75 this.l2ConfigData = new HashMap (); 76 77 this.thisL2Identifier = thisL2Identifier; 78 this.myConfigData = null; 79 80 runConfigurationCreator(this.configurationCreator); 81 82 selectL2((Servers) serversBeanRepository().bean(), "the set of L2s known to us"); 83 validateRestrictions(); 84 } 85 86 private class L2ConfigData { 87 private final String name; 88 private final ChildBeanRepository beanRepository; 89 90 private final NewCommonL2Config commonL2Config; 91 private final NewL2DSOConfig dsoL2Config; 92 93 public L2ConfigData(String name) throws ConfigurationSetupException { 94 this.name = name; 95 findMyL2Bean(); 97 this.beanRepository = new ChildBeanRepository(serversBeanRepository(), Server.class, new BeanFetcher()); 98 99 this.commonL2Config = new NewCommonL2ConfigObject(createContext(this.beanRepository, configurationCreator 100 .directoryConfigurationLoadedFrom())); 101 this.dsoL2Config = new NewL2DSOConfigObject(createContext(this.beanRepository, configurationCreator 102 .directoryConfigurationLoadedFrom())); 103 } 104 105 public String name() { 106 return this.name; 107 } 108 109 public NewCommonL2Config commonL2Config() { 110 return this.commonL2Config; 111 } 112 113 public NewL2DSOConfig dsoL2Config() { 114 return this.dsoL2Config; 115 } 116 117 public boolean explicitlySpecifiedInConfigFile() throws ConfigurationSetupException { 118 return findMyL2Bean() != null; 119 } 120 121 private Server findMyL2Bean() throws ConfigurationSetupException { 122 Servers servers = (Servers) serversBeanRepository().bean(); 123 Server[] l2Array = servers == null ? null : servers.getServerArray(); 124 125 if (l2Array == null || l2Array.length == 0) return null; 126 else if (this.name == null) { 127 if (l2Array.length > 1) { 128 throw new ConfigurationSetupException("You have not specified a name for your L2, and there are " 130 + l2Array.length + " L2s defined in the configuration file. " + "You must indicate which L2 this is."); 131 } else { 132 return l2Array[0]; 133 } 134 } else { 135 for (int i = 0; i < l2Array.length; ++i) { 136 if (this.name.trim().equalsIgnoreCase(l2Array[i].getName().trim())) { return l2Array[i]; } 137 } 138 } 139 140 return null; 141 } 142 143 private class BeanFetcher implements ChildBeanFetcher { 144 public XmlObject getChild(XmlObject parent) { 145 try { 146 return findMyL2Bean(); 147 } catch (ConfigurationSetupException cse) { 148 logger.warn("Unable to find L2 bean for L2 '" + name + "'", cse); 149 return null; 150 } 151 } 152 } 153 } 154 155 public String describeSources() { 156 return this.configurationCreator.describeSources(); 157 } 158 159 private synchronized L2ConfigData configDataFor(String name) throws ConfigurationSetupException { 160 L2ConfigData out = (L2ConfigData) this.l2ConfigData.get(name); 161 162 if (out == null) { 163 out = new L2ConfigData(name); 164 165 Servers servers = (Servers) this.serversBeanRepository().bean(); 166 String list = "[data unavailable]"; 167 168 if (servers != null) { 169 Server[] serverList = servers.getServerArray(); 170 171 if (serverList != null) { 172 list = ""; 173 174 for (int i = 0; i < serverList.length; ++i) { 175 if (i > 0) list += ", "; 176 if (i == serverList.length - 1) list += "and "; 177 list += "'" + serverList[i].getName() + "'"; 178 } 179 } 180 } 181 182 if ((!out.explicitlySpecifiedInConfigFile()) && name != null) { 183 throw new ConfigurationSetupException("Multiple <server> elements are defined in the configuration file. " 185 + "As such, each server that you start needs to know which configuration " + "it should use.\n\n" 186 + "However, this server couldn't figure out which one it is -- it thinks it's " + "called '" + name 187 + "' (which, by default, is the host name of this machine), but you've only " 188 + "created <server> elements in the config file called " + list 189 + ".\n\nPlease re-start the server with a '-n <name>' argument on the command line to tell this " 190 + "server which one it is, or change the 'name' attributes of the <server> " 191 + "elements in the config file as appropriate."); 192 } 193 194 this.l2ConfigData.put(name, out); 195 } 196 197 return out; 198 } 199 200 private void selectL2(Servers servers, final String description) throws ConfigurationSetupException { 201 this.systemConfig = new NewSystemConfigObject(createContext(systemBeanRepository(), configurationCreator 202 .directoryConfigurationLoadedFrom())); 203 204 if (this.allCurrentlyKnownServers().length == 1) { 205 if (servers != null && servers.getServerArray() != null && servers.getServerArray()[0] != null) { 206 this.myConfigData = configDataFor(servers.getServerArray()[0].getName()); 207 } else { 208 this.myConfigData = configDataFor(null); 209 } 210 } else this.myConfigData = configDataFor(this.thisL2Identifier); 211 212 LogSettingConfigItemListener listener = new LogSettingConfigItemListener(TCLogging.PROCESS_TYPE_L2); 213 this.myConfigData.commonL2Config().logsPath().addListener(listener); 214 listener.valueChanged(null, this.myConfigData.commonL2Config().logsPath().getObject()); 215 } 216 217 private void validateRestrictions() throws ConfigurationSetupException { 218 validateLicenseModuleRestrictions(); 219 validateDSOClusterPersistenceMode(); 220 } 221 222 private void validateDSOClusterPersistenceMode() throws ConfigurationSetupException { 223 if (super.serversBeanRepository().bean() != null) { 224 Server[] servers = ((Servers) super.serversBeanRepository().bean()).getServerArray(); 225 Set badServers = new HashSet (); 226 227 if (servers != null && servers.length > 1) { 228 Capabilities capabilities = AbstractCapabilitiesFactory.getCapabilitiesManager(); 229 230 if (!capabilities.hasHA() && capabilities.canClusterPOJOs()) { throw new ConfigurationSetupException( 231 "Attempting to run multiple servers without license " + "authorization of DSO High Availability."); } 232 233 for (int i = 0; i < servers.length; ++i) { 235 String name = servers[i].getName(); 236 L2ConfigData data = configDataFor(name); 237 238 Assert.assertNotNull(data); 239 if (!capabilities.hasHAOverNetwork() 240 && !(data.dsoL2Config().persistenceMode().getObject().equals(PersistenceMode.PERMANENT_STORE))) { 241 badServers.add(name); 242 } 243 } 244 } 245 246 if (badServers.size() > 0) { 247 throw new ConfigurationSetupException("Your Terracotta system has a clustered DSO configuration -- i.e., " 249 + "DSO is enabled, and more than one server is defined in the configuration file -- but " 250 + "at least one server is in the '" + PersistenceMode.TEMPORARY_SWAP_ONLY 251 + "' persistence mode. (Servers in this mode: " + badServers + ".) In a " 252 + "clustered DSO configuration, all servers must be in the '" + PersistenceMode.PERMANENT_STORE 253 + "' mode. Please adjust the " + "persistence/mode element (inside the 'server' element) in your " 254 + "configuration file; see the Terracotta documentation for more details."); 255 } 256 } 257 } 258 259 private void validateLicenseModuleRestrictions() throws ConfigurationSetupException { 260 Capabilities capabilities = AbstractCapabilitiesFactory.getCapabilitiesManager(); 261 262 if (!capabilities.canClusterPOJOs()) { 263 Object result = this.dsoApplicationConfigFor(TVSConfigurationSetupManagerFactory.DEFAULT_APPLICATION_NAME) 264 .roots().getObject(); 265 if (result != null && Array.getLength(result) > 0) { 266 throw new ConfigurationSetupException("Your Terracotta license, " + capabilities.describe() 268 + ", does not allow you to define DSO roots in your configuration file. Please remove them and try again."); 269 } 270 } 271 272 } 273 274 public NewCommonL2Config commonL2ConfigFor(String name) throws ConfigurationSetupException { 275 return configDataFor(name).commonL2Config(); 276 } 277 278 public NewCommonL2Config commonl2Config() { 279 return this.myConfigData.commonL2Config(); 280 } 281 282 public NewSystemConfig systemConfig() { 283 return this.systemConfig; 284 } 285 286 public NewL2DSOConfig dsoL2ConfigFor(String name) throws ConfigurationSetupException { 287 return configDataFor(name).dsoL2Config(); 288 } 289 290 public NewL2DSOConfig dsoL2Config() { 291 return this.myConfigData.dsoL2Config(); 292 } 293 294 public String [] allCurrentlyKnownServers() { 295 Servers serversBean = (Servers) serversBeanRepository().bean(); 296 Server[] l2s = serversBean == null ? null : serversBean.getServerArray(); 297 if (l2s == null || l2s.length == 0) return new String [] { null }; 298 else { 299 String [] out = new String [l2s.length]; 300 for (int i = 0; i < l2s.length; ++i) 301 out[i] = l2s[i].getName(); 302 return out; 303 } 304 } 305 306 public InputStream rawConfigFile() { 307 311 TcConfigDocument doc = TcConfigDocument.Factory.newInstance(); 312 TcConfigDocument.TcConfig config = doc.addNewTcConfig(); 313 314 System system = (System ) this.systemBeanRepository().bean(); 315 Client client = (Client) this.clientBeanRepository().bean(); 316 Servers servers = (Servers) this.serversBeanRepository().bean(); 317 Application application = (Application) this.applicationsRepository().repositoryFor( 318 TVSConfigurationSetupManagerFactory.DEFAULT_APPLICATION_NAME).bean(); 319 320 if (system != null) config.setSystem(system); 321 if (client != null) config.setClients(client); 322 if (servers != null) config.setServers(servers); 323 if (application != null) config.setApplication(application); 324 325 StringWriter sw = new StringWriter (); 326 XmlOptions options = new XmlOptions().setSavePrettyPrint().setSavePrettyPrintIndent(4); 327 328 try { 329 doc.save(sw, options); 330 } catch (IOException ioe) { 331 throw Assert.failure("Unexpected failure writing to in-memory streams", ioe); 332 } 333 334 String text = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n" + sw.toString(); 335 336 try { 337 return new ByteArrayInputStream (text.getBytes("UTF-8")); 338 } catch (UnsupportedEncodingException uee) { 339 throw Assert.failure("This shouldn't be possible", uee); 340 } 341 } 342 343 } 344 | Popular Tags |