Package org.nimbustools.messaging.gt4_0.service

Source Code of org.nimbustools.messaging.gt4_0.service.InstanceHome

/*
* 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.nimbustools.messaging.gt4_0.service;

import org.nimbustools.messaging.gt4_0.common.Constants_GT4_0;
import org.nimbustools.messaging.gt4_0.common.NimbusLocalMasterContext;
import org.nimbustools.messaging.gt4_0.common.NimbusMasterContext;
import org.globus.wsrf.ResourceHome;
import org.globus.wsrf.Resource;
import org.globus.wsrf.ResourceKey;
import org.globus.wsrf.ResourceException;
import org.globus.wsrf.NoSuchResourceException;
import org.globus.wsrf.InvalidResourceKeyException;
import org.globus.wsrf.RemoveNotSupportedException;
import org.globus.wsrf.RemoveCallback;
import org.globus.wsrf.impl.lifetime.SetTerminationTimeProvider;
import org.globus.wsrf.config.ConfigException;
import org.globus.wsrf.jndi.Initializable;
import org.nimbustools.api.services.rm.Manager;
import org.nimbustools.api.services.rm.ManageException;
import org.nimbustools.api.services.rm.DoesNotExistException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.namespace.QName;
import java.io.File;
import java.net.URL;

import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import net.sf.ehcache.CacheManager;
import commonj.timers.TimerManager;

public class InstanceHome implements ResourceHome, Initializable {

    // -------------------------------------------------------------------------
    // STATIC VARIABLES
    // -------------------------------------------------------------------------

    private static final Log logger =
            LogFactory.getLog(InstanceHome.class.getName());
   
   
    // -------------------------------------------------------------------------
    // INSTANCE VARIABLES
    // -------------------------------------------------------------------------
   
    private Manager manager;
    private TimerManager timerManager;
    private String secDescPath;
    private InstanceTranslate translate;
    private Cache cache;

    // note: don't change, other classes consult Constants_GT4_0 directly
    private final QName keyTypeName =
            Constants_GT4_0.RESOURCE_KEY_QNAME;

   
    // -------------------------------------------------------------------------
    // implements Initializable
    // -------------------------------------------------------------------------

    public void initialize() throws Exception {

        final NimbusMasterContext master =
                NimbusLocalMasterContext.discoverApplicationContext();

        this.manager = master.getModuleLocator().getManager();

        // something in this layer needs to init the metadata server at
        // container startup (lame)
        master.getModuleLocator().getMetadataServer();

        this.translate = new InstanceTranslate(
                                    master.getModuleLocator().getReprFactory(),
                                    master.getBaseURL());

        this.secDescPath = master.getBaseLocation() + File.separator +
                                Constants_GT4_0.SERVICE_SECURITY_CONFIG;

        final URL url = this.getClass().getResource("ehcache.xml");
        final CacheManager cacheManager = new CacheManager(url);
        this.cache = cacheManager.getCache("instanceCache");

        this.timerManager = master.discoverTimerManager();

        // todo: go through persistent subscriptions and re-register statechange
        //       and destruction listeners with manager

        this.manager.recover_initialize();
    }

   
    // -------------------------------------------------------------------------
    // implements ResourceHome
    // -------------------------------------------------------------------------

    /**
     * The resource key type. The <code>ResourceKey</code> used or passed to
     * this <code>ResourceHome</code> must have match this type (corresponds to
     * {@link org.globus.wsrf.ResourceKey#getValue() ResourceKey.getValue()}).
     *
     * @return the type of the key.
     */
    public Class getKeyTypeClass() {
        return String.class;
    }

    /**
     * The name of the resource key. The <code>ResourceKey</code> used or passed
     * to this <code>ResourceHome</code> must have match this name (corresponds
     * to {@link org.globus.wsrf.ResourceKey#getName() ResourceKey.getName()}).
     *
     * @return the name of the key.
     */
    public QName getKeyTypeName() {
        return this.keyTypeName;
    }

    /**
     * Retrieves a resource. <b>Note:</b> This function must not return null. It
     * must return the resource object or throw an exception if there is no
     * resource with the specified key.
     *
     * @return non-null resource object.
     * @throws org.globus.wsrf.NoSuchResourceException
     *          if no resource exists with the given key
     * @throws org.globus.wsrf.InvalidResourceKeyException
     *          if the resource key is invalid.
     * @throws org.globus.wsrf.ResourceException
     *          if any other error occurs.
     */
    public Resource find(ResourceKey rkey) throws ResourceException,
                                                  NoSuchResourceException,
                                                  InvalidResourceKeyException {
       
        // #convertKey() validates as well
        final Integer key = this.convertKey(rkey);
        final String instanceid = key.toString();
       
        try {

            // There can be a race between this exists() check and the next
            // access of the manager+id (which is typically coming in a few
            // nanoseconds).  That is OK, the layer below is authoritative.
           
            if (!this.manager.exists(instanceid, Manager.INSTANCE)) {
                throw new NoSuchResourceException(
                        "unknown workspace: '" + instanceid + "'");
            }

            final Element el = this.cache.get(instanceid);
            final InstanceResource resource;
            if (el == null) {
                resource = new InstanceResource(instanceid,
                                                this.manager,
                                                this.secDescPath,
                                                this.translate,
                                                this,
                                                this.timerManager);
                resource.load(rkey);
                this.manager.registerDestructionListener(instanceid,
                                                         Manager.INSTANCE,
                                                         resource);
                this.cache.put(new Element(instanceid, resource));
            } else {
                resource = (InstanceResource) el.getObjectValue();
            }

            return resource;
           
        } catch (ConfigException e) {
            logger.error(e.getMessage(), e);
            throw new ResourceException(e.getMessage(), e);
        } catch (ManageException e) {
            logger.error(e.getMessage(), e);
            throw new ResourceException(e.getMessage(), e);
        } catch (DoesNotExistException e) {
            throw new NoSuchResourceException(e.getMessage(), e);
        } catch (NoSuchResourceException e) {
            throw e;
        } catch (Throwable t) {
            logger.error(t.getMessage(), t);
            throw new ResourceException(t.getMessage(), t);
        }
    }

    /**
     * Converts from ResourceKey to Integer, and validates in the process.
     *
     * @param key key in ResourceKey form
     * @return key in Integer form
     * @throws InvalidResourceKeyException missing/invalid
     */
    public Integer convertKey(ResourceKey key) throws InvalidResourceKeyException {

        if (key == null) {
            throw new InvalidResourceKeyException("resource key is missing");
        }

        if (!this.keyTypeName.equals(key.getName())) {
            throw new InvalidResourceKeyException("key is wrong QName, " +
                    "must be '" + this.keyTypeName.toString() + "'");
        }

        try {
            return new Integer((String) key.getValue());
        } catch (NumberFormatException e) {
            throw new InvalidResourceKeyException(
                    "key value is not integer based");
        }
    }

    /**
     * Removes a resource. If the resource implements the {@link
     * org.globus.wsrf.RemoveCallback RemoveCallback} interface, the
     * implementation must invoke the remove operation on the resource.
     *
     * Since the underlying implementation keeps track of destruction tasks
     * etc and not anything in this messaging layer, we can assume this is
     * from a WSRF destroy operation invoked by some client.
     *
     *
     * @throws org.globus.wsrf.NoSuchResourceException
     *          if no resource exists with the given key
     * @throws org.globus.wsrf.InvalidResourceKeyException
     *          if the resource key is invalid.
     * @throws org.globus.wsrf.RemoveNotSupportedException
     *          if remove operation is not supported.
     * @throws org.globus.wsrf.ResourceException
     *          if any other error occurs.
     */
    public void remove(ResourceKey key) throws ResourceException,
                                               NoSuchResourceException,
                                               InvalidResourceKeyException,
                                               RemoveNotSupportedException {

        // WARNING: RemoveCallback assumed, OK because this class controls the
        //          implementation choice currently
        ((RemoveCallback) this.find(key)).remove();
    }

   
    // -------------------------------------------------------------------------
    // DESTROYED
    // -------------------------------------------------------------------------

    /**
     * The authorative layer is saying the instance is gone, this is our
     * opportunity to send termination notifications if necessary.
     *
     * @param resource resource instance
     */
    public void destroyedNotification(InstanceResource resource) {

        if (resource == null) {
            throw new IllegalArgumentException("resource may not be null");
        }
       
        SetTerminationTimeProvider.sendTerminationNotification(resource);

        // Cache access is not locked, that's fine if there is a race between
        // something finding the instance right now and it being removed right
        // now. The layer below will throw DoesNotExistException for incorrect
        // accesses (if it's coded correctly), this message bridge is just the
        // final leg in getting a message to the authoritative manager impl.
       
        this.cache.remove(resource.getID());

        // Note that RemoveCallback.remove() is not called here, that method
        // is really just a way to receive the manually called WSRF terminate
        // from a remote client -- it translates into manager.trash().  This
        // method being called is the manager saying it's gone already, no
        // need to call trash().
    }
}
TOP

Related Classes of org.nimbustools.messaging.gt4_0.service.InstanceHome

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.