001: /*
002: * BEGIN_HEADER - DO NOT EDIT
003: *
004: * The contents of this file are subject to the terms
005: * of the Common Development and Distribution License
006: * (the "License"). You may not use this file except
007: * in compliance with the License.
008: *
009: * You can obtain a copy of the license at
010: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
011: * See the License for the specific language governing
012: * permissions and limitations under the License.
013: *
014: * When distributing Covered Code, include this CDDL
015: * HEADER in each file and include the License file at
016: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
017: * If applicable add the following below this CDDL HEADER,
018: * with the fields enclosed by brackets "[]" replaced with
019: * your own identifying information: Portions Copyright
020: * [year] [name of copyright owner]
021: */
022:
023: /*
024: * @(#)WebSphereJBIBootstrap.java
025: * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
026: *
027: * END_HEADER - DO NOT EDIT
028: */
029: package com.sun.jbi.framework.websphere;
030:
031: import java.io.File;
032: import java.lang.reflect.Constructor;
033: import java.lang.reflect.Method;
034: import java.net.URL;
035: import java.net.URLClassLoader;
036: import java.util.ArrayList;
037: import java.util.List;
038: import java.util.MissingResourceException;
039: import java.util.Properties;
040: import java.util.ResourceBundle;
041: import java.util.logging.Logger;
042:
043: import javax.management.MBeanServerConnection;
044: import javax.management.ObjectName;
045: import javax.management.remote.JMXConnector;
046: import javax.management.remote.JMXConnectorFactory;
047: import javax.management.remote.JMXServiceURL;
048:
049: /**
050: * Provides support for running JBI in WebSphere
051: *
052: * @author Sun Microsystems, Inc.
053: */
054: public class WebSphereJBIBootstrap
055:
056: {
057: /** JSR208 interfaces. */
058: private static final String JBI_JAR_NAME = "jbi.jar";
059:
060: /** JBI runtime interfaces exposed to components. */
061: private static final String JBI_EXT_JAR_NAME = "jbi-ext.jar";
062:
063: /** Name of the top-level class of the JBI runtime framework. */
064: private static final String JBI_FRAMEWORK_CLASS_NAME = "com.sun.jbi.framework.websphere.WebSphereJBIFramework";
065:
066: /** Environment property used to override install root location. */
067: private static final String INSTALL_ROOT = "install.root";
068:
069: /** Environment property used for instance name. */
070: public static final String INSTANCE_NAME = "instance.name";
071:
072: /** Default instance name. */
073: private static final String DEFAULT_INSTANCE_NAME = "server";
074:
075: /** List of jars that should not be included in the runtime classloader. */
076: private List<String> mBlacklistJars = new ArrayList<String>();
077:
078: /** ClassLoader used for JBI runtime classes. These classes are not
079: * part of the component classloader hierarchy.
080: */
081: private ClassLoader mFrameworkClassLoader;
082:
083: /** JBI installation directory. */
084: private File mJbiInstallDir;
085:
086: /** JBI Framework implementation */
087: private Object mJbiFramework;
088:
089: /** Environment properties */
090: private Properties mEnvironment;
091:
092: /** logger for this bootstrap class */
093: private static Logger logger;
094:
095: /** flag to track if the bootstrap has been called before */
096: public static boolean mStarted = false;
097:
098: /** this resource bundle loads messages used in log*/
099: private static ResourceBundle resourceBundle;
100:
101: /**
102: * Loads the JBI Bootstrap in WebSphere.
103: * @param properties the properties from the servlet context
104: */
105: public static void start(Properties properties) {
106: WebSphereJBIBootstrap jbiBootstrap = new WebSphereJBIBootstrap(
107: properties);
108: try {
109: initResourceBundle();
110: jbiBootstrap.createJBIFramework();
111: jbiBootstrap.loadJBIFramework();
112: logger
113: .info(getString(LocalStringKeys.WEBSPHERE_JBI_FRAMEWORK_LOAD_SUCCESS));
114: mStarted = true;
115: } catch (Exception ex) {
116: logger.severe(ex.getMessage());
117: }
118: }
119:
120: /**
121: * This method is used to find out if JBIBoostrap has been started
122: * @return boolean true if JBIBoostrap is started
123: */
124: public static boolean isStarted() {
125: return mStarted;
126: }
127:
128: /**
129: * This method is used to stop the JBIBootstrap
130: * @param properties tht properties from servlet context
131: */
132: public static void stop(Properties properties) {
133: WebSphereJBIBootstrap jbiBootstrap = new WebSphereJBIBootstrap(
134: properties);
135:
136: try {
137: jbiBootstrap.createJBIFramework();
138: jbiBootstrap.unloadJBIFramework();
139: } catch (Exception ex) {
140: logger.severe(ex.getMessage());
141: }
142: }
143:
144: /**
145: * Create a new WebSphereJBIBootstrap instance with the specified environment.
146: * @param env environment properties
147: */
148: public WebSphereJBIBootstrap(Properties env) {
149: mEnvironment = env;
150:
151: // setup blacklist jars
152: mBlacklistJars.add(JBI_JAR_NAME);
153: mBlacklistJars.add(JBI_EXT_JAR_NAME);
154:
155: // If install root is not set, default to current working directory
156: String installPath = mEnvironment.getProperty(INSTALL_ROOT);
157: if (installPath == null) {
158: File installDir = new File(System.getProperty("user.dir"));
159: // account for javaw launch from a double-click on the jar
160: if (installDir.getName().equals("lib")) {
161: installDir = installDir.getParentFile();
162: }
163:
164: installPath = installDir.getAbsolutePath();
165: }
166:
167: mJbiInstallDir = new File(installPath);
168:
169: // quick sanity check on the install root
170: if (!mJbiInstallDir.isDirectory()
171: || !new File(mJbiInstallDir, "runtime/jbi_rt.jar")
172: .exists()) {
173: throw new RuntimeException(
174: getString(LocalStringKeys.WEBSPHERE_JBI_FRAMEWORK_INVALID_INSTALL_ROOT)
175: + mJbiInstallDir.getAbsolutePath());
176: }
177:
178: // pass this information along to the core framework
179: mEnvironment.setProperty(INSTALL_ROOT, mJbiInstallDir
180: .getAbsolutePath());
181:
182: logger = Logger.getLogger(this .getClass().getPackage()
183: .getName());
184: }
185:
186: /**
187: * Loads the JBI framework using the Java SE platform wrapper. If the
188: * framework loads successfully, this method adds a shutdown hook to
189: * allow for civilized clean-up when the VM terminates.
190: */
191: void loadJBIFramework() {
192: try {
193: invoke(mJbiFramework, "load");
194: } catch (Throwable t) {
195: logger
196: .severe(getString(LocalStringKeys.WEBSPHERE_JBI_FRAMEWORK_LOAD_FAILED));
197: logger.severe(t.toString());
198: }
199: }
200:
201: /**
202: * Unloads the JBI framework using the Java SE platform wrapper. This is
203: * always a remote call, since the framework has (presumably) been loaded
204: * previously by another process.
205: */
206: void unloadJBIFramework() {
207: String errMsg = null;
208: JMXServiceURL serviceURL;
209: int jmxConnectorPort;
210:
211: try {
212: MBeanServerConnection mbsConn = (MBeanServerConnection) invoke(
213: mJbiFramework, "getMBeanServerConnection");
214: ObjectName fwMBeanName = new ObjectName("com.sun.jbi",
215: "instance", mEnvironment.getProperty(INSTANCE_NAME,
216: DEFAULT_INSTANCE_NAME));
217: mbsConn.invoke(fwMBeanName, "unload", new Object[0],
218: new String[0]);
219: mbsConn.unregisterMBean(fwMBeanName);
220:
221: } catch (javax.management.MBeanException mbEx) {
222: errMsg = mbEx.getTargetException().toString();
223: } catch (Throwable t) {
224: errMsg = t.toString();
225: }
226:
227: if (errMsg != null) {
228: logger
229: .severe(getString(LocalStringKeys.WEBSPHERE_JBI_FRAMEWORK_UNLOAD_FAILED));
230: logger.severe(errMsg);
231: } else {
232: logger
233: .info(getString(LocalStringKeys.WEBSPHERE_JBI_FRAMEWORK_UNLOAD_SUCCESS));
234: }
235: }
236:
237: /**
238: * Creates the JBI framework using the appropriate classloading structure.
239: */
240: private void createJBIFramework() throws Exception {
241: Class fwClass;
242: Constructor fwCtor;
243:
244: try {
245: createFrameworkClassLoader();
246: fwClass = mFrameworkClassLoader
247: .loadClass(JBI_FRAMEWORK_CLASS_NAME);
248: fwCtor = fwClass.getDeclaredConstructor(Properties.class);
249: mJbiFramework = fwCtor.newInstance(mEnvironment);
250: } catch (Exception ex) {
251: logger.severe(ex.getMessage());
252: throw new Exception(
253: getString(LocalStringKeys.WEBSPHERE_JBI_FRAMEWORK_CREATE_FAILED));
254:
255: }
256: }
257:
258: /**
259: * Creates a separate runtime classloader to avoid namespace pollution
260: * between the component classloading hierarchy and the JBI implementation.
261: * At present, this method is greedy and includes any file in the lib/
262: * directory in the runtime classpath.
263: */
264: private void createFrameworkClassLoader() {
265: ArrayList<URL> cpList = new ArrayList<URL>();
266: URL[] cpURLs = new URL[0];
267: File libDir = new File(mJbiInstallDir, "runtime");
268:
269: // Everything in the lib directory goes into the classpath
270: for (File lib : libDir.listFiles()) {
271: try {
272: if (mBlacklistJars.contains(lib.getName())) {
273: // skip blacklisted jars
274: continue;
275: }
276:
277: cpList.add(lib.toURL());
278: } catch (java.net.MalformedURLException urlEx) {
279: logger
280: .warning(getString(LocalStringKeys.WEBSPHERE_JBI_FRAMEWORK_BAD_URL_IN_FRAMEWORK_CLASSPATH));
281: logger.warning(urlEx.getMessage());
282: }
283: }
284:
285: cpURLs = cpList.toArray(cpURLs);
286: mFrameworkClassLoader = new URLClassLoader(cpURLs, getClass()
287: .getClassLoader());
288: }
289:
290: /**
291: * This method is used to invoke a given method in a given object using
292: * reflection. This bootstrap class uses this method to invoke the load
293: * method on the framework.
294: * @param obj the object in which the method is to be invoked
295: * @param method the method name
296: * @param params the list of parameteres needed by the method to be invoked
297: */
298: private Object invoke(Object obj, String method, Object... params)
299: throws Throwable {
300: Object result = null;
301:
302: try {
303: for (Method m : obj.getClass().getDeclaredMethods()) {
304: if (m.getName().equals(method)) {
305: result = m.invoke(obj, params);
306: break;
307: }
308: }
309:
310: return result;
311: } catch (java.lang.reflect.InvocationTargetException itEx) {
312: throw itEx.getTargetException();
313: }
314: }
315:
316: /**
317: * This method is used to initialize the resource bundle that is used
318: * to load messages used in log
319: */
320: private static void initResourceBundle() {
321: try {
322: resourceBundle = ResourceBundle
323: .getBundle("com.sun.jbi.framework.websphere.LocalStrings");
324: } catch (MissingResourceException missingException) {
325: logger.warning("Resource bundle could not be loaded "
326: + missingException.getMessage());
327: }
328: }
329:
330: /**
331: * This method is used to get a value of the given key from a resource bundle
332: * If the resource bundle is not available this method returns the key itself
333: * @param key the key
334: * @returns String the value in the bundle for the given key
335: */
336: private static String getString(String key) {
337: if (resourceBundle != null) {
338: return resourceBundle.getString(key);
339: } else {
340: return key;
341: }
342: }
343: }
|