Package org.syrup.sql

Source Code of org.syrup.sql.GenericFunctions

package org.syrup.sql;

import org.syrup.Context;
import org.syrup.Data;
import org.syrup.LogEntry;
import org.syrup.LogEntryTemplate;
import org.syrup.PTask;
import org.syrup.PTaskTemplate;
import org.syrup.helpers.EndPoint;

import java.io.InputStream;
import java.net.URL;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;

/**
* Utility to implement generic WorkSpace functions using JDBC.
*
* @author Robbert van Dalen
*/
public class GenericFunctions extends Functions
{
    static final String COPYRIGHT = "Copyright 2005 Robbert van Dalen."
        + "At your option, you may copy, distribute, or make derivative works under "
        + "the terms of The Artistic License. This License may be found at "
        + "http://www.opensource.org/licenses/artistic-license.php. "
        + "THERE IS NO WARRANTY; USE THIS PRODUCT AT YOUR OWN RISK.";

    private final static Logger logger = Logger.getLogger("org.syrup.sql.GenericFunctions");

    /**
     * Constructor for the GenericFunctions object
     *
     * @param sqlImpl
     *            The SQLImpl that is held by the Function instance.
     */
    public GenericFunctions(SQLImpl sqlImpl)
    {
        super(sqlImpl);
    }

    /**
     * Sets the first input by executing SQL statements over a Connection..
     *
     * @param data
     *            The Data that is set on the first input.
     * @param con
     *            The SyrupConnection over which SQL statements are executed
     */

    public void set_in_1(Data data, SyrupConnection con) throws Exception
    {
        try
        {
            EndPoint p = sqlImpl().queryFunctions().readOutEndPoint("1", false, con);
            if (p.data != null)
            {
                throw new Exception("in1 is filled");
            }
            sqlImpl().updateFunctions().updateOutLink("1", false, data, con);
            sqlImpl().loggingFunctions().log("1", LogEntry.EVENT
                | LogEntry.IN_1, con);
            sqlImpl().updateFunctions().checkAndUpdateDone("1", con);
            con.commit();
        }
        finally
        {
            con.rollback();
        }
    }

    /**
     * Sets the second input by executing SQL statements over a Connection..
     *
     * @param data
     *            The Data that is set on the second input.
     * @param con
     *            The SyrupConnection over which SQL statements are executed
     */
    public void set_in_2(Data data, SyrupConnection con) throws Exception
    {
        try
        {
            EndPoint p = sqlImpl().queryFunctions().readOutEndPoint("1", true, con);
            if (p.data != null)
            {
                throw new Exception("in2 is filled");
            }
            sqlImpl().updateFunctions().updateOutLink("1", true, data, con);
            sqlImpl().loggingFunctions().log("1", LogEntry.EVENT
                | LogEntry.IN_2, con);
            sqlImpl().updateFunctions().checkAndUpdateDone("1", con);
            con.commit();
        }
        finally
        {
            con.rollback();
        }
    }

    /**
     * Returns the first output by executing SQL statements over a Connection..
     *
     * @param con
     *            The SyrupConnection over which SQL statements are executed
     * @return The Data removed from the first output.
     */
    public Data get_out_1(SyrupConnection con) throws Exception
    {
        try
        {
            EndPoint p = sqlImpl().queryFunctions().readInEndPoint("1", false, con);
            if (p.data != null)
            {
                sqlImpl().updateFunctions().updateInLink("1", false, null, con);
                sqlImpl().loggingFunctions().log("1", LogEntry.EVENT
                    | LogEntry.OUT_1, con);
                sqlImpl().updateFunctions().checkAndUpdateDone("1", con);
                con.commit();
                return p.data;
            }
            else
            {
                throw new Exception("out1 is empty");
            }
        }
        finally
        {
            con.rollback();
        }
    }

    /**
     * Returns the second output by executing SQL statements over a Connection..
     *
     * @param con
     *            The SyrupConnection over which SQL statements are executed
     * @return The Data removed from the second output.
     */
    public Data get_out_2(SyrupConnection con) throws Exception
    {
        try
        {
            EndPoint p = sqlImpl().queryFunctions().readInEndPoint("1", true, con);
            if (p.data != null)
            {
                sqlImpl().updateFunctions().updateInLink("1", true, null, con);
                sqlImpl().loggingFunctions().log("1", LogEntry.EVENT
                    | LogEntry.OUT_2, con);
                sqlImpl().updateFunctions().checkAndUpdateDone("1", con);
                con.commit();
                return p.data;
            }
            else
            {
                throw new Exception("out2 is empty");
            }
        }
        finally
        {
            con.rollback();
        }
    }

    /**
     * Get PTasks matching the PTaskTemplate.
     *
     * @param template
     *            The PTaskTemplate to be matched.
     * @param con
     *            The SyrupConnection over which SQL statements are executed
     * @return An array of PTasks that match the PTaskTemplate.
     */
    public PTask[] match(PTaskTemplate template, SyrupConnection con)
        throws Exception
    {
        PTask p[] = new PTask[0];
        String qq = null;

        List qParts = new LinkedList();

        // Add all the qualifiers, mapping from PTaskTemplate attributes to SQL
        // attributes.
        qParts.add(new QueryOperation(template, "description", "description"));
        qParts.add(new QueryOperation(template, "name", "name"));
        qParts.add(new QueryOperation(template, "function_class", "functionClass"));
        qParts.add(new QueryOperation(template, "environment", "environment"));
        qParts.add(new QueryOperation(template, "parameter", "parameter"));
        qParts.add(new QueryOperation(template, "or_type", "orType"));
        qParts.add(new QueryOperation(template, "parent_key", "parentKey"));
        qParts.add(new QueryOperation(template, "key_", "key"));
        qParts.add(new QueryOperation(template, "modifications", "modifications"));
        qParts.add(new QueryOperation(template, "modification_time", "modificationTime"));
        qParts.add(new QueryOperation(template, "creation_time", "creationTime"));
        qParts.add(new QueryOperation(template, "executable", "executable"));
        qParts.add(new QueryOperation(template, "done", "done"));
        qParts.add(new QueryOperation(template, "worker", "worker"));
        qParts.add(new QueryOperation(template, "is_parent", "isParent"));

        // Builds the SQL query.
        // [TODO: use an StringBuffer to speed up the concatenation of Strings].
        Iterator qIterator = qParts.iterator();
        while (qIterator.hasNext())
        {
            QueryOperation op = (QueryOperation) qIterator.next();
            if (op.sqlOp != null)
            {
                if (qq != null)
                {
                    qq = qq
                        + " and ";
                }
                else
                {
                    qq = " ";
                }
                qq = qq
                    + op.sqlAtt + " " + op.sqlOp + " ?";
            }
        }

        if (qq == null)
        {
            qq = sqlImpl().sqlStatements().selectTasksStatement();
        }
        else
        {
            qq = sqlImpl().sqlStatements().selectTasksStatement()
                + "where" + qq;
        }

        PreparedStatement ps = null;

    
            ps = con.prepareStatement(qq);
          
           
            qIterator = qParts.iterator();
            int ii = 1;

            while (qIterator.hasNext())
            {
                QueryOperation op = (QueryOperation) qIterator.next();

                // For each qualifier, the SQL value is set.
                if (op.sqlOp != null)
                {
                    ps.setObject(ii++, op.value);
                }
            }

            ResultSet result = null;
               
            try
            {  
            result = ps.executeQuery();

            // Build the result array
            // [TODO: Make this more efficient without the need of an extra
            // ArrayList object]
            ArrayList ptasks = new ArrayList();
            while (result.next())
            {
                PTask t = sqlImpl().queryFunctions().readPTask(result);
                ptasks.add(t);
            }

            p = new PTask[ptasks.size()];
            Object[] o = ptasks.toArray();

            for (int i = 0; i < o.length; i++)
            {
                p[i] = (PTask) o[i];
            }
        }
        finally
        {
            close(result);
        }
        return p;
    }

    /**
     * Get LogEntries matching the LogEntryTemplate.
     *
     * @param template
     *            The LogEntryTemplate to be matched.
     * @param con
     *            The SyrupConnection over which SQL statements are executed
     * @return An array of LogEntries that match the LogEntryTemplate.
     */
   
    public LogEntry[] match(LogEntryTemplate template, SyrupConnection con)
    throws Exception
{
    LogEntry l[] = new LogEntry[0];
    String qq = null;

    List qParts = new LinkedList();

    // Add all the qualifiers, mapping from LogEntry attributes to SQL
    // attributes.
    qParts.add(new QueryOperation(template, "creation_time", "time"));
    qParts.add(new QueryOperation(template, "key_", "key"));
    qParts.add(new QueryOperation(template, "event", "event"));
    qParts.add(new QueryOperation(template, "worker", "worker"));

    // Builds the SQL query.
    // [TODO: use an StringBuffer to speed up the concatenation of Strings].
    // [TODO: factor out this code so that it can be share by the previous match function]
    Iterator qIterator = qParts.iterator();
    while (qIterator.hasNext())
    {
        QueryOperation op = (QueryOperation) qIterator.next();
        if (op.sqlOp != null)
        {
            if (qq != null)
            {
                qq = qq
                    + " and ";
            }
            else
            {
                qq = " ";
            }
            qq = qq
                + op.sqlAtt + " " + op.sqlOp + " ?";
        }
    }

    if (qq == null)
    {
        qq = sqlImpl().sqlStatements().selectLogEntriesStatement();
    }
    else
    {
        qq = sqlImpl().sqlStatements().selectLogEntriesStatement()
            + "where" + qq;
    }

    PreparedStatement ps = null;

        ps = con.prepareStatement(qq);

        qIterator = qParts.iterator();
        int ii = 1;

        while (qIterator.hasNext())
        {
            QueryOperation op = (QueryOperation) qIterator.next();

            // For each qualifier, the SQL value is set.
            if (op.sqlOp != null)
            {
                ps.setObject(ii++, op.value);
            }
        }

        ResultSet result = null;
       
        try
        {
        result = ps.executeQuery();

        // Build the result array
        // [TODO: Make this more efficient without the need of an extra
        // ArrayList object]
        ArrayList logs = new ArrayList();
        while (result.next())
        {
            LogEntry t = sqlImpl().queryFunctions().readLogEntry(result);
            logs.add(t);
        }

        l = new LogEntry[logs.size()];
        Object[] o = logs.toArray();

        for (int i = 0; i < o.length; i++)
        {
            l[i] = (LogEntry) o[i];
        }
    }
    finally
    {
        close(result);
    }
    return l;
}

   
    /**
     * Get the Contexts of PTasks that match the PTaskTemplate.
     *
     * @param t
     *            The PTaskTemplate to be matched.
     * @param con
     *            The SyrupConnection over which SQL statements are executed
     * @return An array of Contexts surrounding the PTasks that match the
     *         PTaskTemplate.
     */

    public Context[] get(PTaskTemplate t, SyrupConnection con) throws Exception
    {
        PTask[] tasks = match(t, con);
        Context[] c = new Context[tasks.length];

        // [TODO: make the query more direct, so that the query returns Contexts
        // directly instead of PTasks].
        for (int i = 0; i < tasks.length; i++)
        {
            c[i] = sqlImpl().queryFunctions().readContext(tasks[i], con);
        }
        return c;
    }

    /**
     * Resets the WorkSpace to the initial state.
     *
     * @param con
     *            The SyrupConnection over which SQL statements are executed
     */
    public void reset(SyrupConnection con) throws Exception
    {
        sqlImpl().creationFunctions().reset(con);
        sqlImpl().creationFunctions().createTables(con);
    }

    /**
     * Stop non-progressing executions of a PTask.
     *
     * @param task
     *            The PTask to be stopped.
     * @param con
     *            The SyrupConnection over which SQL statements are executed
     * @return The stopped PTask.
     */
    public PTask stop(PTask task, SyrupConnection con) throws Exception
    {
        PreparedStatement s = null;
        ResultSet result = null;
       
        try
        {
            s = con.prepareStatementFromCache(sqlImpl().sqlStatements().checkWorkerStatement());
            s.setString(1, task.key());
            result = s.executeQuery();

            // Commit now, so to not unnecessary hold a read-lock
            // This because resolving URLs can take > 1 seconds
            // (avoiding RDMS write/read deadlocks)
            //
            con.commit();

            if (result.next())
            {
                String url = result.getString("worker");
                InputStream i = null;

                try
                {
                    Object b = new URL(url).getContent();
                    if (b instanceof InputStream)
                    {
                        i = (InputStream) b;
                        byte[] bb = new byte[256];
                        int ll = i.read(bb);
                        String k = new String(bb, 0, ll);

                        // The Worker returns the correct Task key under the
                        // address that is known by the Workspace.
                        if (k.equals(task.key()))
                        {
                            // everything OK. PTask not stopped.
                            return task;
                        }
                    }
                }
                catch (Exception e)
                {
                    // The Worker is not reachable under the address that is
                    // known by the WorkSpace.
                }
                finally
                {
                    if (i != null)
                    {
                        i.close();
                    }
                }

                PreparedStatement s2 = null;
                    // The address is set to null, so the PTask is effectively
                    // stopped executing. Other Workers can now have a try.
                    s2 = con.prepareStatementFromCache(sqlImpl().sqlStatements().resetWorkerStatement());
                    s2.setString(1, task.key());
                    s2.executeUpdate();

                    task = sqlImpl().queryFunctions().readPTask(task.key(), con);
                    sqlImpl().loggingFunctions().log(task.key(), LogEntry.STOPPED, con);
                    con.commit();

            }
        }
        finally
        {
            con.rollback();
            close(result);
        }
        return task;
    }

    /**
     * Utility method that closes the Connection.
     *
     * @param con
     *            The SyrupConnection to be closed.
     */
    public final void close(SyrupConnection con) throws Exception
    {
        if (con != null)
        {
            if (!con.isClosed())
            {
                con.rollback();
                con.close();
            }
        }
    }

    /**
     * Utility method that resets the ResultSet.
     *
     * @param result
     *            The ResultSet to be resetted.
     */
    public final void close(ResultSet result) throws Exception
    {
        if (result != null)
        {
            result.close();
        }
    }
}
TOP

Related Classes of org.syrup.sql.GenericFunctions

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.