Package org.apache.jetspeed.services.registry

Source Code of org.apache.jetspeed.services.registry.DatabaseRegistryService

/*
* Copyright 2000-2004 The Apache Software Foundation.
*
* 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.apache.jetspeed.services.registry;

// Java classes
import java.io.Reader;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.servlet.ServletConfig;

//turbine stuff
import org.apache.turbine.services.InitializationException;
import org.apache.turbine.services.TurbineBaseService;
import org.apache.turbine.services.TurbineServices;
import org.apache.turbine.services.resources.ResourceService;
import org.apache.turbine.services.servlet.ServletService;

// Jetspeed classes
import org.apache.jetspeed.om.registry.DBRegistry;
import org.apache.jetspeed.om.registry.Registry;
import org.apache.jetspeed.om.registry.RegistryEntry;
import org.apache.jetspeed.om.registry.RegistryException;
import org.apache.jetspeed.om.registry.base.BaseRegistry;
import org.apache.jetspeed.om.registry.base.LocalRegistry;
import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
import org.apache.jetspeed.services.logging.JetspeedLogger;

/**
* <p>This is an implementation of the <code>RegistryService</code>
* based on the Jetspeed Database Persistence Manager</p>
*
* @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
* @author <a href="mailto:susinha@cisco.com">Suchisubhra Sinha</a>
* @version $Id: DatabaseRegistryService.java,v 1.6 2004/02/23 03:31:50 jford Exp $
*/
public class DatabaseRegistryService
    extends TurbineBaseService
    implements RegistryService , FileRegistry
{
    private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(CastorRegistryService.class.getName());
       
    /** The name of this service */
    public static String SERVICE_NAME = "DatabaseRegistry";

    public static final int DEFAULT_VERBOSE = 1;

    /** regsitry type keyed list of entries */
    private Hashtable registries = new Hashtable();

    /** The list of default fragments stores for newly created objects */
    private Hashtable defaults = new Hashtable();

    /** The Castor generated RegsitryFragment objects */
    private Hashtable fragments = new Hashtable();

    /** Associates entries with their fragments name for quick lookup */
    private Hashtable entryIndex = new Hashtable();

    /** the Watcher object which monitors the regsitry directory */
    private DatabaseRegistryWatcher watcher = null;

    /** Assign  the default  poolname */
    private final static String POOL_NAME = "database";

   
    /** controls amount of debug output, the bigger the more output will be generated */
    private int verbose = DEFAULT_VERBOSE;

    /** Base class to implement  */
    private static Hashtable baseClass = new Hashtable();
   
    /**
     * Returns a Registry object for further manipulation
     *
     * @param regName the name of the registry to fetch
     * @return a Registry object if found by the manager or null
     */
    public Registry get(String regName)
    {
        return (Registry) registries.get(regName);
    }

    /**
     *  List all the registry currently available to this service
     *
     * @return an Enumeration of registry names.
     */
    public Enumeration getNames()
    {
        return registries.keys();
    }

    /**
     * Creates a new RegistryEntry instance compatible with the current
     * Registry instance implementation
     *
     * @param regName the name of the registry to use
     * @return the newly created RegistryEntry
     */
    public RegistryEntry createEntry(String regName)
    {
        RegistryEntry entry = null;
        Registry registry = (Registry) registries.get(regName);

        if (registry != null)
        {
            entry = registry.createEntry();
        }

        return entry;
    }

   
    /**
     * Returns a RegistryEntry from the named Registry.
     * This is a convenience wrapper around {@link
     * org.apache.jetspeed.om.registry.Registry#getEntry }
     *
     * @param regName the name of the registry
     * @param entryName the name of the entry to retrieve from the registry.
     * @return a RegistryEntry object if the key is found or null
     */
    public RegistryEntry getEntry(String regName, String entryName)
    {
        try
        {
            return ((Registry) registries.get(regName)).getEntry(entryName);
        }
        catch (RegistryException e)
        {
            if (logger.isInfoEnabled())
            {
                logger.info(
                    "RegistryService: Failed to retrieve "
                        + entryName
                        + " from "
                        + regName);
            }
        }
        catch (NullPointerException e)
        {
            logger.error(
                "DatabaseRegistryService: "
                    + regName
                    + " registry is not known ");
            logger.error(e);
        }

        return null;
    }
           
    /**
     * Add a new RegistryEntry in the named Registry.
     * This is a convenience wrapper around {@link
     * org.apache.jetspeed.om.registry.Registry#addEntry }
     *
     * @param regName the name of the registry
     * @param entry the Registry entry to add
     * @exception Sends a RegistryException if the manager can't add
     *            the provided entry
     */
    public void addEntry(String regName, RegistryEntry entry)
        throws RegistryException
    {
        if (entry == null)
        {
            return;
        }

        LocalRegistry registry = (LocalRegistry) registries.get(regName);

        if (registry != null)
        {
            String fragmentName = (String) entryIndex.get(entry.getName());

            if (fragmentName == null)
            {
                // either the entry was deleted or it does not exist
                // in both cases, use the default fragment
                fragmentName = (String) defaults.get(regName);
            }

            RegistryFragment fragment =
                (RegistryFragment) fragments.get(fragmentName);

            //Fragment can be (and sometimes is, but should not be) null
            if (fragment == null)
            {
                fragment = new RegistryFragment();
                fragment.put(regName, new Vector());
                fragments.put(fragmentName, fragment);
            }
            else
            {
                Vector vectRegistry = (Vector) fragment.get(regName);
                if (vectRegistry == null)
                {
                    fragment.put(regName, new Vector());
                }
            }

            synchronized (entryIndex)
            {
                if (registry.hasEntry(entry.getName()))
                {
                    fragment.setEntry(regName, entry);
                    registry.setLocalEntry(entry);
                }
                else
                {
                    fragment.addEntry(regName, entry);
                    registry.addLocalEntry(entry);
                }

                entryIndex.put(entry.getName(), fragmentName);
                // mark this fragment so that it's persisted next time
                // the registry watcher is running
                fragment.setDirty(true);
            }
        }
    }
   
   /**
    * Deletes a RegistryEntry from the named Registry
    * This is a convenience wrapper around {@link
    * org.apache.jetspeed.om.registry.Registry#removeEntry }
    *
    * @param regName the name of the registry
    * @param entryName the name of the entry to remove
    */
    public void removeEntry(String regName, String entryName)
    {
        if (entryName == null)
        {
            return;
        }

        LocalRegistry registry = (LocalRegistry) registries.get(regName);

        if (registry != null)
        {
            String fragmentName = (String) entryIndex.get(entryName);

            if (fragmentName != null)
            {
                RegistryFragment fragment =
                    (RegistryFragment) fragments.get(fragmentName);

                synchronized (entryIndex)
                {
                    fragment.removeEntry(regName, entryName);
                    entryIndex.remove(entryName);

                    // mark this fragment so that it's persisted next time
                    // the registry watcher is running
                    fragment.setDirty(true);
                }
            }

            // the entry is physically removed, remove the dangling reference
            registry.removeLocalEntry(entryName);
        }
    }
   
    /**
     * This is the early initialization method called by the
     * Turbine <code>Service</code> framework
     */
    public synchronized void init(ServletConfig conf)
    throws InitializationException
    {
        int refreshRate = 0;
        Vector names = new Vector();
   
        //Ensure that the servlet service is initialized
        TurbineServices.getInstance().initService(ServletService.SERVICE_NAME, conf);

        ResourceService serviceConf =
            ((TurbineServices) TurbineServices.getInstance()).getResources(SERVICE_NAME);

        //build the map of default fragments, eahc registry must be associated
        //with at least one fragment
        try
        {           
            refreshRate = serviceConf.getInt("refreshRate", DEFAULT_REFRESH);
            ResourceService defaults = serviceConf.getResources("default");
            Iterator i = defaults.getKeys();

            while (i.hasNext())
            {
                String name = (String) i.next();
                // add this name in the list of available registries
               
                names.add(name);
                try
                {
                    String registryClass =
                        "org.apache.jetspeed.om.registry.database.BaseJetspeed"
                            + name
                            + "Peer";

                    baseClass.put(
                        name,
                        (DBRegistry) Class
                            .forName(registryClass)
                            .newInstance());
                }
                catch (Exception e)
                {
                    if (logger.isWarnEnabled())
                    {
                        logger.warn(
                            "DatabaseRegistryService: Class "
                                + name
                                + " not found");
                    }

                }

            }
        }
        catch (Throwable t)
        {
            throw new InitializationException("Unable to initialize DatabaseRegistryService, missing config keys");
        }
   
        this.watcher = new DatabaseRegistryWatcher();
        this.watcher.setSubscriber(this);

        if (refreshRate == 0)
        {
            this.watcher.setDone();
        }
        else
        {
            this.watcher.setRefreshRate(refreshRate);
        }
        // changing the base will trigger a synchronous loading of the fragments
        this.watcher.changeBase(names);

        //Mark that we are done
        setInit(true);

        // load the registries
        Enumeration en = names.elements();

        RegistryService localeService =
            (RegistryService) TurbineServices
                .getInstance()
                .getService(RegistryService.SERVICE_NAME);

        while (en.hasMoreElements())
        {
            String name = (String) en.nextElement();
            Registry registry = (Registry) registries.get(name);

            if (registry == null)
            {
                String registryClass = null;
                try
                {
                    registry = localeService.get(name);
                }
                catch (Exception e)
                {
                    if (logger.isWarnEnabled())
                    {
                        logger.warn(
                            "DatabaseRegistryService: Class "
                                + registryClass
                                + " not found, reverting to default Registry");
                    }
                    registry = new BaseRegistry();
                }
                registries.put(name, registry);
            }

            refresh(name);
        }
       
        // Start the directory watcher thread and rely on its refresh process
        // to completely load all registries
        if (this.watcher != null)
        {
            this.watcher.start();
        }

        if (logger.isDebugEnabled())
        {
            logger.debug(
                "DatabaseRegistryService: early init()....end!, this.getInit()= "
                    + getInit());
        }
    }
    /**
         * @return a Map of all fragments keyed by file names
         */
    public Map getFragmentMap()
    {
        return (Map) fragments.clone();
    }

    /** Late init method from Turbine Service model */
    public void init() throws InitializationException
    {
        if (logger.isDebugEnabled())
        {
            logger.debug("DatabaseRegistryService: Late init called");
        }
        while (!getInit())
        {
            //Not yet...
            try
            {
                Thread.sleep(500);
                if ((verbose > 2) && logger.isDebugEnabled())
                {
                    logger.debug(
                        "DatabaseRegistryService: Waiting for init of Registry...");
                }
            }
            catch (InterruptedException ie)
            {
                logger.error(ie);
            }
        }

        if (logger.isDebugEnabled())
        {
            logger.debug("DatabaseRegistryService: We are done");
        }
    }
   
    /**
     * This is the shutdown method called by the
     * Turbine <code>Service</code> framework
     */
    public void shutdown()
    {
        this.watcher.setDone();

        Iterator i = fragments.keySet().iterator();
        while (i.hasNext())
        {
            saveFragment((String) i.next());
        }
    }

    /**
     * Scan all the registry fragments for new entries relevant to
     * this registry and update its definition.
     *
     * @param regName the name of the Registry to refresh
     */
    protected void refresh(String regName)
    {
        if (logger.isDebugEnabled())
        {
            logger.debug(
                "DatabaseRegistryService: Updating the "
                    + regName
                    + " registry");
        }

        int count = 0;
        int counDeleted = 0;
        LocalRegistry registry = (LocalRegistry) get(regName);

        Vector toDelete = new Vector();
        Iterator i = registry.listEntryNames();

        while (i.hasNext())
        {
            toDelete.add(i.next());
        }

        if (registry == null)
        {
            logger.error(
                "DatabaseRegistryService: Null "
                    + name
                    + " registry in refresh");
            return;
        }

        // for each fragment...
        Enumeration en = fragments.keys();
        while (en.hasMoreElements())
        {
            String location = (String) en.nextElement();
            RegistryFragment fragment =
                (RegistryFragment) fragments.get(location);
            int fragCount = 0;

            if (!fragment.hasChanged())
            {
                if ((verbose > 2) && logger.isDebugEnabled())
                {
                    logger.debug(
                        "DatabaseRegistryService: Skipping fragment "
                            + location);
                }

                //remove this fragment entries from the delete list
                Vector entries = fragment.getEntries(regName);
                i = entries.iterator();
                while (i.hasNext())
                {
                    toDelete.remove(((RegistryEntry) i.next()).getName());
                }
                continue;
            }

            //the fragment has some changes, iterate over its entries...
            Vector entries = fragment.getEntries(regName);
            //... if it has entries related to this regsistry,
            if (entries != null)
            {
                // for all these entries
                Enumeration en2 = entries.elements();
                while (en2.hasMoreElements())
                {
                    RegistryEntry entry = (RegistryEntry) en2.nextElement();
                    // update or add the entry in the registry
                    try
                    {
                        if (registry.hasEntry(entry.getName()))
                        {
                            if (registry
                                .getEntry(entry.getName())
                                .equals(entry))
                            {
                                if ((verbose > 2)
                                    && logger.isDebugEnabled())
                                {
                                    logger.debug(
                                        "DatabaseRegistryService: No changes to entry "
                                            + entry.getName());
                                }
                            }
                            else
                            {
                                if ((verbose > 1)
                                    && logger.isDebugEnabled())
                                {
                                    logger.debug(
                                        "DatabaseRegistryService: Updating entry "
                                            + entry.getName()
                                            + " of class "
                                            + entry.getClass()
                                            + " to registry "
                                            + name);
                                }
                                registry.setLocalEntry(entry);
                                // Initialize the entry index
                                this.entryIndex.put(entry.getName(), location);
                                ++fragCount;
                            }
                        }
                        else
                        {
                            registry.addLocalEntry(entry);
                            // Initialize the entry index
                            this.entryIndex.put(entry.getName(), location);
                            ++fragCount;

                            if ((verbose > 1)
                                && logger.isDebugEnabled())
                            {
                                logger.debug(
                                    "DatabaseRegistryService: Adding entry "
                                        + entry.getName()
                                        + " of class "
                                        + entry.getClass()
                                        + " to registry "
                                        + name);
                            }
                        }
                    }
                    catch (RegistryException e)
                    {
                        logger.error(
                            "DatabaseRegistryService: RegistryException while adding "
                                + entry.getName()
                                + "from "
                                + location,
                            e);
                    }
                    //remove this entry from the delete list
                    toDelete.remove(entry.getName());
                }
            }

            count += fragCount;
        }

        //now delete the entries not found in any fragment
        i = toDelete.iterator();
        while (i.hasNext())
        {
            String entryName = (String) i.next();

            if ((verbose > 1) && logger.isDebugEnabled())
            {
                logger.debug(
                    "DatabaseRegistryService: removing entry " + entryName);
            }
            //TODO may  be I will  do it later
            //it should  delete only portlets which  is coming from  database
           
            //registry.removeLocalEntry(entryName);
        }

        if ((verbose > 1) && logger.isDebugEnabled())
        {
            logger.debug(
                "DatabaseRegistryService: Merged "
                    + count
                    + " entries and deleted "
                    + toDelete.size()
                    + " in "
                    + name);
        }
    }

    // FileRegistry interface

    /** Refresh the state of the registry implementation. Should be called
     *   whenever the underlying fragments are modified
     */
    public void refresh()
    {
        synchronized (watcher)
        {
            Enumeration en = getNames();
            while (en.hasMoreElements())
            {
                refresh((String) en.nextElement());
            }
        }
    }

    /**
        * Load and unmarshal a RegistryFragment from the file
        * @param file the absolute file path storing this fragment
        */
    public void loadFragment(String file )
    {
        try
        {           
            RegistryFragment fragment = createFragment(file);
            //mark this fragment as changed
            fragment.setChanged(true);

            // if we get here, we successfully loaded the new fragment
            updateFragment(file, fragment);

        }
        catch (Throwable t)
        {
            logger.error(
                "DatabaseRegistryService: Could not unmarshal: " + file,
                t);
        }
    }

    /**
        * Read and unmarshal a fragment in memory
        * @param name the name of this fragment
        * @param persistent whether this fragment should be persisted on disk in
        * the registry
        */
    public void createFragment(
        String name,
        Reader reader,
        boolean persistent)
    {
        String file = null;

        try
        {
        }
        catch (Throwable t)
        {
            logger.error(
                "DatabaseRegistryService: Could not create fragment: " + file, t);
        }
        finally
        {
            try
            {
                reader.close();
            }
            catch (Exception e)
            {
                logger.error(e); // At least log the exception.
            }
        }
    }
    /**
     * Marshal and save a RegistryFragment to disk
     * @param file the absolute file path storing this fragment
     */
    public void saveFragment(String file)
    {

        /**
         * TODO I will  implement this
         * should go  to  database
         */

    }
    /**
     * Remove a fragment from storage
     * @param file the absolute file path storing this fragment
     */
    public void removeFragment(String file)
    {
        RegistryFragment fragment = (RegistryFragment) fragments.get(file);

        if (fragment != null)
        {
            synchronized (entryIndex)
            {
                // clear the entry index
                Iterator i = entryIndex.keySet().iterator();
                while (i.hasNext())
                {
                    if (file.equals(entryIndex.get(i.next())))
                    {
                        i.remove();
                    }
                }

                // make sure the keys & entries are freed for this fragment
                // only the entries not replaced by the next registry refresh will
                // stay in memory
                fragment.clear();
                // remove the actual fragment from memory
                fragments.remove(file);
            }
        }
    }
   
    /**
     * Updates a fragment in storage and the associated entryIndex
     */
    protected void updateFragment(String name, RegistryFragment fragment)
    {
        synchronized (entryIndex)
        {
            // remove the old keys
            Iterator i = entryIndex.keySet().iterator();
            while (i.hasNext())
            {
                if (name.equals(entryIndex.get(i.next())))
                {
                    i.remove();
                }
            }
            // store the new fragment
            fragments.put(name, fragment);

            // recreate the index entries (only this fragment)

            Enumeration enum = fragment.keys();
            while (enum.hasMoreElements())
            {
                String strReg = (String) enum.nextElement();
                Vector v = fragment.getEntries(strReg);
                for (int counter = 0; counter < v.size(); counter++)
                {
                    RegistryEntry str = (RegistryEntry) v.elementAt(counter);
                    entryIndex.put(str.getName(), name);
                }
            }
        }
    }

    //class  specific implementation
    private static List getData(String name)
    {
        List list = null;
        try
        {       
            DBRegistry BaseClass = (DBRegistry) baseClass.get(name);
            if (BaseClass != null)
            {
                list = BaseClass.getXREGDataFromDb();
            }
            else
            {
                logger.warn(
                    "DatabaseRegistryService: Base class  for service " + name + " not found");
            }
        }
        catch (Exception ex)
        {
            logger.warn(
                "DatabaseRegistryService: Base class  for service " + name + " not found");
        }
        return list;
    }
   
    private RegistryFragment createFragment(String regName)
    {
        RegistryFragment fragment = (RegistryFragment) fragments.get(regName);

        //Fragment can be (and sometimes is, but should not be) null
        if (fragment == null)
        {
            fragment = new RegistryFragment();
            fragment.put(regName, new Vector());
        }
        else
        {
            Vector vectRegistry = (Vector) fragment.get(regName);
            if (vectRegistry == null)
            {
                fragment.put(regName, new Vector());
            }
        }
        List entries = getData(regName);
        if (entries != null)
        {
            for (int i = 0; i < entries.size(); i++)
            {
                fragment.setEntry(regName, (RegistryEntry) entries.get(i));
                // mark this fragment so that it's persisted next time
                // the registry watcher is running
                fragment.setDirty(true);
            }
        }
        else
        {           
            logger.warn(
                "DatabaseRegistryService:no data fouund for service " + name );

        }
        return fragment;

    }
}
TOP

Related Classes of org.apache.jetspeed.services.registry.DatabaseRegistryService

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.