org.smartfrog.services.deployapi.engine.ServerInstance.java Source code

Java tutorial

Introduction

Here is the source code for org.smartfrog.services.deployapi.engine.ServerInstance.java

Source

/** (C) Copyright 2004 Hewlett-Packard Development Company, LP
    
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.
    
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.
    
 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    
 For more information: www.smartfrog.org
    
 */

package org.smartfrog.services.deployapi.engine;

import nu.xom.Attribute;
import nu.xom.Element;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.ggf.cddlm.generated.api.CddlmConstants;
import org.smartfrog.projects.alpine.om.base.SoapElement;
import org.smartfrog.projects.alpine.faults.AlpineRuntimeException;
import org.smartfrog.services.deployapi.binding.DescriptorHelper;
import org.smartfrog.services.deployapi.binding.XomHelper;
import org.smartfrog.services.deployapi.components.DeploymentServer;
import org.smartfrog.services.deployapi.notifications.EventSubscriberManager;
import org.smartfrog.services.deployapi.notifications.SubscriptionServiceStore;
import org.smartfrog.services.deployapi.system.Constants;
import org.smartfrog.services.deployapi.system.Utils;
import org.smartfrog.services.deployapi.transport.wsrf.NotificationSubscription;
import org.smartfrog.services.deployapi.transport.wsrf.PropertyMap;
import org.smartfrog.services.deployapi.transport.wsrf.WSRPResourceSource;
import org.smartfrog.services.deployapi.transport.wsrf.WsrfUtils;
import org.smartfrog.services.filesystem.FileSystem;
import org.smartfrog.services.filesystem.filestore.AddedFilestore;
import org.smartfrog.services.xml.java5.Xom5Utils;
import org.smartfrog.sfcore.common.SmartFrogException;
import org.smartfrog.sfcore.common.SmartFrogLivenessException;
import org.smartfrog.sfcore.prim.Prim;

import javax.xml.namespace.QName;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * This is a server instance Date: 10-Aug-2004 Time: 22:13:26
 */
public class ServerInstance implements WSRPResourceSource {

    /**
     * a private instance
     */
    private static ServerInstance instance;

    private String resourceID = Utils.createNewID();

    private PropertyMap properties;

    private JobRepository jobs;

    private AddedFilestore filestore;

    //keep all portal subscriptions
    //private EventSubscriberManager subscriptions;

    //weak reference store of all subscriptions
    private SubscriptionServiceStore subscriptionStore = new SubscriptionServiceStore();

    private File tempdir = null;

    private DescriptorHelper descriptorHelper;

    private String protocol = "http";
    private String hostname = Constants.LOCALHOST;
    private int port = 5050;
    private String path = Constants.CONTEXT_PATH + Constants.SERVICES_PATH + Constants.SYSTEM_PATH;
    private String subscriptionsPath = Constants.CONTEXT_PATH + Constants.SERVICES_PATH
            + Constants.SUBSCRIPTION_PATH;
    private String location = "unknown";

    private static final Log log = LogFactory.getLog(ServerInstance.class);

    private URL systemsURL;

    private int requests = 0;

    private int failures = 0;

    private static final String BUILD_TIMESTAMP = "$Date$";

    //URL for subscriptions
    private URL subscriptionURL;

    /**
     * Create a new server instance, and bind it to be our current
     * server
     *
     * @param owner owning prim
     * @return the object
     * @throws SmartFrogException
     * @throws RemoteException
     */
    public static ServerInstance createServerInstance(Prim owner) throws SmartFrogException, RemoteException {
        ServerInstance serverInstance = new ServerInstance(owner);
        instance = serverInstance;
        return instance;
    }

    private ServerInstance(Prim owner) throws SmartFrogException, RemoteException {
        location = owner.sfResolve(DeploymentServer.ATTR_LOCATION, location, false);
        protocol = owner.sfResolve(DeploymentServer.ATTR_PROTOCOL, protocol, false);
        hostname = owner.sfResolve(DeploymentServer.ATTR_HOSTNAME, hostname, false);
        if (hostname.length() == 0) {
            hostname = Constants.LOCALHOST;
        }
        port = owner.sfResolve(DeploymentServer.ATTR_PORT, port, false);
        String ctx = owner.sfResolve(DeploymentServer.ATTR_CONTEXTPATH, Constants.CONTEXT_PATH, false);
        String servicespath = owner.sfResolve(DeploymentServer.ATTR_SERVICESPATH, Constants.SERVICES_PATH, false);
        String systemPath = owner.sfResolve(DeploymentServer.ATTR_SYSTEM_PATH, Constants.SYSTEM_PATH, false);
        path = ctx + servicespath + systemPath;
        subscriptionsPath = ctx + servicespath
                + owner.sfResolve(DeploymentServer.ATTR_SUBSCRIPTIONS_PATH, Constants.SUBSCRIPTION_PATH, false);
        //temp dir set up
        File javatmpdir = new File(System.getProperty("java.io.tmpdir"));
        String absolutePath = FileSystem.lookupAbsolutePath(owner, DeploymentServer.ATTR_FILESTORE_DIR, null,
                javatmpdir, false, null);
        if (absolutePath != null) {
            tempdir = new File(absolutePath);
        }
        try {
            init();
        } catch (IOException e) {
            throw SmartFrogException.forward(e);
        }
    }

    private void init() throws IOException {
        systemsURL = new URL(protocol, hostname, port, path);
        subscriptionURL = new URL(protocol, hostname, port, subscriptionsPath);
        jobs = new JobRepository(systemsURL, this, createEventExecutorService());
        if (tempdir == null) {
            tempdir = File.createTempFile("filestore", ".dir");
            //little bit of a race condition here.
            tempdir.delete();
        }
        descriptorHelper = new DescriptorHelper(tempdir);
        filestore = new AddedFilestore(tempdir);
        log.debug("Creating server instance " + toString());

        //now create our property map
        initPropertyMap();
    }

    /**
     * initiate a graceful shutdown of workers. we do this by pushing a shutdown
     * request for every worker
     */
    public void terminate() throws RemoteException {
        filestore.deleteAllEntries();
        jobs.shutdown();
    }

    /**
     * liveness check
     *
     * @throws SmartFrogLivenessException
     */
    public void ping() throws SmartFrogLivenessException {
    }

    /**
     * Returns a string representation of the object.
     *
     * @return a string representation of the object.
     */
    public String toString() {
        return "Server @" + systemsURL + " filestore:" + tempdir;
    }

    /**
     * Get the job repository
     * @return
     */
    public JobRepository getJobs() {
        return jobs;
    }

    public EventSubscriberManager getSubscriptions() {
        return jobs.getSubscriptions();
    }

    public String getSubscriptionsPath() {
        return subscriptionsPath;
    }

    /**
     * Get the URL for subscriptions
     * @return
     */
    public URL getSubscriptionURL() {
        return subscriptionURL;
    }

    /**
     * get the current instance; bailing out if none exists
     *
     * @return the current instance
     * @throws AlpineRuntimeException if needed
     */
    public static ServerInstance currentInstance() {
        if (instance == null) {
            throw new AlpineRuntimeException("No configured ServerInstance");
        }
        return instance;
    }

    /**
     * Get the server or null if none is defined
     * @return the current server instance
     */
    public static ServerInstance getServerInstanceOrNull() {
        return instance;
    }

    public DescriptorHelper getDescriptorHelper() {
        return descriptorHelper;
    }

    public AddedFilestore getFilestore() {
        return filestore;
    }

    public String getResourceID() {
        return resourceID;
    }

    private void initPropertyMap() {
        properties = new PropertyMap();
        properties.addStaticProperty(Constants.PROPERTY_MUWS_RESOURCEID, XomHelper.makeResourceId(resourceID));
        properties.addStaticProperty(Constants.PROPERTY_PORTAL_STATIC_PORTAL_STATUS, makeStaticStatus());

        //this is the dynamic property that lists active systems
        properties.add(new ActiveSystemsProperty(this));

        WsrfUtils.addManagementCharacteristics(properties, CddlmConstants.CDL_API_PORTAL_CAPABILITY);

        //the list of topics
        /*
          <wstop:Topic name="SystemCreatedEvent"
        messageTypes="muws-p1-xs:ManagementEvent">
        </wstop:Topic>
        */
        List<Element> topics = new ArrayList<Element>();
        SoapElement systemCreatedEvent = new SoapElement(CddlmConstants.PROPERTY_WSNT_TOPIC);
        systemCreatedEvent.addAttribute(new Attribute("name", "SystemCreatedEvent"));
        systemCreatedEvent.addNamespaceDeclaration("muws-p1-xs", CddlmConstants.MUWS_P1_NAMESPACE);
        systemCreatedEvent.addAttribute(new Attribute("messageTypes", "muws-p1-xs:ManagementEvent"));
        topics.add(systemCreatedEvent);
        WsrfUtils.addWsTopics(properties, topics, true, WsrfUtils.DEFAULT_TOPIC_DIALECTS);
    }

    /**
     * Get a property value
     *
     * @param property
     * @return null for no match;
     * @throws org.smartfrog.services.deployapi.transport.faults.BaseException
     *          if they feel like it
     */
    public List<Element> getProperty(QName property) {
        return properties.getProperty(property);
    }

    @SuppressWarnings("deprecation")
    private Element makeStaticStatus() {
        Element status = Xom5Utils.element(Constants.PROPERTY_PORTAL_STATIC_PORTAL_STATUS);
        Element portal = XomHelper.apiElement(StatusElements.PORTAL);
        status.appendChild(portal);

        portal.appendChild(XomHelper.apiElement(StatusElements.NAME, Constants.BUILD_INFO_IMPLEMENTATION_NAME));
        portal.appendChild(XomHelper.apiElement(StatusElements.BUILD, BUILD_TIMESTAMP));
        portal.appendChild(XomHelper.apiElement(StatusElements.LOCATION, location));
        portal.appendChild(XomHelper.apiElement(StatusElements.HOME, Constants.BUILD_INFO_HOMEPAGE));
        Date now = new Date();
        BigInteger tzoffset = BigInteger.valueOf(now.getTimezoneOffset());
        portal.appendChild(XomHelper.apiElement(StatusElements.TIMEZONE_UTCOFFSET, tzoffset.toString()));

        Element languages = XomHelper.apiElement(StatusElements.LANGUAGES);
        Element cdl = XomHelper.apiElement(StatusElements.ITEM);
        Element name = XomHelper.apiElement(StatusElements.NAME, Constants.BUILD_INFO_CDL_LANGUAGE);
        Element uri = XomHelper.apiElement(StatusElements.URI, Constants.XML_CDL_NAMESPACE);
        cdl.appendChild(name);
        cdl.appendChild(uri);
        languages.appendChild(cdl);
        status.appendChild(languages);
        Element sfrog = XomHelper.apiElement(StatusElements.ITEM);
        name = XomHelper.apiElement(StatusElements.NAME, Constants.BUILD_INFO_SF_LANGUAGE);
        uri = XomHelper.apiElement(StatusElements.URI, Constants.SMARTFROG_NAMESPACE);
        sfrog.appendChild(name);
        sfrog.appendChild(uri);
        languages.appendChild(sfrog);

        Element notifications = XomHelper.apiElement(StatusElements.NOTIFICATIONS);
        Element wsrf = XomHelper.apiElement(StatusElements.ITEM, Constants.WSRF_WSNT_NAMESPACE);
        notifications.appendChild(wsrf);
        status.appendChild(notifications);

        Element options = XomHelper.apiElement(StatusElements.OPTIONS);
        status.appendChild(options);
        return status;
    }

    public synchronized void resetStatistics() {
        failures = 0;
        requests = 0;
    }

    public int getRequests() {
        return requests;
    }

    public int getFailures() {
        return failures;
    }

    public void incrementRequests() {
        synchronized (this) {
            requests++;
        }
    }

    public void incrementFailures() {
        synchronized (this) {
            failures++;
        }
    }

    /**
     * Control point for managing
     * @return
     */
    public ExecutorService createEventExecutorService() {
        return Executors.newSingleThreadExecutor();
    }

    public SubscriptionServiceStore getSubscriptionStore() {
        return subscriptionStore;
    }

    /**
     * subscribe to portal events
     * @param subscription
     */
    public void subscribeToPortalEvents(NotificationSubscription subscription) {
        log.info("Adding portal subscription " + subscription);
        EventSubscriberManager subscriptions = getSubscriptions();
        subscriptions.add(subscription);
        getSubscriptionStore().add(subscription);
    }
}