Java tutorial
/* * Copyright 2014 Kurt Faulknerloser * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.bbsync.webservice.client.proxytool; import java.io.IOException; import java.io.Serializable; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.rmi.RemoteException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import org.apache.axis2.AxisFault; import org.apache.axis2.Constants; import org.apache.axis2.client.Options; import org.apache.axis2.client.ServiceClient; import org.apache.axis2.client.Stub; import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.context.ConfigurationContextFactory; import org.apache.axis2.transport.http.HTTPConstants; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; import org.apache.log4j.Logger; import org.apache.rampart.handler.WSSHandlerConstants; import org.apache.rampart.handler.config.OutflowConfiguration; import org.apache.ws.security.WSPasswordCallback; import org.apache.ws.security.handler.WSHandlerConstants; import org.bbsync.webservice.client.ClientWebService; import org.bbsync.webservice.client.generated.ContextWSStub; import org.bbsync.webservice.client.generated.ContextWSStub.CourseIdVO; import org.bbsync.webservice.client.generated.ContextWSStub.DeactivateTool; import org.bbsync.webservice.client.generated.ContextWSStub.DeactivateToolResponse; import org.bbsync.webservice.client.generated.ContextWSStub.DeactivateToolResultVO; import org.bbsync.webservice.client.generated.ContextWSStub.EmulateUser; import org.bbsync.webservice.client.generated.ContextWSStub.EmulateUserResponse; import org.bbsync.webservice.client.generated.ContextWSStub.ExtendSessionLife; import org.bbsync.webservice.client.generated.ContextWSStub.ExtendSessionLifeResponse; import org.bbsync.webservice.client.generated.ContextWSStub.GetMemberships; import org.bbsync.webservice.client.generated.ContextWSStub.GetMembershipsResponse; import org.bbsync.webservice.client.generated.ContextWSStub.GetMyMembershipsResponse; import org.bbsync.webservice.client.generated.ContextWSStub.GetRequiredEntitlements; import org.bbsync.webservice.client.generated.ContextWSStub.GetRequiredEntitlementsResponse; import org.bbsync.webservice.client.generated.ContextWSStub.GetServerVersion; import org.bbsync.webservice.client.generated.ContextWSStub.GetServerVersionResponse; import org.bbsync.webservice.client.generated.ContextWSStub.GetSystemInstallationIdResponse; import org.bbsync.webservice.client.generated.ContextWSStub.InitializeResponse; import org.bbsync.webservice.client.generated.ContextWSStub.InitializeVersion2Response; import org.bbsync.webservice.client.generated.ContextWSStub.Login; import org.bbsync.webservice.client.generated.ContextWSStub.LoginResponse; import org.bbsync.webservice.client.generated.ContextWSStub.LoginTicket; import org.bbsync.webservice.client.generated.ContextWSStub.LoginTicketResponse; import org.bbsync.webservice.client.generated.ContextWSStub.LoginTool; import org.bbsync.webservice.client.generated.ContextWSStub.LoginToolResponse; import org.bbsync.webservice.client.generated.ContextWSStub.LogoutResponse; import org.bbsync.webservice.client.generated.ContextWSStub.RegisterTool; import org.bbsync.webservice.client.generated.ContextWSStub.RegisterToolResponse; import org.bbsync.webservice.client.generated.ContextWSStub.RegisterToolResultVO; import org.bbsync.webservice.client.generated.ContextWSStub.VersionVO; /** * A Blackboard Context provides the initial methods required for session * creation and is therefore required to be used before any other Web Services * can be utilized. The basic usage for a user session is as follows: * * //setup UserToken WS-Security header with userid="session", password="nosession", type="PasswordText" * String sessionId = initialize(); * * // change your UserToken.password to be sessionId and make sure it is passed on all subsequent requests * login("user", "password", "clientvendor", "clientapp", null, 3600); * ... * logout(); // This will invalidate your session. * * But there are other ways to login as well (loginTool and loginTicket). In * addition to having to login to get an authenticated session, you also have * to be aware of session lifetime. When logging in you can declare how long * you expect to need this session (up to a max of 24 hours). After that time * period your session will no longer work. You can use extendSessionLife to * extend the life of your session at any time so it is possible to have a * long-running client application using the same session, but you must * explicitly keep extending the session life. Note that all login methods * require a vendor and program identifier. Leading and trailing spaces will be * trimmed and they are case-insensitive. */ @SuppressWarnings("deprecation") public abstract class ContextProxyTool extends AbstractProxyTool implements ClientWebService, Serializable { private static final long serialVersionUID = 1111000000000000L; private static final String CLIENT_PROGRAM_ID = "ContextProxyTool"; private static final Logger logger = Logger.getLogger(ContextProxyTool.class.getName()); private transient ContextWSStub contextWS = null; private static String proxy_tool_password = null; private static String context_ws_url = null; protected static String client_vendor_id = null; protected static Long default_timeout_seconds = null; private static Long server_version = null; private ContextProxyTool.PasswordCallbackClass pwcb = null; private HttpClient _httpClient = null; private ConfigurationContext ctx = null; private static String modulePath = null; private static String session_id = null; private static String blackboardServerURL = null; /////////////////////////////////////////////////////////////////////////// // Constructor ////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// protected ContextProxyTool() { if (context_ws_url == null) { context_ws_url = config.getConfigClass("ContextProxyTool", "webServiceURL"); } if (default_timeout_seconds == null) { String long_str = config.getConfigClass("GLOBAL", "sessionTimeOutSeconds"); default_timeout_seconds = new Long(long_str); } if (client_vendor_id == null) { client_vendor_id = config.getConfigClass("GLOBAL", "clientVendorId"); } if (proxy_tool_password == null) { proxy_tool_password = config.getConfigClass(CLIENT_PROGRAM_ID, "sharedSecret"); } if (blackboardServerURL == null) { blackboardServerURL = config.getConfigClass("GLOBAL", "blackboardServerURL"); } if (modulePath == null) { modulePath = config.getConfigClass("GLOBAL", "modulePath"); } } /////////////////////////////////////////////////////////////////////////// // All ContextWS Methods //////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /** * Deactivates the proxy tool associated with the current session. The * caller must be logged in as the tool that it wishes to deactivate. The * status field of the returned object will be true if the deactivation * succeeds, and false otherwise. In case of failure, consult the * failureError field for the reasons why. * * Because you must be logged in as the tool to be deactivated in order to * use this method, be sure that the tool has been configured to use the * tool method "Context.WS:deactivateTool" in conf.xml. * * @param ignore - Currently unused * @return Returns the results of deactivation (true, false or error code). */ protected DeactivateToolResultVO deactivateTool(String ignore) { DeactivateToolResponse response = null; DeactivateTool deactivate = new DeactivateTool(); deactivate.setIgnore(ignore); //Don't setupSession() or initializeSession(). //To use this method, your session should already be active. try { response = contextWS.deactivateTool(deactivate); } catch (RemoteException e) { logger.error("Encountered a remote exception while trying to Deactivate Tool"); logger.error(e.getMessage()); return null; } //don't cleanupSession() here. Do it at logout(). if (response == null) { logger.warn("deactivateTool returned null."); return null; } return response.get_return(); } /** * emulateUser can be used to switch the 'current' user for your Web * Service session to someone else. Once you have emulated a user you will * lose all your current entitlements (including tool based entitlements if * you logged in as a 'tool'). To regain those tool entitlements you either * have to logout/initialize/logintool again or * * session = emulateUser(session,null); * * (If you were originally logged in as a user with this entitlement (i.e. * 'administrator') then you cannot emulate a null user - null is only valid * if originally logged in as a tool. * * If you use emulate user with tool login, be sure to grant the following * entitlement: webservices.tools.EMULATE. This can be done by adding * "Context.WS:emulateUser" to the list of entitlements for the particular * tool in conf.xml. You'll then have to re-register the tool for the * entitlement to take effect. * * When emulating a user, make sure that the emulated user has the correct * System privileges to perform the task. This means that the user should * have a system role assigned that is not "None", "Guest", or "User". * System privileges can be assigned to System roles by using the Admin GUI. * * @param user_to_emulate - username/login id of the user you wish to * become. Null will 'unemulate' any user. * @return Returns true if successful. Otherwise returns false. */ protected boolean emulateUser(String user_to_emulate) { EmulateUserResponse response = null; EmulateUser emulate_user = new EmulateUser(); emulate_user.setUserToEmulate(user_to_emulate); //Don't setupSession() or initializeSession(). //To use this method, your session should already be active. try { response = contextWS.emulateUser(emulate_user); } catch (RemoteException e) { logger.error("Encountered a remote exception while trying to Emulate User"); logger.error(e.getMessage()); return false; } //don't cleanupSession() here. Do it at logout(). if (response == null) { logger.warn("emulateUser returned null."); return false; } return response.get_return(); } /** * Call this to extend the life of your Web Service session. Note that you * cannot set a session to be live for more than 24 hours from the current * time. * * @param additional_seconds - the number of additional seconds you want to * add to the life of your session. * @return Returns true if successful. Otherwise returns false. */ protected boolean extendSessionLife(Long additional_seconds) { ExtendSessionLifeResponse response = null; ExtendSessionLife extend = new ExtendSessionLife(); extend.setAdditionalSeconds(additional_seconds); //Don't setupSession() or initializeSession(). //To use this method, your session should already be active. try { response = contextWS.extendSessionLife(extend); } catch (RemoteException e) { logger.error("Encountered a remote exception while trying to Extend SessionLife"); logger.error(e.getMessage()); return false; } //Don't cleanupSession() here. Do it at logout(). if (response == null) { logger.warn("extendSessionLife returned null."); return false; } return response.get_return(); } /** * If session is a user then return the courses they are enrolled in. * If session is a tool then return an empty set. * * @return Returns an array of courseidvo's representing the currently * logged-in user's memberships. */ protected CourseIdVO[] getMyMemberships() { GetMyMembershipsResponse response = null; //Don't setupSession() or initializeSession(). //To use this method, your session should already be active. try { response = contextWS.getMyMemberships(); } catch (RemoteException e) { logger.error("Encountered a remote exception while trying to Get My Memberships"); logger.error(e.getMessage()); return null; } //don't cleanupSession() here. Do it at logout(). if (response == null) { logger.warn("getMyMemberships returned null."); return null; } return response.get_return(); } /** * If session is a user and userid==session.userid then return the courses * they are enrolled in. * If session is a user and userid!=session.userid then return an empty * set. * If session is a tool then return the courses the given user is enrolled * in. * * Entitlement Required: webservices.tools.getMemberships.VIEW * * @param user_id - the user you wish to get memberships for * @return Returns an array of courseidvo's representing the user's * memberships. */ protected CourseIdVO[] getMemberships(String user_id) { GetMembershipsResponse response = null; GetMemberships memberships = new GetMemberships(); memberships.setUserid(user_id); //Don't setupSession() or initializeSession(). //To use this method, your session should already be active. try { response = contextWS.getMemberships(memberships); } catch (RemoteException e) { logger.error("Encountered a remote exception while trying to Get Memberships"); logger.error(e.getMessage()); return null; } //don't cleanupSession() here. Do it at logout(). if (response == null) { logger.warn("getMemberships returned null."); return null; } return response.get_return(); } /** * This will return a list of the entitlements the specified method * requires for successful completion. Typical use of this method is during * client application installation to build up the arguments required when * calling registerTool. * * @param method - the name of a method on this Web Service that you plan * to call while using tool based authentication. * @return Returns a String[] array of entitlement UIDs. */ protected String[] getRequiredEntitlements(String method) { GetRequiredEntitlementsResponse response = null; GetRequiredEntitlements gre = new GetRequiredEntitlements(); gre.setMethod(method); setupSession(); try { response = contextWS.getRequiredEntitlements(gre); } catch (RemoteException e) { logger.error("Encountered a remote exception while trying to Get Required Entitlements"); logger.error(e.getMessage()); return null; } cleanupSession(); if (response == null) { logger.warn("getRequiredEntitlements returned null."); return null; } return response.get_return(); } /** * Returns the current version of this web service on the server. In the * future this can be used to adjust client behavior to match the * capabilities of the server you are talking to. * * @param unused - this is an optional parameter put here to make the * generation of .net client applications from the wsdl * 'cleaner' (0-argument methods do not generate clean * stubs and are much harder to have the same method name * across multiple Web Services in the same .net client) * @return Returns a VersionVO representing the current version of this web * service on the server. */ protected VersionVO getServerVersion(VersionVO unused) { setupSession(); VersionVO response = _getServerVersion(unused); cleanupSession(); return response; } private VersionVO _getServerVersion(VersionVO unused) { GetServerVersionResponse response = null; GetServerVersion version = new GetServerVersion(); version.setUnused(unused); //Don't setupSession() or initializeSession(). //To use this method, your session should already be active. try { response = contextWS.getServerVersion(version); } catch (RemoteException e) { logger.error("Encountered a remote exception while trying to Get Server Version"); logger.error(e.getMessage()); return null; } //don't cleanupSession() here. Do it at logout(). if (response == null) { logger.warn("getServerVersion returned null."); return null; } return response.get_return(); } /** * Each installation of Academic Suite has a unique 32-character identifier * associated with it. You can use this method to retrieve this value for * the target server. * * @return Returns a 32 character String of hex digits. */ protected String getSystemInstallationId() { GetSystemInstallationIdResponse response = null; setupSession(); try { response = contextWS.getSystemInstallationId(); } catch (RemoteException e) { logger.error("Encountered a remote exception while trying to Get System Installation ID"); logger.error(e.getMessage()); return null; } cleanupSession(); if (response == null) { logger.warn("getSystemInstallationId returned null."); return null; } return response.get_return(); } /** * Sets the client version to version 1 and returns an appropriate session. * One of initialize or initializeVersion2 must be called prior to logging * in so that the server knows what version of the web service the client * was developed against and can adjust behavior to match the expected * behavior from the client. NOTE that this session is only valid for 5 * minutes - in other words you must login within 5 minutes or call * initialize again. According to the Blackboard web services API, with * each release of this web service, a new initializeVersionXXX method will * be implemented. * * Setting the GLOBAL "serverVersion" parameter in conf.xml to "1" will * make this the default initialization method. If serverVersion is not * set, or is set to a value other than "1" or "2", the server version will * be determined automatically. * * @return Returns a a 32 character String of hex digits representing the * unique session ID. This ID will be passed in all subsequent * requests as the session password. */ protected String initialize() { setupSession(); String response = _initialize(); cleanupSession(); return response; } private String _initialize() { InitializeResponse response = null; //Don't setupSession() or initializeSession(). //To use this method, your session should already be active. try { response = contextWS.initialize(); } catch (RemoteException e) { logger.error("Encountered a remote exception while trying to Initialize"); logger.error(e.getMessage()); return null; } //don't cleanupSession() here. Do it at logout(). if (response == null) { logger.warn("initialize returned null."); return null; } return response.get_return(); } /** * Sets the client version to version 2 and returns an appropriate session. * One of initialize or initializeVersion2 must be called prior to logging * in so that the server knows what version of the web service the client * was developed against and can adjust behavior to match the expected * behavior from the client. NOTE that this session is only valid for 5 * minutes - in other words you must login within 5 minutes or call * initializeVersion2 again. * * Setting the GLOBAL "serverVersion" parameter in conf.xml to "2" will * make this the default initialization method. If serverVersion is not * set, or is set to a value other than "1" or "2", the server version will * be determined automatically. * * @return Returns a 32 character String of hex digits representing the * unique session ID. This ID will be passed in all subsequent * requests as the session password. */ protected String initializeVersion2() { setupSession(); String response = _initializeVersion2(); cleanupSession(); return response; } private String _initializeVersion2() { InitializeVersion2Response response = null; //Don't setupSession() or initializeSession(). //To use this method, your session should already be active. try { response = contextWS.initializeVersion2(); } catch (RemoteException e) { logger.error("Encountered a remote exception while trying to Initialize Version2"); logger.error(e.getMessage()); return null; } //don't cleanupSession() here. Do it at logout(). if (response == null) { logger.warn("initializeVersion2 returned null."); return null; } return response.get_return(); } /** * Logs in user using the given password. ONLY works if the authentication * source is the internal AS database. * * @param user_name - The user name/login ID of the user, not the internal * Blackboard ID. * @param password - The password associated with the given user name. * @param client_vendor_id - the "clientVendorId" as defined in conf.xml * @param proxy_tool_name - the registered name of the proxy tool. See * <ClassConfig name=" ... "> in conf.xml * @param login_extra_info - not used at this time. * @param timeout_seconds - The number of seconds to keep this session * object valid - see "sessionTimeOutSeconds" in * conf.xml to configure the default timeout * value. You can call extendSessionLife() to * keep a session alive longer. * * @return If successful, establishes a user-authenticated session valid for * use in other calls and returns true. Otherwise returns false. */ protected boolean login(String user_name, String user_password, String client_vendor_id, String tool_name, String login_extra_info, Long timeout_seconds) { LoginResponse response = null; Login login = new Login(); login.setClientProgramId(tool_name); login.setClientVendorId(client_vendor_id); login.setExpectedLifeSeconds(timeout_seconds); login.setLoginExtraInfo(login_extra_info); login.setPassword(user_password); login.setUserid(user_name); setupSession(); initializeSession(); try { response = contextWS.login(login); } catch (RemoteException e) { logger.error("Encountered a remote exception while trying to Login"); logger.error(e.getMessage()); return false; } //don't cleanupSession() here. Do it at logout(). if (response == null) { logger.warn("login returned null."); return false; } return response.get_return(); } /** * Logs in a session based on the given ticket. The ticket will contain * information about the user it is authenticated for as well as timestamp * information. It is only valid for a short time after it is generated * (i.e. approximately 5 minutes) so you should be sure to use it * immediately to get a sessionid if you are unsure how long it will be in * your client application before you need the Web Service session. * * @param ticket - Ticket provided during proxy tool negotiation. * @param client_vendor_id - the "clientVendorId" as defined in conf.xml * @param proxy_tool_name - the registered name of the proxy tool. See * <ClassConfig name=" ... "> in conf.xml * @param login_extra_info - not used at this time. * @param timeout_seconds - The number of seconds to keep this session * object valid - see "sessionTimeOutSeconds" in * conf.xml to configure the default timeout * value. You can call extendSessionLife() to * keep a session alive longer. * * @return If successful, establishes an authenticated session valid for * use in other calls (either tool or user based - depends on * ticket) and returns true. Otherwise, returns false. */ protected boolean loginTicket(String ticket, String client_vendor_id, String proxy_tool_name, String login_extra_info, Long timeout_seconds) { LoginTicketResponse response = null; LoginTicket login = new LoginTicket(); login.setClientProgramId(proxy_tool_name); login.setClientVendorId(client_vendor_id); login.setExpectedLifeSeconds(timeout_seconds); login.setLoginExtraInfo(login_extra_info); login.setTicket(ticket); setupSession(); initializeSession(); try { response = contextWS.loginTicket(login); } catch (RemoteException e) { logger.error("Encountered a remote exception while trying to Login Ticket"); logger.error(e.getMessage()); return false; } //don't cleanupSession() here. Do it at logout(). if (response == null) { logger.warn("loginTicket returned null."); return false; } return response.get_return(); } /** * Login using tool-based authentication. * @param shared_secret - see the "sharedSecret" parameter as defined in * conf.xml for the specific proxy tool. * @param client_vendor_id - the "clientVendorId" as defined in conf.xml * @param proxy_tool_name - the registered name of the proxy tool. See * <ClassConfig name=" ... "> in conf.xml * @param login_extra_info - not used at this time. * @param timeout_seconds - The number of seconds to keep this session * object valid - see "sessionTimeOutSeconds" in * conf.xml to configure the default timeout * value. You can call extendSessionLife() to * keep a session alive longer. * * @return If successful, establishes a tool-authenticated session valid for * use in other calls and returns true. Otherwise, returns false. */ protected boolean loginTool(String shared_secret, String client_vendor_id, String tool_name, String login_extra_info, Long timeout_seconds) { LoginTool loginArgs = new LoginTool(); loginArgs.setPassword(shared_secret); loginArgs.setClientVendorId(client_vendor_id); loginArgs.setClientProgramId(tool_name); loginArgs.setLoginExtraInfo(login_extra_info); loginArgs.setExpectedLifeSeconds(timeout_seconds); LoginToolResponse response = null; setupSession(); initializeSession(); try { response = contextWS.loginTool(loginArgs); } catch (RemoteException e) { logger.error("Encountered a remote exception while trying to Login Tool"); logger.error(e.getMessage()); return false; } //don't cleanupSession() here. Do it at logout(). if (response == null) { logger.warn("loginTool returned null."); return false; } return response.get_return(); } /** * This method will destroy the current session rendering * it invalid for use in subsequent operations. * @return */ protected boolean logout() { LogoutResponse response = null; try { response = contextWS.logout(); } catch (RemoteException e) { logger.error("Encountered a remote exception while trying to Logout"); logger.error(e.getMessage()); return false; } cleanupSession(); if (response == null) { logger.warn("logout returned null."); return false; } return response.get_return(); } /** * Register your client program with the Academic Suite server. The list of * required methods is a list of "webservicename:operation" for each * operation you intend to call on each webservice. The requiredToolMethods * are those you call from a loginTool session while the methods in * requiredTicketMethods are those you call from a loginTicket session. You * do not have to declare requiredUserMethods because you will get whatever * entitlements the user has if you provide their password as part of the * login method. * After calling this registration method from your client program * installer, the Academic Suite administrator will have to login and make * the tool available before you can login as a tool (via loginTool) and * get the entitlements associated with the methods you requested. * * NOTE that this call will only succeed BEFORE a password is assigned to * your tool. Once a password is assigned you cannot re-register to change * your desired entitlements (by declaring a different set of methods being * used). If you are testing your tool and wish to change entitlements you * have to first clear the password in the UI, then call registerTool, then * set the password again. Be careful setting the initial password as there * are several sets of rules around this: * 1) If you register without a password and without placements (i.e no * tool-profile xml in the description) then your proxy tool is * 'available' by default, but you can only use the login(user/pw) * method. * 2) If you register with a password or with placements then your proxy * tool is either 'unavailable' (no placements) or 'inactive' (with * placements). You cannot login using any methods in this state. * 3) Once your tool is registered, you cannot call this method as long as * there is a password set on your tool unless you are being asked to * via the reregister proxy-tool callback operation. * 4) If you are calling this as part of the reregister operation, the * initialsharedsecret is ignored. * *@param client_vendor_id - Your vendor ID. You will use this same ID in * any login calls. *@param client_program_id - Your program ID (should be unique per client * program/Web Service agent you develop). You * will use this ID in any login calls. *@param registration_password - If required by the AS administrator you * may need a special password to register * tools. *@param description - A longer description of your client program * (displayed to the administrator on the manage agent * page). When registering a Proxy Tool, the * description field must be the Proxy Tool XML * description for your tool. When registering a Proxy * Tool with an XML descriptor, specify the operations * in the registerTool method or in the XML or both. If * you specify in both places, the list of operations * is merged together. Blackboard recommends specifying * them in the XML because that is the only place where * the list of 'webservices requested' is generated in * the administrator UI. *@param initial_shared_secret - the initial shared secret to be used by * this tool (note that the administrator has * to make the tool 'available' before you * can use this password and they can also * change it through the edit proxy tool UI). * Also, if you are re-registering then this * password is ignored - only valid for the * Initial registration. *@param required_tool_methods - An array of webservice methods that you * will use when logged in as a tool. *@param required_ticket_methods - An array of webservice methods that you * will use when logged in as a user via * the loginTicket method. *@return Returns a RegisterToolResultVO: * success=true - successfully registered * success=false - failed to register * proxyToolGuid = the GUID for this proxy tool if the tool being * registered is a proxy tool. This guid is a * unique identifier generated by Academic Suite * associated with this tool registration. You must * record this GUID and use it to correlate future * requests from the server with your local * configuration. */ protected RegisterToolResultVO registerTool(String client_vendor_id, String client_program_id, String registration_password, String description, String initial_shared_secret, String[] required_tool_methods, String[] required_ticket_methods) { RegisterTool register_tool = new RegisterTool(); register_tool.setClientProgramId(client_program_id); register_tool.setClientVendorId(client_vendor_id); register_tool.setDescription(description); register_tool.setInitialSharedSecret(initial_shared_secret); register_tool.setRegistrationPassword(registration_password); register_tool.setRequiredToolMethods(required_tool_methods); register_tool.setRequiredTicketMethods(required_ticket_methods); RegisterToolResponse response = null; setupSession(); try { response = contextWS.registerTool(register_tool); } catch (RemoteException e) { logger.error("Encountered a remote exception while trying to Register Tool"); logger.error(e.getMessage()); return null; } cleanupSession(); if (response == null) { logger.warn("registerTool returned null."); return null; } return response.get_return(); } /////////////////////////////////////////////////////////////////////////// // Local Methods //////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// private void setupSession() { try { ctx = ConfigurationContextFactory.createConfigurationContextFromFileSystem(modulePath); } catch (AxisFault af) { logger.error("Failed to create an initial ConfigurationContext: " + af.getMessage()); } pwcb = new ContextProxyTool.PasswordCallbackClass(); contextWS = (ContextWSStub) createClientWS(ContextWSStub.class, context_ws_url); contextWS = (ContextWSStub) configureClientOptions(contextWS); } /** * Determines the version of the ContextWS service ad initializes the * session accordingly. You can set the service version of * ContextProxyTool manually in the main configuration file using: * <param name="serverVersion" value="1"/> (value can be different) * Otherwise, the version number will be determined by calling the * _getServerVersion() method, resulting in another server hit. * * Note: Since we're trying to initialize the session, the private methods * _getServerVersion(), _initialize() and _initializeVersion2() are used. * This prevents a session initialization loop & premature session cleanup. */ private void initializeSession() { //First, check to see if we've already determined the version number if (server_version != null) { switch (server_version.intValue()) { case 2: pwcb.setSessionId(_initializeVersion2()); break; default: pwcb.setSessionId(_initialize()); break; } return; } //If we made it here, we'll try to get the server version number from the config file. String version = config.getConfigClass("ContextProxyTool", "serverVersion"); if (version != null && version.equals("2")) { server_version = 2L; pwcb.setSessionId(_initializeVersion2()); return; } if (version != null && version.equals("1")) { server_version = 1L; pwcb.setSessionId(_initialize()); return; } //If we made it here, we'll try getting the version number from the server. server_version = _getServerVersion(null).getVersion(); if (server_version != null && server_version == 2L) { pwcb.setSessionId(_initializeVersion2()); return; } if (server_version != null && server_version == 1L) { pwcb.setSessionId(_initialize()); return; } //If we can't determine the version number, return an error logger.error("Unable to determine server version number & generate a session ID"); } /** * This method will instantiate a client Stub object from a Stub class * template and a web service URL using the existing ConfigurationContext. * * @param client_stub - the class template used to determine the appropriate object * to instantiate. * @param service_url - the location of the server-side web service. * * @return Returns a client Stub object based on the parameters provided. */ protected Stub createClientWS(Class<? extends Stub> client_stub, String service_url) { Stub wsStub = null; //we're creating a generic class array and loading it with our 2 constructor object Classes Class<?>[] constructor_params = { ConfigurationContext.class, String.class }; try { //we're creating a parameterized constructor for a class that extends Stub. Constructor<? extends Stub> constructor = client_stub.getConstructor(constructor_params); //now we're instantiating the the actual subclass using the constructor that we just created. wsStub = constructor.newInstance(ctx, service_url); } catch (NoSuchMethodException e) { logger.error("Unable to create the client web service stub object: " + e.getMessage()); return null; } catch (SecurityException e) { logger.error("Unable to create the client web service stub object: " + e.getMessage()); return null; } catch (InstantiationException e) { logger.error("Unable to create the client web service stub object: " + e.getMessage()); return null; } catch (IllegalAccessException e) { logger.error("Unable to create the client web service stub object: " + e.getMessage()); return null; } catch (IllegalArgumentException e) { logger.error("Unable to create the client web service stub object: " + e.getMessage()); return null; } catch (InvocationTargetException e) { logger.error("Unable to create the client web service stub class: " + e.getMessage()); return null; } return wsStub; } /** * After instantiating a Stub object, we need to configure how it will * communicate with the server-side web service. As the name implies, * this method configures various client options. These options include * setting up Rampart-based security for user login, tool login and ticket * login. * * @param wsStub - a newly created Stub object. See createClientWS(). * @return Returns a fully-configured client Stub that will be able to * communicate with it's server-side counterpart. */ protected Stub configureClientOptions(Stub wsStub) { if (_httpClient == null) _httpClient = new HttpClient(new MultiThreadedHttpConnectionManager()); ServiceClient client = wsStub._getServiceClient(); Options options = client.getOptions(); options.setProperty(HTTPConstants.AUTO_RELEASE_CONNECTION, Constants.VALUE_TRUE); //This is where we configure the password callback handler options.setProperty(WSHandlerConstants.PW_CALLBACK_REF, pwcb); /* * Setup ws-security settings. Must use deprecated class of setting * up security because the SOAP response doesn't include a security * header. Using the deprecated OutflowConfiguration class we can * specify that the security header is only for the outgoing SOAP message. */ OutflowConfiguration ofc = new OutflowConfiguration(); ofc.setActionItems("UsernameToken Timestamp"); ofc.setUser("session"); ofc.setPasswordType("PasswordText"); options.setProperty(WSSHandlerConstants.OUTFLOW_SECURITY, ofc.getProperty()); //You might want to use the same HTTPClient instance for multiple //invocations. This flag will notify the engine to use the same //HTTPClient between invocations. options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Constants.VALUE_TRUE); //If user had requested to re-use an HTTPClient using the above //property, this property can be used to set a custom HTTPClient to //be re-used. options.setProperty(HTTPConstants.CACHED_HTTP_CLIENT, _httpClient); try { client.engageModule("rampart"); } catch (AxisFault e) { logger.error("Unable to engage the rampart security module: " + e.getMessage()); return null; } return wsStub; } /** * Whenever a session is successfully logged in, resources are allocated in * the Axis2 ConfigurationContext. Unfortunately, these resources will * persist even after invoking the logout() method. After invoking * logout(), this method will cleanup the ConfigurationContext and release * all of it's resources. * * @return Returns true when the configuration Context has been cleaned up * successfully. Otherwise, returns false. */ private boolean cleanupSession() { try { ctx.cleanupContexts(); //Called during shutdown to clean up all Contexts ctx.flush(); //(part of superclass AbstractContext) ctx.terminate(); //Invoked during shutdown to stop the ListenerManager and perform configuration cleanup } catch (RemoteException e) { logger.error("Encountered an error while attempting to cleanup the configuration context: " + e.getMessage()); session_id = null; ctx = null; return false; } ctx = null; session_id = null; return true; } /////////////////////////////////////////////////////////////////////////// // Inner Class - Password Callback Class //////////////////////////////// /////////////////////////////////////////////////////////////////////////// /** * Whenever the Rampart Engine needs a password to create a username token, * whether it is to build a signature, validate username token or decrypt * encrypted content, it will create a WSPasswordCallback instance setting * the appropriate identifier which it extracts from the <ramp:user> * parameter of the Rampart configuration (see the OutflowConfiguration * setUser() method in configureClientOptions()) and pass it to the password * callback class via the handle method. Then password callback fills the * password relevant to the given identifier so that the Rampart Engine can * use it for further processing. */ public static class PasswordCallbackClass implements CallbackHandler { public void setSessionId(String _session_id) { session_id = _session_id; } public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { WSPasswordCallback pwcb = (WSPasswordCallback) callbacks[i]; String pw = "nosession"; if (session_id != null) { pw = session_id; } pwcb.setPassword(pw); } } } }