/* * Copyright 2008 the original author or authors. * * 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.rioproject.tools.cli; import com.sun.jini.proxy.BasicProxyTrustVerifier; import net.jini.config.Configuration; import net.jini.config.ConfigurationException; import net.jini.export.Exporter; import net.jini.jeri.BasicILFactory; import net.jini.jeri.BasicJeriExporter; import net.jini.jeri.tcp.TcpServerEndpoint; import net.jini.security.TrustVerifier; import net.jini.security.proxytrust.ServerProxyTrust; import org.rioproject.deploy.ServiceProvisionListener; import org.rioproject.opstring.OperationalString; import org.rioproject.deploy.ServiceBeanInstance; import org.rioproject.opstring.ServiceElement; import java.rmi.RemoteException; import java.rmi.server.ExportException; /** * Class to handle ServiceProvisionEvent notifications * * @author Dennis Reedy */ public class ServiceProvisionNotification implements ServiceProvisionListener, ServerProxyTrust { Exporter exporter; ServiceProvisionListener provisionListener; int provisionedSuccessfully; int provisionFailures; int notificationCounter; int serviceCounter; boolean interactive = false; final Object mutex = new Object(); /** * Create the ServiceProvisionNotification utility * * @param config The configuration * * @throws ConfigurationException If the configuration is no good * @throws ExportException If the exporter cannot be created */ public ServiceProvisionNotification(Configuration config) throws ConfigurationException, ExportException { Exporter defaultExporter = new BasicJeriExporter(TcpServerEndpoint.getInstance(0), new BasicILFactory(), false, true); exporter = (Exporter)config.getEntry("org.rioproject.tools.cli", "provisionListenerExporter", Exporter.class, defaultExporter); provisionListener = (ServiceProvisionListener)exporter.export(this); } /** * Unexport this utility */ public void unexport() { exporter.unexport(true); } /** * Get the ServiceProvisionListener proxy * * @return The ServiceProvisionListener proxy */ public ServiceProvisionListener getServiceProvisionListener() { return(provisionListener); } /** * Set the number of notifications and the timeout * * @param serviceCount the number of services * @param maxTimeout The maximum amount of time (in millis) to wait */ public void notify(int serviceCount, final long maxTimeout) { interactive = true; notificationCounter = 0; serviceCounter = serviceCount; synchronized(mutex) { try { mutex.wait(maxTimeout); interactive = false; if(notificationCounter<serviceCounter) { System.out.println("\t- There are "+ "["+(serviceCounter-notificationCounter)+"] "+ "service provisioning requests outstanding"); } } catch(InterruptedException e) { e.printStackTrace(); } } } private void receivedNotify() { if(interactive) { notificationCounter++; if(notificationCounter==serviceCounter) { synchronized(mutex) { mutex.notifyAll(); } } } } public void succeeded(ServiceBeanInstance jsbInstance) throws RemoteException { provisionedSuccessfully++; if(interactive) System.out.println("\t["+(notificationCounter+1)+"] "+ jsbInstance.getServiceBeanConfig().getName()+" "+ "provisioned to\t"+jsbInstance.getHostAddress()); receivedNotify(); } public void failed(ServiceElement sElem, boolean resubmitted) throws RemoteException { provisionFailures++; receivedNotify(); if(interactive) System.out.println("\t"+sElem.getName()+" provision failure"); } public TrustVerifier getProxyVerifier() { return new BasicProxyTrustVerifier(provisionListener); } /** * Sum up all services that need to be deployed * * @param deployment The deployed OperationalString * * @return The number of services indicated by summing up all planned * values */ public static int sumUpServices(OperationalString deployment) { int summation = 0; ServiceElement[] elems = deployment.getServices(); for (ServiceElement elem : elems) { summation += elem.getPlanned(); } OperationalString[] nested = deployment.getNestedOperationalStrings(); for (OperationalString aNested : nested) { summation += sumUpServices(aNested); } return (summation); } /** * Get the name(s) of the deployments for an OperationalString. If the * deployment has nested components, return a comma-separated list of * deployment names * * @param deployment The OperationalString * * @return The name(s) of the deployments for an OperationalString. */ public static String getDeploymentNames(OperationalString deployment) { StringBuffer buffer = new StringBuffer(); buffer.append(deployment.getName()); OperationalString[] nested = deployment.getNestedOperationalStrings(); for (OperationalString aNested : nested) { buffer.append(", ").append(getDeploymentNames(aNested)); } return (buffer.toString()); } }