Package org.rioproject.cybernode

Source Code of org.rioproject.cybernode.StaticCybernode$ActivatedService

/*
* Copyright to 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.cybernode;

import net.jini.config.Configuration;
import net.jini.config.EmptyConfiguration;
import net.jini.id.UuidFactory;
import org.rioproject.cybernode.service.Environment;
import org.rioproject.cybernode.service.ServiceBeanContainerImpl;
import org.rioproject.cybernode.service.ServiceBeanDelegateImpl;
import org.rioproject.deploy.ServiceBeanInstance;
import org.rioproject.deploy.ServiceBeanInstantiationException;
import org.rioproject.impl.opstring.OAR;
import org.rioproject.impl.opstring.OpStringLoader;
import org.rioproject.opstring.*;
import org.rioproject.resolver.Artifact;
import org.rioproject.resolver.ResolverHelper;
import org.rioproject.impl.client.LookupCachePool;
import org.rioproject.start.LogManagementHelper;
import org.rioproject.impl.system.ComputeResource;
import org.rioproject.url.artifact.ArtifactURLStreamHandlerFactory;
import org.rioproject.impl.util.StringUtil;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RMISecurityManager;
import java.security.*;
import java.util.*;

/**
* A simple container for instantiating service beans. This utility can be used
* to create a service bean either from a classname, or from an
* <tt>OperationalString</tt> document. If the latter is used, the service bean
* is created using the attributes contained within the <tt>OperationalString</tt>
* document.
*
* <p>The <tt>StaticCybernode</tt> returns the implementation (back-end) object
* for the service bean(s) that have been created. This allows direct
* manipulation of the implementation, allowing debugging and unit testing to occur
* easily.
*
* <p>Notes:<br>
* <ul>
* <li>This utility expects that all necessary classes are in the
* classpath of the JVM in order to activate the service bean(s).</li>
* <li>If associations have been declared (with setter properties) the
* injection of associated services is undefined at this time.</li>
* <li><tt>OperationalString</tt> attributes relating to provisioning and
* SLAs are undefined at this time
* <li>The StaticCybernode does not support the instantiation of forked services.</li>
* </ul>
*
* @author Dennis Reedy
*/
public class StaticCybernode {
    private ServiceBeanContainerImpl instantiator;
    //private final Map<Object, Object> serviceMap = new HashMap<Object, Object>();
    private final Set<ActivatedService> serviceSet = new HashSet<ActivatedService>();

    static {
        Policy.setPolicy(
            new Policy() {
                public PermissionCollection getPermissions(CodeSource codesource) {
                    Permissions perms = new Permissions();
                    perms.add(new AllPermission());
                    return(perms);
                }
                public void refresh() {
                }

            });
        System.setSecurityManager(new RMISecurityManager());
        System.setProperty("StaticCybernode", "true");
    }

    public StaticCybernode()  {
        LogManagementHelper.setup();
        try {
            new URL("artifact:org.rioproject");
        } catch (MalformedURLException e) {
            URL.setURLStreamHandlerFactory(new ArtifactURLStreamHandlerFactory());
        }
        try {
            Configuration config = EmptyConfiguration.INSTANCE;
            instantiator = new ServiceBeanContainerImpl(config);
            ComputeResource cr = new ComputeResource();
            String provisionRoot = Environment.setupProvisionRoot(true, config);
            cr.setPersistentProvisioningRoot(provisionRoot);
            cr.boot();
            instantiator.setComputeResource(cr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        instantiator.setUuid(UuidFactory.generate());
        LookupCachePool.getInstance().setServiceBeanContainer(instantiator);
    }

    /**
     * Shutdown & terminate the StaticCybernode
     */
    public void destroy() {
        instantiator.terminateServices();
    }

    /**
     * Activate a service bean.
     * 
     * @param classname The service bean class to create.
     * @return The service bean implementation, initialized by the
     * <tt>Cybernode</tt>. The service bean will have been instantiated with
     * an empty configuration.
     *
     * @throws org.rioproject.deploy.ServiceBeanInstantiationException If the service bean cannot be created
     */
    public Object activate(String classname) throws ServiceBeanInstantiationException {
        if(classname==null)
            throw new IllegalArgumentException("classname must not be null");
        ServiceBeanInstance instance =
            instantiator.activate(makeServiceElement(classname),
                                  null,  // OperationalStringManager
                                  null); // EventHandler (slas)
        ServiceBeanDelegateImpl delegate =
            (ServiceBeanDelegateImpl) instantiator.getServiceBeanDelegate(instance.getServiceBeanID());
        Object impl = delegate.getImpl();
        serviceSet.add(new ActivatedService(impl, delegate.getProxy(), delegate));
        return impl;
    }

    /**
     * Activate service beans defined in an <tt>OperationalString</tt> document,
     * scoping the beans to be activated by providing the bean names.
     *
     * @param opstring The <tt>OperationalString</tt> document
     * @param beans The bean names to create. If not provided all
     * services in the opstring will be created
     * @return A map of bean name keys and service implementation object values
     *
     * @throws Exception If the <tt>OperationalString</tt> document results in
     * parsing errors or the bean(s) cannot be created.
     */
    public Map<String, Object> activate(File opstring, String... beans) throws Exception {
         if(opstring==null)
            throw new IllegalArgumentException("opstring file must not be null");
        Map<String, Object> map = new HashMap<String, Object>();
        OpStringLoader opl = new OpStringLoader();
        OperationalString[] opStrings = opl.parseOperationalString(opstring);
        for(OperationalString ops : opStrings) {
            if(beans!=null && beans.length>0)
                map.putAll(activate(ops, beans));
            else
                map.putAll(activate(ops));
        }
        return map;
    }

    /**
     * Activate service beans defined by an OAR artifact,
     * scoping the beans to be activated by providing the bean names.
     *
     * @param artifact The <code>Artifact</code> to activate
     * @param beans The bean names to create. If not provided all
     * services in the opstring will be created
     * @return A map of bean name keys and service implementation object values
     *
     * @throws Exception If the <tt>OperationalString</tt> document results in
     * parsing errors or the bean(s) cannot be created.
     */
    @SuppressWarnings("unused")
    public Map<String, Object> activate(Artifact artifact, String... beans) throws Exception {
        if(artifact==null)
            throw new IllegalArgumentException("artifact must not be null");
        URL opStringURL = ResolverHelper.getResolver().getLocation(artifact.getGAV(), "oar");
        if(opStringURL==null)
            throw new OperationalStringException("Artifact "+artifact+" not resolvable");
        OAR oar = new OAR(new File(opStringURL.toURI()));
        OperationalString[] opStrings = oar.loadOperationalStrings();
        Map<String, Object> map = new HashMap<String, Object>();

        for(OperationalString ops : opStrings) {
            if(beans!=null && beans.length>0)
                map.putAll(activate(ops, beans));
            else
                map.putAll(activate(ops));
        }
        return map;
    }

    /**
     * Activate service beans defined in an {@link org.rioproject.opstring.OperationalString},
     * scoping the beans to be activated by providing the bean names.
     *
     * @param opstring The <tt>OperationalString</tt> document
     * @param beans The bean names to create. If not provided all
     * services in the opstring will be created
     * @return A map of bean name keys and service implementation object values
     *
     * @throws org.rioproject.deploy.ServiceBeanInstantiationException If the bean(s) cannot be created.
     */
    public Map<String, Object> activate(OperationalString opstring, String... beans)
        throws ServiceBeanInstantiationException {
        if(opstring==null)
            throw new IllegalArgumentException("opstring must not be null");
        Map<String, Object> map = new HashMap<String, Object>();
        for(ServiceElement elem : opstring.getServices()) {
            for(String bean : beans) {
                if(elem.getName().equals(bean)) {
                    map.put(elem.getName(), instantiateBean(elem));
                }
            }
        }
        for(OperationalString nested : opstring.getNestedOperationalStrings()) {
            activate(nested, beans);
        }
        return map;
    }

    /**
     * Activate all service beans defined in an
     * {@link org.rioproject.opstring.OperationalString}
     *
     * @param opstring The <tt>OperationalString</tt> document
     * @return A map of bean name keys and service implementation object values
     *
     * @throws org.rioproject.deploy.ServiceBeanInstantiationException If the bean(s) cannot be created.
     */
    public Map<String, Object> activate(OperationalString opstring)
        throws ServiceBeanInstantiationException {
        Map<String, Object> map = new HashMap<String, Object>();
        for(ServiceElement elem : opstring.getServices()) {
            map.put(elem.getName(), instantiateBean(elem));
        }
        return map;
    }

    /**
     * De-activate a service
     *
     * @param impl The service implementation, obtained through the
     * <tt>activate</tt> method
     */
    public void deactivate(Object impl)  {
        ActivatedService a = getActivatedService(impl);
        if(a!=null) {
            a.delegate.terminate();
            a.proxy = null;
            a.impl = null;
            a.delegate = null;
            synchronized (serviceSet) {
                serviceSet.remove(a);
            }
        }
    }

    /**
     * Get the proxy for a service implementation created by the
     * <tt>StaticCybernode</tt>
     *
     * @param impl The service implementation, obtained through the
     * <tt>activate</tt> method
     * @return The proxy for the service, or null if the service implementation
     * has not been created by the <tt>StaticCybernode</tt>
     *
     * @throws IllegalArgumentException if the impl parameter is null
     */
    public Object getServiceProxy(Object impl)  {
        if(impl==null)
            throw new IllegalArgumentException("impl must not be null");
        ActivatedService a = getActivatedService(impl);
        return a==null?null:a.proxy;
    }

    private ActivatedService getActivatedService(Object impl) {
        ActivatedService activatedService = null;
        synchronized (serviceSet) {
            for(ActivatedService a : serviceSet) {
                if(a.impl.equals(impl)) {
                    activatedService = a;
                    break;
                }
            }
        }
        return activatedService;
    }

    private Object instantiateBean(ServiceElement elem) throws ServiceBeanInstantiationException {
        if(elem.forkService())
            throw new ServiceBeanInstantiationException("The StaticCybernode does not " +
                                                        "support the instantiation of a " +
                                                        "service declared to be forked");
        ServiceBeanInstance instance = instantiator.activate(elem,
                                                             null,  // OperationalStringManager
                                                             null); // EventHandler (slas)
        ServiceBeanDelegateImpl delegate = (ServiceBeanDelegateImpl) instantiator.getServiceBeanDelegate(instance.getServiceBeanID());
        Object impl = delegate.getImpl();
        serviceSet.add(new ActivatedService(impl, delegate.getProxy(), delegate));
        return impl;
    }

    private static String[] parseBeans(String beans) {
        return StringUtil.toArray(beans);
    }

    private ServiceElement makeServiceElement(String implClass) {
        ServiceElement elem = new ServiceElement();
        ClassBundle main = new ClassBundle(implClass);
        elem.setComponentBundle(main);
        ServiceBeanConfig sbc = new ServiceBeanConfig();
        String name = implClass;
        int ndx = implClass.lastIndexOf(".");
        if(ndx>0)
            name = implClass.substring(ndx+1);
        sbc.setName(name);
        elem.setServiceBeanConfig(sbc);
        return elem;
    }

    private static class ActivatedService {
        private Object impl;
        private Object proxy;
        private ServiceBeanDelegateImpl delegate;

        private ActivatedService(Object impl, Object proxy, ServiceBeanDelegateImpl delegate) {
            this.impl = impl;
            this.proxy = proxy;
            this.delegate = delegate;
        }
    }

    /**
     * The <tt>StaticCybernode</tt> can be invoked directly from the command
     * line. The <tt>StaticCybernode</tt> expects that all necessary classes
     * are in the classpath of the JVM in order to activate the service
     * bean(s). This includes the Rio, River (Jini) and Groovy jars, as well as
     * any specific application classes.
     *
     * <p>Invoking the <tt>StaticCybernode</tt> is done as follows:
     * <pre>
     *  Usage:
     *      org.rioproject.cybernode.StaticCybernode service-class-name | opstring-file [bean-names]
     * </pre>
     * <p>The <tt>StaticCybernode</tt>  takes either a
     * <table style="text-align: left; width: 100%;" border="1" cellpadding="2"
     * cellspacing="2">
     * <tbody>
     * <tr>
     * <td style="vertical-align: top;"><b>Argument</b><br>
     * </td>
     * <td style="vertical-align: top;"><b>Description</b><br>
     * </td>
     * </tr>
     * <tr>
     * <td style="vertical-align: top;">service-class-name<br>
     * </td>
     * <td style="vertical-align: top;">The fully qualified class name
     * of the service bean to instantiate. The service bean will be created
     * with an <i>empty</i> configuration<br>
     * </td>
     * </tr>
     * <tr>
     * <td style="vertical-align: top;">opstring-file<br>
     * </td>
     * <td style="vertical-align: top;">The OperationalString document
     * (either .xml or .groovy) declaring service beans and service bean
     * attributes.<br>
     * </td>
     * </tr>
     * <tr>
     * <td style="vertical-align: top;">bean-names<br>
     * </td>
     * <td style="vertical-align: top;">Optional comma-separated list of
     * beans to create within the provided opstring-file<br>
     * </td>
     * </tr>
     * </tbody>
     * </table>
     *
     * @param args Either a <tt>service-class-name</tt> or the location of an
     * <tt>opstring-file</tt> with optional <tt>bean-names</tt>
     */
    public static void main(String... args) {
        if(args.length==0) {
            StringBuilder sb = new StringBuilder();
            sb.append("Usage: \n");
            sb.append("\t")
                .append(StaticCybernode.class.getName())
                .append(" service-class-name | opstring-file [bean-names]\n");
            System.out.println(sb.toString());
            System.exit(1);
        }
        try {
            StaticCybernode sbc = new StaticCybernode();
            List<String> options = new ArrayList<String>(Arrays.asList(args));
            String option = options.get(0);
            if(option.endsWith(".xml") || option.endsWith(".groovy")) {
                options.remove(option);
                String[] beans = null;
                if(!options.isEmpty())
                    beans = parseBeans(options.get(0));
                sbc.activate(new File(args[0]), beans);
            }
            else {
                sbc.activate(args[0]);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
TOP

Related Classes of org.rioproject.cybernode.StaticCybernode$ActivatedService

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.