KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > object > bytecode > hook > impl > DSOContextImpl


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

5 package com.tc.object.bytecode.hook.impl;
6
7 import org.apache.commons.io.CopyUtils;
8
9 import com.tc.aspectwerkz.transform.InstrumentationContext;
10 import com.tc.aspectwerkz.transform.WeavingStrategy;
11 import com.tc.config.schema.L2ConfigForL1.L2Data;
12 import com.tc.config.schema.setup.ConfigurationSetupException;
13 import com.tc.config.schema.setup.FatalIllegalConfigurationChangeHandler;
14 import com.tc.config.schema.setup.L1TVSConfigurationSetupManager;
15 import com.tc.config.schema.setup.StandardTVSConfigurationSetupManagerFactory;
16 import com.tc.logging.TCLogger;
17 import com.tc.logging.TCLogging;
18 import com.tc.object.bytecode.Manageable;
19 import com.tc.object.bytecode.Manager;
20 import com.tc.object.bytecode.ManagerImpl;
21 import com.tc.object.bytecode.hook.ClassLoaderPreProcessorImpl;
22 import com.tc.object.bytecode.hook.DSOContext;
23 import com.tc.object.config.DSOClientConfigHelper;
24 import com.tc.object.config.IncompleteBootJarException;
25 import com.tc.object.config.StandardDSOClientConfigHelper;
26 import com.tc.object.config.UnverifiedBootJarException;
27 import com.tc.object.loaders.ClassProvider;
28 import com.tc.object.logging.InstrumentationLoggerImpl;
29 import com.tc.plugins.ModulesLoader;
30 import com.tc.util.Assert;
31 import com.tc.util.TCTimeoutException;
32 import com.terracottatech.config.ConfigurationModel;
33
34 import java.io.ByteArrayOutputStream JavaDoc;
35 import java.io.IOException JavaDoc;
36 import java.io.InputStream JavaDoc;
37 import java.net.ConnectException JavaDoc;
38 import java.net.MalformedURLException JavaDoc;
39 import java.net.URL JavaDoc;
40 import java.net.UnknownHostException JavaDoc;
41 import java.util.Collection JavaDoc;
42 import java.util.HashMap JavaDoc;
43
44 public class DSOContextImpl implements DSOContext {
45
46   private static final TCLogger logger = TCLogging.getLogger(DSOContextImpl.class);
47
48   private static DSOClientConfigHelper staticConfigHelper;
49   private static PreparedComponentsFromL2Connection preparedComponentsFromL2Connection;
50
51   private final DSOClientConfigHelper configHelper;
52   private final Manager manager;
53   private final WeavingStrategy weavingStrategy;
54
55   /**
56    * Creates a "global" DSO Context. This context is appropriate only when there is only one DSO Context that applies to
57    * the entire VM
58    */

59   public static DSOContext createGlobalContext(ClassProvider globalProvider) throws ConfigurationSetupException {
60     DSOClientConfigHelper configHelper = getGlobalConfigHelper();
61     Manager manager = new ManagerImpl(configHelper, globalProvider, preparedComponentsFromL2Connection);
62     return new DSOContextImpl(configHelper, globalProvider, manager);
63   }
64
65   /**
66    * For tests
67    */

68   public static DSOContext createContext(DSOClientConfigHelper configHelper, ClassProvider classProvider, Manager manager) {
69     return new DSOContextImpl(configHelper, classProvider, manager);
70   }
71
72   public static boolean isDSOSessions(String JavaDoc appName) throws ConfigurationSetupException {
73     return getGlobalConfigHelper().isDSOSessions(appName);
74   }
75
76   private DSOContextImpl(DSOClientConfigHelper configHelper, ClassProvider classProvider, Manager manager) {
77     checkForProperlyInstrumentedBaseClasses();
78     if (configHelper == null) { throw new NullPointerException JavaDoc(); }
79
80     this.configHelper = configHelper;
81     this.manager = manager;
82     weavingStrategy = new DefaultWeavingStrategy(configHelper, new InstrumentationLoggerImpl(configHelper
83         .instrumentationLoggingOptions()));
84
85     ModulesLoader.initModules(configHelper, classProvider, false);
86     validateBootJar();
87   }
88
89   private void validateBootJar() {
90     try {
91       configHelper.verifyBootJarContents();
92     } catch (final UnverifiedBootJarException ubjex) {
93       final StringBuffer JavaDoc msg = new StringBuffer JavaDoc(ubjex.getMessage() + " ");
94       msg.append("Unable to verify the contents of the boot jar; ");
95       msg.append("Please check the client logs for more information.");
96       logger.error(ubjex);
97       throw new RuntimeException JavaDoc(msg.toString());
98     } catch (final IncompleteBootJarException ibjex) {
99       final StringBuffer JavaDoc msg = new StringBuffer JavaDoc(ibjex.getMessage() + " ");
100       msg.append("The DSO boot jar appears to be incomplete --- some pre-instrumented classes ");
101       msg.append("listed in your tc-config is not included in the boot jar file. This could ");
102       msg.append("happen if you've modified your DSO clients' tc-config file to specify additional ");
103       msg.append("classes for inclusion in the boot jar, but forgot to rebuild the boot jar. Or, you ");
104       msg.append("could be a using an older boot jar against a newer Terracotta client installation. ");
105       msg.append("Please check the client logs for the list of classes that were not found in your boot jar.");
106       logger.error(ibjex);
107       throw new RuntimeException JavaDoc(msg.toString());
108     }
109   }
110
111   private void checkForProperlyInstrumentedBaseClasses() {
112     if (!Manageable.class.isAssignableFrom(HashMap JavaDoc.class)) {
113       StringBuffer JavaDoc msg = new StringBuffer JavaDoc();
114       msg.append("The DSO boot jar is not prepended to your bootclasspath! ");
115       msg.append("Generate it using the make-boot-jar script ");
116       msg.append("and place the generated jar file in the bootclasspath ");
117       msg.append("(i.e. -Xbootclasspath/p:/path/to/terracotta/lib/dso-boot/dso-boot-xxx.jar)");
118       throw new RuntimeException JavaDoc(msg.toString());
119     }
120   }
121
122   public Manager getManager() {
123     return this.manager;
124   }
125
126   /**
127    * XXX::NOTE:: ClassLoader checks the returned byte array to see if the class is instrumented or not to maintain the
128    * offset.
129    *
130    * @return new byte array if the class is instrumented and same input byte array if not.
131    * @see ClassLoaderPreProcessorImpl
132    */

133   public byte[] preProcess(String JavaDoc name, byte[] data, int offset, int length, ClassLoader JavaDoc caller) {
134     InstrumentationContext context = new InstrumentationContext(name, data, caller);
135     weavingStrategy.transform(name, context);
136     return context.getCurrentBytecode();
137   }
138
139   public void postProcess(Class JavaDoc clazz, ClassLoader JavaDoc caller) {
140     // NOP
141
}
142
143   // Needed by Spring
144
public void addTransient(String JavaDoc className, String JavaDoc fieldName) {
145     this.configHelper.addTransient(className, fieldName);
146   }
147
148   // Needed by Spring
149
public void addInclude(String JavaDoc expression, boolean callConstructorOnLoad, String JavaDoc lockExpression) {
150     this.configHelper.addIncludeAndLockIfRequired(expression, true, callConstructorOnLoad, false, lockExpression);
151   }
152
153   // Needed by Spring
154
public Collection JavaDoc getDSOSpringConfigHelpers() {
155     return this.configHelper.getDSOSpringConfigs();
156   }
157
158   private synchronized static DSOClientConfigHelper getGlobalConfigHelper() throws ConfigurationSetupException {
159     if (staticConfigHelper == null) {
160       StandardTVSConfigurationSetupManagerFactory factory = new StandardTVSConfigurationSetupManagerFactory(
161                                                                                                             false,
162                                                                                                             new FatalIllegalConfigurationChangeHandler());
163
164       logger.debug("Created StandardTVSConfigurationSetupManagerFactory.");
165       L1TVSConfigurationSetupManager config = factory.createL1TVSConfigurationSetupManager();
166       config.setupLogging();
167       logger.debug("Created L1TVSConfigurationSetupManager.");
168
169       try {
170         preparedComponentsFromL2Connection = validateMakeL2Connection(config);
171       } catch (Exception JavaDoc e) {
172         throw new ConfigurationSetupException(e.getLocalizedMessage(), e);
173       }
174       staticConfigHelper = new StandardDSOClientConfigHelper(config);
175     }
176
177     return staticConfigHelper;
178   }
179
180   private static PreparedComponentsFromL2Connection validateMakeL2Connection(L1TVSConfigurationSetupManager config)
181       throws UnknownHostException JavaDoc, IOException JavaDoc, TCTimeoutException {
182     L2Data[] l2Data = (L2Data[]) config.l2Config().l2Data().getObjects();
183     Assert.assertNotNull(l2Data);
184
185     String JavaDoc serverHost = l2Data[0].host();
186
187     if (false && !config.loadedFromTrustedSource()) {
188       String JavaDoc serverConfigMode = getServerConfigMode(serverHost, l2Data[0].dsoPort());
189
190       if (serverConfigMode != null && serverConfigMode.equals(ConfigurationModel.PRODUCTION)) {
191         String JavaDoc text = "Configuration constraint violation: "
192                       + "untrusted client configuration not allowed against production server";
193         throw new AssertionError JavaDoc(text);
194       }
195     }
196
197     return new PreparedComponentsFromL2Connection(config);
198   }
199
200   private static final long MAX_HTTP_FETCH_TIME = 30 * 1000; // 30 seconds
201
private static final long HTTP_FETCH_RETRY_INTERVAL = 1 * 1000; // 1 second
202

203   private static String JavaDoc getServerConfigMode(String JavaDoc serverHost, int httpPort) throws MalformedURLException JavaDoc,
204       TCTimeoutException, IOException JavaDoc {
205     URL JavaDoc theURL = new URL JavaDoc("http", serverHost, httpPort, "/config?query=mode");
206     long startTime = System.currentTimeMillis();
207     long lastTrial = 0;
208
209     while (System.currentTimeMillis() < (startTime + MAX_HTTP_FETCH_TIME)) {
210       try {
211         long untilNextTrial = HTTP_FETCH_RETRY_INTERVAL - (System.currentTimeMillis() - lastTrial);
212
213         if (untilNextTrial > 0) {
214           try {
215             Thread.sleep(untilNextTrial);
216           } catch (InterruptedException JavaDoc ie) {
217             // whatever; just try again now
218
}
219         }
220
221         logger.debug("Opening connection to: " + theURL + " to fetch server configuration.");
222
223         lastTrial = System.currentTimeMillis();
224         InputStream JavaDoc in = theURL.openStream();
225         logger.debug("Got input stream to: " + theURL);
226         ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
227
228         CopyUtils.copy(in, baos);
229
230         return baos.toString();
231       } catch (ConnectException JavaDoc ce) {
232         logger.warn("Unable to fetch configuration mode from L2 at '" + theURL + "'; trying again. "
233                     + "(Is an L2 running at that address?): " + ce.getLocalizedMessage());
234         // oops -- try again
235
}
236     }
237
238     throw new TCTimeoutException("We tried for " + (int) ((System.currentTimeMillis() - startTime) / 1000)
239                                  + " seconds, but couldn't fetch system configuration mode from the L2 " + "at '"
240                                  + theURL + "'. Is the L2 running?");
241   }
242
243   public int getSessionLockType(String JavaDoc appName) {
244     return configHelper.getSessionLockType(appName);
245   }
246 }
247
Popular Tags