001: /*
002: * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.object.config;
006:
007: import org.apache.commons.lang.ArrayUtils;
008:
009: import com.tc.config.schema.setup.ConfigurationSetupException;
010: import com.tc.logging.TCLogger;
011: import com.tc.object.config.schema.ExcludedInstrumentedClass;
012: import com.tc.object.config.schema.IncludeOnLoad;
013: import com.tc.object.config.schema.IncludedInstrumentedClass;
014: import com.tc.util.Assert;
015: import com.tc.util.ClassUtils;
016: import com.tc.util.ClassUtils.ClassSpec;
017: import com.terracottatech.config.AdditionalBootJarClasses;
018: import com.terracottatech.config.Autolock;
019: import com.terracottatech.config.DistributedMethods;
020: import com.terracottatech.config.DsoApplication;
021: import com.terracottatech.config.Include;
022: import com.terracottatech.config.InstrumentedClasses;
023: import com.terracottatech.config.LockLevel;
024: import com.terracottatech.config.Locks;
025: import com.terracottatech.config.NamedLock;
026: import com.terracottatech.config.NonDistributedFields;
027: import com.terracottatech.config.OnLoad;
028: import com.terracottatech.config.Root;
029: import com.terracottatech.config.Roots;
030: import com.terracottatech.config.SpringAppContext;
031: import com.terracottatech.config.SpringApplication;
032: import com.terracottatech.config.SpringApps;
033: import com.terracottatech.config.SpringBean;
034: import com.terracottatech.config.SpringDistributedEvent;
035: import com.terracottatech.config.SpringPath;
036: import com.terracottatech.config.TransientFields;
037: import com.terracottatech.config.WebApplication;
038: import com.terracottatech.config.WebApplications;
039: import com.terracottatech.config.DistributedMethods.MethodExpression;
040:
041: import java.text.ParseException;
042: import java.util.Arrays;
043: import java.util.HashSet;
044: import java.util.Iterator;
045: import java.util.Set;
046:
047: public class ConfigLoader {
048: private final DSOClientConfigHelper config;
049: private final TCLogger logger;
050:
051: public ConfigLoader(DSOClientConfigHelper config, TCLogger logger) {
052: this .config = config;
053: this .logger = logger;
054: }
055:
056: public void loadDsoConfig(DsoApplication dsoApplication)
057: throws ConfigurationSetupException {
058: if (dsoApplication != null) {
059: Roots rootsList = dsoApplication.getRoots();
060: if (rootsList != null && rootsList.getRootArray() != null) {
061: Root[] roots = rootsList.getRootArray();
062: for (int i = 0; i < roots.length; ++i) {
063: Root root = roots[i];
064: try {
065: String rootName = root.getRootName();
066: String fieldName = root.getFieldName();
067: String fieldExpression = root
068: .getFieldExpression();
069:
070: // XXX: It would be nice to enforce this constraint in XML Schema
071: if (fieldName == null
072: && fieldExpression == null) {
073: throw new ConfigurationSetupException(
074: "must specify either field-name or field-expression");
075: }
076:
077: if (fieldName != null
078: && fieldExpression != null) {
079: throw new ConfigurationSetupException(
080: "cannot specify both field-name and field-expression");
081: }
082:
083: Assert
084: .assertTrue((fieldName != null && fieldExpression == null)
085: || (fieldName == null && fieldExpression != null));
086:
087: if (fieldName != null) {
088: ClassSpec classSpec = ClassUtils
089: .parseFullyQualifiedFieldName(fieldName);
090: String className = classSpec
091: .getFullyQualifiedClassName();
092: config
093: .addRoot(
094: new com.tc.object.config.Root(
095: className,
096: classSpec
097: .getShortFieldName(),
098: rootName), false);
099: } else if (fieldExpression != null) {
100: config.addRoot(
101: new com.tc.object.config.Root(
102: fieldExpression, rootName),
103: false);
104: } else {
105: throw new AssertionError();
106: }
107: } catch (ParseException pe) {
108: throw new ConfigurationSetupException("Root '"
109: + root.getFieldName() + "' is invalid",
110: pe);
111: }
112: }
113: }
114:
115: WebApplications webApplicationsList = dsoApplication
116: .getWebApplications();
117: if (webApplicationsList != null
118: && webApplicationsList.getWebApplicationArray() != null) {
119: WebApplication[] webApplications = webApplicationsList
120: .getWebApplicationArray();
121: for (int i = 0; i < webApplications.length; i++) {
122: config.addApplicationName(webApplications[i]
123: .getStringValue());
124: if (webApplications[i].getSynchronousWrite()) {
125: config
126: .addSynchronousWriteApplication(webApplications[i]
127: .getStringValue());
128: }
129: }
130: }
131:
132: loadLocks(dsoApplication.getLocks());
133: loadTransientFields(dsoApplication.getTransientFields());
134: loadInstrumentedClasses(dsoApplication
135: .getInstrumentedClasses());
136: loadDistributedMethods(dsoApplication
137: .getDistributedMethods());
138:
139: AdditionalBootJarClasses additionalBootJarClassesList = dsoApplication
140: .getAdditionalBootJarClasses();
141: // XXX
142: if (additionalBootJarClassesList != null) {
143: Set userDefinedBootClassNames = new HashSet();
144: userDefinedBootClassNames.addAll(Arrays
145: .asList(additionalBootJarClassesList
146: .getIncludeArray()));
147: logger.debug("Additional boot-jar classes: "
148: + ArrayUtils
149: .toString(userDefinedBootClassNames));
150:
151: for (Iterator i = userDefinedBootClassNames.iterator(); i
152: .hasNext();) {
153: String className = (String) i.next();
154: TransparencyClassSpec spec = config
155: .getSpec(className);
156: if (spec == null) {
157: spec = new TransparencyClassSpecImpl(className,
158: config);
159: spec.markPreInstrumented();
160: config.addUserDefinedBootSpec(spec
161: .getClassName(), spec);
162: } else if (!spec.isPreInstrumented()) {
163: // DEV-458: if the class being added to the boot jar defines locks/distributed methods/etc. it creates a
164: // spec but does not pre-instrument it. This makes sure that the adapted code gets into the boot jar in
165: // this case.
166: spec.markPreInstrumented();
167: }
168: }
169: }
170: }
171: }
172:
173: public void loadSpringConfig(SpringApplication springApplication)
174: throws ConfigurationSetupException {
175: if (springApplication != null) {
176: SpringApps[] springApps = springApplication
177: .getJeeApplicationArray();
178: for (int i = 0; springApps != null && i < springApps.length; i++) {
179: SpringApps springApp = springApps[i];
180: if (springApp != null) {
181: loadSpringApp(springApp);
182: }
183: }
184: }
185: }
186:
187: private void loadSpringApp(SpringApps springApp)
188: throws ConfigurationSetupException {
189: // TODO scope the following by app namespace https://jira.terracotta.lan/jira/browse/LKC-2284
190: loadLocks(springApp.getLocks());
191: loadTransientFields(springApp.getTransientFields());
192: loadInstrumentedClasses(springApp.getInstrumentedClasses());
193:
194: if (springApp.getSessionSupport()) {
195: config.addApplicationName(springApp.getName()); // enable session support
196: }
197:
198: if (springApp.getApplicationContexts() != null) {
199: loadSpringAppContexts(springApp);
200: }
201: }
202:
203: private void loadSpringAppContexts(SpringApps springApp) {
204: String appName = springApp.getName();
205: boolean fastProxy = springApp.getFastProxy();
206: SpringAppContext[] applicationContexts = springApp
207: .getApplicationContexts().getApplicationContextArray();
208: for (int i = 0; applicationContexts != null
209: && i < applicationContexts.length; i++) {
210: SpringAppContext appContext = applicationContexts[i];
211: if (appContext == null)
212: continue;
213:
214: DSOSpringConfigHelper springConfigHelper = new StandardDSOSpringConfigHelper();
215: springConfigHelper.addApplicationNamePattern(appName);
216: springConfigHelper.setFastProxyEnabled(fastProxy); // copy flag to all subcontexts
217: springConfigHelper.setRootName(appContext.getRootName());
218: springConfigHelper.setLocationInfoEnabled(appContext
219: .getEnableLocationInfo());
220:
221: SpringDistributedEvent distributedEventList = appContext
222: .getDistributedEvents();
223: if (distributedEventList != null) {
224: String[] distributedEvents = distributedEventList
225: .getDistributedEventArray();
226: for (int k = 0; distributedEvents != null
227: && k < distributedEvents.length; k++) {
228: springConfigHelper
229: .addDistributedEvent(distributedEvents[k]);
230: }
231: }
232:
233: SpringPath pathList = appContext.getPaths();
234: if (pathList != null) {
235: String[] paths = pathList.getPathArray();
236: for (int j = 0; paths != null && j < paths.length; j++) {
237: springConfigHelper.addConfigPattern(paths[j]);
238: }
239: }
240:
241: SpringBean springBean = appContext.getBeans();
242: if (springBean != null) {
243: NonDistributedFields[] nonDistributedFields = springBean
244: .getBeanArray();
245: for (int j = 0; nonDistributedFields != null
246: && j < nonDistributedFields.length; j++) {
247: NonDistributedFields nonDistributedField = nonDistributedFields[j];
248:
249: String beanName = nonDistributedField.getName();
250: springConfigHelper.addBean(beanName);
251:
252: String[] fields = nonDistributedField
253: .getNonDistributedFieldArray();
254: for (int k = 0; fields != null && k < fields.length; k++) {
255: springConfigHelper.excludeField(beanName,
256: fields[k]);
257: }
258: }
259: }
260:
261: config.addDSOSpringConfig(springConfigHelper);
262: }
263: }
264:
265: private ConfigLockLevel getLockLevel(LockLevel.Enum lockLevel,
266: boolean autoSynchronized) {
267: if (lockLevel == null || LockLevel.WRITE.equals(lockLevel)) {
268: return autoSynchronized ? ConfigLockLevel.AUTO_SYNCHRONIZED_WRITE
269: : ConfigLockLevel.WRITE;
270: } else if (LockLevel.CONCURRENT.equals(lockLevel)) {
271: return autoSynchronized ? ConfigLockLevel.AUTO_SYNCHRONIZED_CONCURRENT
272: : ConfigLockLevel.CONCURRENT;
273: } else if (LockLevel.READ.equals(lockLevel)) {
274: return autoSynchronized ? ConfigLockLevel.AUTO_SYNCHRONIZED_READ
275: : ConfigLockLevel.READ;
276: } else if (LockLevel.SYNCHRONOUS_WRITE.equals(lockLevel)) {
277: return autoSynchronized ? ConfigLockLevel.AUTO_SYNCHRONIZED_SYNCHRONOUS_WRITE
278: : ConfigLockLevel.SYNCHRONOUS_WRITE;
279: }
280: throw Assert.failure("Unknown lock level " + lockLevel);
281: }
282:
283: private void loadLocks(Locks lockList) {
284: if (lockList == null)
285: return;
286:
287: Autolock[] autolocks = lockList.getAutolockArray();
288: for (int i = 0; autolocks != null && i < autolocks.length; i++) {
289: config.addAutolock(autolocks[i].getMethodExpression(),
290: getLockLevel(autolocks[i].getLockLevel(),
291: autolocks[i].getAutoSynchronized()));
292: }
293:
294: NamedLock[] namedLocks = lockList.getNamedLockArray();
295: for (int i = 0; namedLocks != null && i < namedLocks.length; i++) {
296: NamedLock namedLock = namedLocks[i];
297: LockDefinition lockDefinition = new LockDefinitionImpl(
298: namedLock.getLockName(), getLockLevel(namedLock
299: .getLockLevel(), false));
300: lockDefinition.commit();
301: config.addLock(namedLock.getMethodExpression(),
302: lockDefinition);
303: }
304: }
305:
306: private void loadTransientFields(TransientFields transientFieldsList)
307: throws ConfigurationSetupException {
308: if (transientFieldsList != null) {
309: String[] transientFields = transientFieldsList
310: .getFieldNameArray();
311: try {
312: for (int i = 0; transientFields != null
313: && i < transientFields.length; i++) {
314: ClassSpec spec = ClassUtils
315: .parseFullyQualifiedFieldName(transientFields[i]);
316: config.addTransient(spec
317: .getFullyQualifiedClassName(), spec
318: .getShortFieldName());
319: }
320: } catch (ParseException e) {
321: throw new ConfigurationSetupException(e
322: .getLocalizedMessage(), e);
323: }
324: }
325: }
326:
327: private void loadInstrumentedClasses(
328: InstrumentedClasses instrumentedClasses) {
329: if (instrumentedClasses != null) {
330: Include[] includes = instrumentedClasses.getIncludeArray();
331: for (int i = 0; includes != null && i < includes.length; i++) {
332: Include include = includes[i];
333: IncludeOnLoad includeOnLoad = new IncludeOnLoad();
334: OnLoad onLoad = include.getOnLoad();
335: if (onLoad != null) {
336: if (onLoad.getExecute() != null) {
337: includeOnLoad = new IncludeOnLoad(
338: IncludeOnLoad.EXECUTE, onLoad
339: .getExecute());
340: } else if (onLoad.getMethod() != null) {
341: includeOnLoad = new IncludeOnLoad(
342: IncludeOnLoad.METHOD, onLoad
343: .getMethod());
344: }
345: }
346: config
347: .addInstrumentationDescriptor(new IncludedInstrumentedClass(
348: include.getClassExpression(), include
349: .getHonorTransient(), false,
350: includeOnLoad));
351: }
352:
353: String[] excludeArray = instrumentedClasses
354: .getExcludeArray();
355: for (int i = 0; excludeArray != null
356: && i < excludeArray.length; i++) {
357: config
358: .addInstrumentationDescriptor(new ExcludedInstrumentedClass(
359: excludeArray[i]));
360: }
361: }
362: }
363:
364: private void loadDistributedMethods(
365: DistributedMethods distributedMethods) {
366: if (distributedMethods != null) {
367: MethodExpression[] methodExpressions = distributedMethods
368: .getMethodExpressionArray();
369: for (int i = 0; methodExpressions != null
370: && i < methodExpressions.length; i++) {
371: final MethodExpression me = methodExpressions[i];
372: final DistributedMethodSpec dms = new DistributedMethodSpec(
373: me.getStringValue(), me.getRunOnAllNodes());
374: config.addDistributedMethodCall(dms);
375: }
376: }
377: }
378:
379: }
|