KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > config > schema > setup > StandardL2TVSConfigurationSetupManager


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
3  * notice. All rights reserved.
4  */

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 JavaDoc;
35 import java.io.IOException JavaDoc;
36 import java.io.InputStream JavaDoc;
37 import java.io.StringWriter JavaDoc;
38 import java.io.UnsupportedEncodingException JavaDoc;
39 import java.lang.reflect.Array JavaDoc;
40 import java.util.HashMap JavaDoc;
41 import java.util.HashSet JavaDoc;
42 import java.util.Map JavaDoc;
43 import java.util.Set JavaDoc;
44
45 /**
46  * The standard implementation of {@link com.tc.config.schema.setup.L2TVSConfigurationSetupManager}.
47  */

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 JavaDoc l2ConfigData;
57
58   private final String JavaDoc thisL2Identifier;
59   private L2ConfigData myConfigData;
60
61   public StandardL2TVSConfigurationSetupManager(ConfigurationCreator configurationCreator, String JavaDoc 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 JavaDoc();
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 JavaDoc name;
88     private final ChildBeanRepository beanRepository;
89
90     private final NewCommonL2Config commonL2Config;
91     private final NewL2DSOConfig dsoL2Config;
92
93     public L2ConfigData(String JavaDoc name) throws ConfigurationSetupException {
94       this.name = name;
95       findMyL2Bean(); // To get the exception in case things are screwed up
96

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 JavaDoc 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           // formatting
129
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 JavaDoc describeSources() {
156     return this.configurationCreator.describeSources();
157   }
158
159   private synchronized L2ConfigData configDataFor(String JavaDoc 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 JavaDoc 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         // formatting
184
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 JavaDoc 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 JavaDoc badServers = new HashSet JavaDoc();
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         // We have clustered DSO; they must all be in permanent-store mode
234
for (int i = 0; i < servers.length; ++i) {
235           String JavaDoc 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         // formatting
248
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 JavaDoc result = this.dsoApplicationConfigFor(TVSConfigurationSetupManagerFactory.DEFAULT_APPLICATION_NAME)
264           .roots().getObject();
265       if (result != null && Array.getLength(result) > 0) {
266         // formatting
267
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 JavaDoc 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 JavaDoc name) throws ConfigurationSetupException {
287     return configDataFor(name).dsoL2Config();
288   }
289
290   public NewL2DSOConfig dsoL2Config() {
291     return this.myConfigData.dsoL2Config();
292   }
293
294   public String JavaDoc[] 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 JavaDoc[] { null };
298     else {
299       String JavaDoc[] out = new String JavaDoc[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 JavaDoc rawConfigFile() {
307     // This MUST piece together the configuration from our currently-active bean repositories. If we just read the
308
// actual config file we got on startup, we'd be sending out, well, the config we got on startup -- which might be
309
// quite different from our current config, if an L1 came in and overrode our config.
310

311     TcConfigDocument doc = TcConfigDocument.Factory.newInstance();
312     TcConfigDocument.TcConfig config = doc.addNewTcConfig();
313
314     System JavaDoc system = (System JavaDoc) 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 JavaDoc sw = new StringWriter JavaDoc();
326     XmlOptions options = new XmlOptions().setSavePrettyPrint().setSavePrettyPrintIndent(4);
327
328     try {
329       doc.save(sw, options);
330     } catch (IOException JavaDoc ioe) {
331       throw Assert.failure("Unexpected failure writing to in-memory streams", ioe);
332     }
333
334     String JavaDoc text = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n\n" + sw.toString();
335
336     try {
337       return new ByteArrayInputStream JavaDoc(text.getBytes("UTF-8"));
338     } catch (UnsupportedEncodingException JavaDoc uee) {
339       throw Assert.failure("This shouldn't be possible", uee);
340     }
341   }
342
343 }
344
Popular Tags