Java tutorial
/* * Copyright 1999-2008 University of Chicago * * 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.globus.workspace.client.modes; import org.globus.workspace.common.print.Print; import org.globus.workspace.client_core.print.PrCodes; import org.globus.workspace.client_core.ParameterProblem; import org.globus.workspace.client_core.ExecutionProblem; import org.globus.workspace.client_core.ExitNow; import org.globus.workspace.client_core.StubConfigurator; import org.globus.workspace.client_core.utils.EPRUtils; import org.globus.workspace.client_core.subscribe_tools.ListeningSubscriptionMaster; import org.globus.workspace.client_core.subscribe_tools.PollingSubscriptionMaster; import org.globus.workspace.client_core.subscribe_tools.SubscriptionMaster; import org.globus.workspace.client_core.subscribe_tools.NotificationImplementationException; import org.globus.workspace.client_core.subscribe_tools.SubscriptionMasterFactory; import org.globus.workspace.client_core.repr.State; import org.globus.workspace.client_core.repr.Workspace; import org.globus.workspace.client.AllArguments; import org.globus.workspace.client.modes.aux.SubscribeLaunch; import org.globus.workspace.client.modes.aux.CommonLogs; import org.nimbustools.messaging.gt4_0.common.CommonUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.axis.message.addressing.EndpointReferenceType; import edu.emory.mathcs.backport.java.util.concurrent.ExecutorService; import java.net.URL; import java.net.MalformedURLException; public class Subscribe extends Mode { // ------------------------------------------------------------------------- // STATIC VARIABLES // ------------------------------------------------------------------------- private static final Log logger = LogFactory.getLog(Subscribe.class.getName()); // ------------------------------------------------------------------------- // INSTANCE VARIABLES // ------------------------------------------------------------------------- EndpointReferenceType epr; boolean dryrun; boolean autodestroy; boolean isGroupRequest; String nameToPrint; String shortName; Workspace[] workspaces; // note that "subscribe" has same meaning here whether polling or not boolean pollDontListen; // true: poll, false: async listen State exitState; State veryTerseNotifyState; SubscribeLaunch subscribeLaunch; ListeningSubscriptionMaster listeningSubscriptionMaster; PollingSubscriptionMaster pollingSubscriptionMaster; SubscriptionMaster eitherSubscriptionMaster; String notificationListenerOverride_IPorHost; Integer notificationListenerOverride_Port; long pollMS = -1; int pollMaxThreads = -1; // ------------------------------------------------------------------------- // CONSTRUCTOR // ------------------------------------------------------------------------- public Subscribe(Print print, AllArguments arguments, StubConfigurator stubConfigurator) { super(print, arguments, stubConfigurator); } // ------------------------------------------------------------------------- // GENERAL // ------------------------------------------------------------------------- public String name() { return "Subscribe"; } // ------------------------------------------------------------------------- // VALIDATE // ------------------------------------------------------------------------- public void validateOptionsImpl() throws ParameterProblem { this.validateEndpoint(); this.validateName(); this._handleExitState(); this._handleVeryTerseNotifyState(); this._handlePollDelay(); this._handlePollMaxThreads(); this._handleListenerOverride(); this.dryrun = this.args.dryrun; CommonLogs.logBoolean(this.dryrun, "dryrun mode", this.pr, logger); this.autodestroy = this.args.autodestroy; CommonLogs.logBoolean(this.autodestroy, "autodestroy mode", this.pr, logger); this._logSubscribeStatus(); if (this.pollDontListen) { this._handleSubscribeWithPoll(); } else { this._handleSubscribeWithListen(); } this._handleWorkspaces(); } protected void validateEndpoint() throws ParameterProblem { this.epr = this.stubConf.getEPR(); if (this.epr == null) { throw new ParameterProblem(name() + " requires EPR"); } final String eprStr; try { eprStr = EPRUtils.eprToString(this.epr); } catch (Exception e) { final String err = CommonUtil.genericExceptionMessageWrapper(e); throw new ParameterProblem(err, e); } if (this.pr.enabled()) { // xml print final String dbg = "\nGiven EPR:\n----------\n" + eprStr + "----------\n"; if (this.pr.useThis()) { this.pr.dbg(dbg); } else if (this.pr.useLogging()) { logger.debug(dbg); } } final String kind; if (EPRUtils.isInstanceEPR(this.epr)) { this.isGroupRequest = false; kind = "an instance"; } else if (EPRUtils.isGroupEPR(this.epr)) { this.isGroupRequest = true; kind = "a group"; } else { throw new ParameterProblem(name() + " requires a valid EPR."); } if (this.pr.enabled()) { final String dbg = "Given EPR is " + kind + " EPR"; if (this.pr.useThis()) { this.pr.dbg(dbg); } else if (this.pr.useLogging()) { logger.debug(dbg); } } if (this.isGroupRequest) { throw new ParameterProblem( name() + " can not handle group " + "subscribe yet (only after deploying). Stay tuned."); } } protected void validateName() throws ParameterProblem { String eprName; if (this.isGroupRequest) { eprName = EPRUtils.getGroupIdFromEPR(this.epr); eprName = "group-" + eprName; } else { eprName = Integer.toString(EPRUtils.getIdFromEPR(this.epr)); eprName = "workspace-" + eprName; } this.shortName = this.args.shortName; if (this.pr.enabled()) { final String dbg; if (this.shortName == null) { dbg = "Given display name is null"; } else { dbg = "Given display name: " + this.shortName + "'"; } if (this.pr.useThis()) { this.pr.dbg(dbg); } else if (this.pr.useLogging()) { logger.debug(dbg); } } if (this.shortName != null) { this.nameToPrint = this.shortName; } else { this.nameToPrint = eprName; } } protected void _handleExitState() throws ParameterProblem { if (this.args.exitStateString == null) { return; // *** EARLY RETURN *** } if (!State.testValidState(this.args.exitStateString)) { throw new ParameterProblem( "Provided exit string is not a " + "valid state: '" + this.args.exitStateString + "'"); } this.exitState = new State(this.args.exitStateString); if (this.pr.enabled()) { final String dbg = "Exit state: " + this.exitState.toString(); if (this.pr.useThis()) { this.pr.dbg(dbg); } else if (this.pr.useLogging()) { logger.debug(dbg); } } } protected void _handleVeryTerseNotifyState() throws ParameterProblem { if (this.args.veryTerseNotifyStateString == null) { return; // *** EARLY RETURN *** } if (!State.testValidState(this.args.veryTerseNotifyStateString)) { throw new ParameterProblem("Provided very-terse-notify state string is not a " + "valid state: '" + this.args.veryTerseNotifyStateString + "'"); } this.veryTerseNotifyState = new State(this.args.veryTerseNotifyStateString); if (this.pr.enabled()) { final String dbg = "very-terse-notify state: " + this.veryTerseNotifyState.toString(); if (this.pr.useThis()) { this.pr.dbg(dbg); } else if (this.pr.useLogging()) { logger.debug(dbg); } } } protected void _handlePollDelay() throws ParameterProblem { if (this.args.pollDelayString == null) { return; // *** EARLY RETURN *** } // default subscription mode is notification listener // setting the poll delay sets the subscription mode to poll this.pollDontListen = true; try { this.pollMS = Long.parseLong(this.args.pollDelayString); } catch (NumberFormatException e) { throw new ParameterProblem( "Given poll delay is not valid: '" + this.args.pollDelayString + "': " + e.getMessage(), e); } if (this.pollMS < 1) { throw new ParameterProblem("Given poll delay is less than 1ms: " + this.pollMS + "ms"); } } protected void _handlePollMaxThreads() throws ParameterProblem { if (this.args.pollMaxThreadsString == null) { return; // *** EARLY RETURN *** } try { this.pollMaxThreads = Integer.parseInt(this.args.pollMaxThreadsString); } catch (NumberFormatException e) { throw new ParameterProblem("Given poll max-threads number is not valid: '" + this.args.pollMaxThreadsString + "': " + e.getMessage(), e); } if (this.pollMaxThreads < 1) { throw new ParameterProblem( "Given poll max-threads is invalid, " + "it is less than 1: " + this.pollMaxThreads); } } protected void _handleListenerOverride() throws ParameterProblem { final String given = this.args.listenerOverride; if (given == null) { return; // *** EARLY RETURN *** } if (given.indexOf('/') >= 0) { throw new ParameterProblem( "Listener override address has a '/' " + "in it, use just a host or IP, not an URL"); } final int splt = given.indexOf(':'); // first occurence only final String host; final String port; if (splt >= 0) { host = given.substring(0, splt).trim(); port = given.substring(splt).trim(); } else { host = given.trim(); port = null; } if (host.length() == 0) { throw new ParameterProblem( "Listener override address " + "has zero-length hostname, given: \"" + given + "\""); } if (port != null && port.length() == 0) { throw new ParameterProblem( "Listener override address " + "has zero-length port, given: \"" + given + "\""); } final String urlString; if (port == null) { urlString = "http://" + host; } else { urlString = "http://" + host + ":" + port; } final String usingHost; int usingPort = -1; try { final URL url = new URL(urlString); usingHost = url.getHost(); if (port != null) { usingPort = url.getPort(); } } catch (MalformedURLException e) { throw new ParameterProblem( "Falied to test validity of listener " + "override address using given input '" + given + "', " + "testing with URL constructed from '" + urlString + "': " + e.getMessage(), e); } this.notificationListenerOverride_IPorHost = usingHost; if (usingPort > 0) { this.notificationListenerOverride_Port = new Integer(usingPort); } } protected void _logSubscribeStatus() { if (!this.pr.enabled()) { return; // *** EARLY RETURN *** } String listenTail = ""; if (this.notificationListenerOverride_IPorHost != null && this.notificationListenerOverride_Port != null) { final String addr = this.notificationListenerOverride_IPorHost + ":" + this.notificationListenerOverride_Port.intValue(); listenTail = " (listener override host+port: '" + addr + "')"; } else if (this.notificationListenerOverride_IPorHost != null) { listenTail = " (listener override host: '" + this.notificationListenerOverride_IPorHost + "')"; } final String dbg; if (this.pollDontListen) { dbg = "subscription mode: POLL (" + this.pollMS + "ms delay)"; } else { dbg = "subscription mode: LISTENER" + listenTail; } if (this.pr.useThis()) { this.pr.dbg(dbg); } else if (this.pr.useLogging()) { logger.debug(dbg); } } protected void _handleSubscribeWithListen() throws ParameterProblem { if (this.eitherSubscriptionMaster != null) { throw new IllegalStateException("you may only make one " + "subscription master non-null (and copy its reference " + "to 'either' variable)"); } this.listeningSubscriptionMaster = SubscriptionMasterFactory.newListeningMaster(null, this.pr); this.eitherSubscriptionMaster = this.listeningSubscriptionMaster; if (this.dryrun) { final String dbg = "Dryrun, not starting to listen for notifications."; if (this.pr.useThis()) { this.pr.info(PrCodes.CREATE__DRYRUN, dbg); } else if (this.pr.useLogging()) { logger.info(dbg); } return; // *** EARLY RETURN *** } final String errPrefix = "Problem starting to listen for notifications: "; try { this.listeningSubscriptionMaster.listen(this.notificationListenerOverride_IPorHost, this.notificationListenerOverride_Port); } catch (IllegalStateException e) { throw new ParameterProblem(errPrefix + e.getMessage(), e); } catch (IllegalArgumentException e) { throw new ParameterProblem(errPrefix + e.getMessage(), e); } catch (Exception e) { throw new ParameterProblem(errPrefix + e.getMessage(), e); } this.subscribeLaunch = new SubscribeLaunch(this.listeningSubscriptionMaster, this.nameToPrint, this.pr, this.stubConf, null); } protected void _handleSubscribeWithPoll() throws ParameterProblem { if (this.eitherSubscriptionMaster != null) { throw new IllegalStateException("you may only make one " + "subscription master non-null (and copy its reference " + "to 'either' variable)"); } final long ms = this.pollMS; final int thrNum = this.pollMaxThreads; final ExecutorService execService = null; final StubConfigurator conf = this.stubConf; final PollingSubscriptionMaster master; if (thrNum < 1) { // default maxThreads master = SubscriptionMasterFactory.newPollingMaster(ms, conf, execService, this.pr); } else { // cap the maxThreads master = SubscriptionMasterFactory.newPollingMaster(ms, thrNum, conf, execService, this.pr); } this.pollingSubscriptionMaster = master; this.eitherSubscriptionMaster = master; this.subscribeLaunch = new SubscribeLaunch(master, this.nameToPrint, this.pr, this.stubConf, null); } protected void _handleWorkspaces() { if (this.isGroupRequest) { throw new IllegalStateException("group requests should have been rejected already"); } final Workspace workspace = new Workspace(); workspace.setEpr(this.epr); workspace.setCurrentState(new State()); this.workspaces = new Workspace[1]; this.workspaces[0] = workspace; } // ------------------------------------------------------------------------- // EXECUTE // ------------------------------------------------------------------------- public void runImpl() throws ParameterProblem, ExecutionProblem, ExitNow { try { _runImpl(); } finally { this.doneCleanupSubscriptions(); } } private void _runImpl() throws ParameterProblem, ExecutionProblem, ExitNow { this.subscribeLaunch.subscribe(this.workspaces, this.exitState, this.veryTerseNotifyState, this.autodestroy, false, false); } protected void doneCleanupSubscriptions() { if (this.listeningSubscriptionMaster != null) { try { this.listeningSubscriptionMaster.stopListening(); } catch (NotificationImplementationException e) { if (this.pr.enabled()) { final String err = "Problem stopping notification listener: " + e.getMessage(); if (this.pr.useThis()) { this.pr.errln(PrCodes.ANY_ERROR_CATCH_ALL, err); } else if (this.pr.useLogging()) { if (logger.isDebugEnabled()) { logger.error(err, e); } else { logger.error(err); } } } } } if (this.pollingSubscriptionMaster != null) { this.pollingSubscriptionMaster.stopPolling(); } } }