Package org.apache.cocoon.acting

Source Code of org.apache.cocoon.acting.OraAddAction

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.cocoon.acting;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import oracle.jdbc.OracleResultSet;
import oracle.sql.BLOB;
import oracle.sql.CLOB;

import org.apache.avalon.excalibur.datasource.DataSourceComponent;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Redirector;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.util.ImageProperties;
import org.apache.cocoon.util.ImageUtils;

/**
* Add a record in a database.  This Action assumes that there is
* only one table at a time to update.
*
* @version $Id: OraAddAction.java 591580 2007-11-03 10:47:48Z felixk $
*/
public class OraAddAction extends DatabaseAddAction {
    private static final Map selectLOBStatements = new HashMap();

    /**
     * Add a record to the database.  This action assumes that
     * the file referenced by the "descriptor" parameter conforms
     * to the AbstractDatabaseAction specifications.
     */
    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters param) throws Exception {
        DataSourceComponent datasource = null;
        Connection conn = null;
        int currentIndex = 0;

        try {
            Configuration conf = this.getConfiguration(param.getParameter("descriptor", null));
            String query = this.getAddQuery(conf);

            datasource = this.getDataSource(conf);
            conn = datasource.getConnection();
            Request request = ObjectModelHelper.getRequest(objectModel);

            if (conn.getAutoCommit()) {
                conn.setAutoCommit(false);
            }

            PreparedStatement statement = conn.prepareStatement(query);
            getLogger().info(query);

            Configuration[] keys = conf.getChild("table").getChild("keys").getChildren("key");
            Configuration[] values = conf.getChild("table").getChild("values").getChildren("value");
            currentIndex = 1;

            // Insert the keys into the query
            for (int i = 0; i < keys.length; i++) {
                String mode = keys[i].getAttribute("mode", "automatic");

                if ("manual".equals(mode)) {
                    String selectQuery = this.getSelectQuery(keys[i]);

                    final Statement stmnt = conn.createStatement();
                    final ResultSet set = stmnt.executeQuery(selectQuery);
                    try {
                        set.next();
                        int value = set.getInt("maxid") + 1;

                        statement.setInt(currentIndex, value);

                        request.setAttribute(keys[i].getAttribute("param"), String.valueOf(value));

                        set.getStatement().close();
                        set.close();
                        currentIndex++;
                    } finally {
                        stmnt.close();
                    }
                } else if ("form".equals(mode)) {
                    String parameter = keys[i].getAttribute("param");
                    request.setAttribute(parameter, request.getParameter(parameter));
                    this.setColumn(statement, currentIndex, request, keys[i]);
                    currentIndex++;
                }
            }

            // insert the values into the query
            for (int i = 0; i < values.length; i++) {
                String type = values[i].getAttribute("type");
                String parameter = values[i].getAttribute("param");

                if (type.equals("image")) {
                    File binaryFile = (File) request.get(parameter);
                    Parameters iparam = new Parameters();

                    iparam.setParameter("image-size", String.valueOf(binaryFile.length()));

                    ImageProperties prop = ImageUtils.getImageProperties(binaryFile);
                    iparam.setParameter("image-width", Integer.toString(prop.width));
                    iparam.setParameter("image-height", Integer.toString(prop.height));

                    synchronized (this.files) {
                        this.files.put(binaryFile, param);
                    }
                }

                if (! this.isLargeObject(type)) {
                    this.setColumn(statement, currentIndex, request, values[i]);
                    currentIndex++;
                }
            }

            statement.execute();
            statement.close();

            query = this.getSelectLOBQuery(conf);

            // Process the large objects if they exist
            if (query != null) {
                PreparedStatement LOBstatement = conn.prepareStatement(query);
                getLogger().info(query);

                if (keys.length > 0) {
                    currentIndex = 1;

                    for (int i = 0; i < keys.length; i++) {
                        this.setColumn(LOBstatement, currentIndex, request, keys[i]);
                        currentIndex++;
                    }
                }

                OracleResultSet set = (OracleResultSet) LOBstatement.executeQuery();

                if (set.next()) {
                    int index = 0;

                    for (int i = 0; i < values.length; i++) {
                        String type = values[i].getAttribute("type", "");
                        if (this.isLargeObject(type)) {
                            Object attr = request.get(values[i].getAttribute("param"));
                            int length = -1;
                            InputStream stream = null;
                            OutputStream output = null;
                            int bufSize = 1024;

                            index++;

                            if (type.equals("ascii")) {
                                CLOB ascii = set.getCLOB(index);

                                if (attr instanceof File) {
                                    File asciiFile = (File) attr;
                                    stream = new BufferedInputStream(new FileInputStream(asciiFile));
                                } else {
                                    String asciiText = (String) attr;
                                    stream = new BufferedInputStream(new ByteArrayInputStream(asciiText.getBytes()));
                                }

                                output = new BufferedOutputStream(ascii.getAsciiOutputStream());
                                bufSize = ascii.getBufferSize();
                            } else {
                                BLOB binary = set.getBLOB(index);
                                File binaryFile = (File) attr;
                                stream = new BufferedInputStream(new FileInputStream(binaryFile));
                                length = (int) binaryFile.length();

                                output = new BufferedOutputStream(binary.getBinaryOutputStream());
                                bufSize = binary.getBufferSize();
                            }

                            byte[] buffer = new byte[bufSize];
                            while ((length = stream.read(buffer)) != -1) {
                                output.write(buffer, 0, length);
                            }

                            stream.close();
                            output.close();
                        }
                    }
                }

                set.close();
                set.getStatement().close();
            }

            conn.commit();
        } catch (Exception e) {
            if (conn != null) {
                try {
                    conn.rollback();
                } catch (SQLException se) {
                    getLogger().debug("There was an error rolling back the transaction", se);
                }
            }

            throw new ProcessingException("Could not add record :position = " + (currentIndex - 1), e);
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException sqe) {
                    getLogger().warn("There was an error closing the datasource", sqe);
                }
            }

            if (datasource != null) this.dbselector.release(datasource);
        }

        return null;
    }

    /**
     * Get the String representation of the PreparedStatement.  This is
     * mapped to the Configuration object itself, so if it doesn't exist,
     * it will be created.
     */
    protected final String getAddQuery(Configuration conf) throws ConfigurationException {
        String query = null;

        synchronized (DatabaseAddAction.addStatements) {
            query = (String) DatabaseAddAction.addStatements.get(conf);

            if (query == null) {
                Configuration table = conf.getChild("table");
                Configuration[] values = table.getChild("values").getChildren("value");
                Configuration[] keys = table.getChild("keys").getChildren("key");

                StringBuffer queryBuffer = new StringBuffer("INSERT INTO ");
                queryBuffer.append(table.getAttribute("name"));
                queryBuffer.append(" (");

                int numKeys = 0;

                for (int i = 0; i < keys.length; i++) {
                    String mode = keys[i].getAttribute("mode", "automatic");
                    if (numKeys > 0) {
                        queryBuffer.append(", ");
                    }

                    queryBuffer.append(keys[i].getAttribute("dbcol"));

                    if ("manual".equals(mode)) {
                        this.setSelectQuery(table.getAttribute("name"), keys[i]);
                    }

                    numKeys++;
                }

                for (int i = 0; i < values.length; i++) {
                    if ((numKeys + i) > 0) {
                        queryBuffer.append(", ");
                    }

                    queryBuffer.append(values[i].getAttribute("dbcol"));
                }

                queryBuffer.append(") VALUES (");

                numKeys = 0;
                ArrayList sequences = new ArrayList();

                for (int i = 0; i < keys.length; i++) {
                    if (numKeys > 0) queryBuffer.append(", ");
                    if ("automatic".equals(keys[i].getAttribute("mode", "automatic"))) {
                        String sequence = keys[i].getAttribute("sequence", "");
                        queryBuffer.append(sequence);

                        if (sequences.contains(sequence)) {
                            queryBuffer.append(".CURRVAL");
                        } else {
                            sequences.add(sequence);
                            queryBuffer.append(".NEXTVAL");
                        }

                        numKeys++;
                    } else {
                        queryBuffer.append("?");
                        numKeys++;
                    }
                }

                for (int i = 0; i < values.length; i++) {
                    if ((numKeys + i) > 0) {
                        queryBuffer.append(", ");
                    }

                    if (this.isLargeObject(values[i].getAttribute("type"))) {
                        if (values[i].getAttribute("type").equals("ascii")) {
                             queryBuffer.append("empty_clob()");
                        } else {
                             queryBuffer.append("empty_blob()");
                        }
                    } else {
                        queryBuffer.append("?");
                    }
                }

                queryBuffer.append(")");

                query = queryBuffer.toString();

                DatabaseAddAction.addStatements.put(conf, query);
            }
        }

        if ("".equals(query)) return null;

        return query;
    }

    /**
     * Get the String representation of the PreparedStatement.  This is
     * mapped to the Configuration object itself, so if it doesn't exist,
     * it will be created.
     */
    private final String getSelectLOBQuery (Configuration conf)
    throws ConfigurationException {
        String query = null;

        synchronized (OraAddAction.selectLOBStatements) {
            query = (String) OraAddAction.selectLOBStatements.get(conf);

            // executes only if query is null.
            if (query == null) {
                StringBuffer queryBuffer = new StringBuffer("SELECT ");
                Configuration table = conf.getChild("table");
                Configuration[] values = table.getChild("values").getChildren("value");
                Configuration[] keys = table.getChild("keys").getChildren("key");
                int numLobs = 0;

                // Add the values to the query
                for (int i = 0; i < values.length; i++) {
                    if (this.isLargeObject(values[i].getAttribute("type"))) {
                        numLobs++;
                        if (numLobs > 1) {
                            queryBuffer.append(", ");
                        }
                        queryBuffer.append(values[i].getAttribute("dbcol"));
                    }
                }

                if (numLobs < 1) {
                    // if query is set to "", then the Action won't
                    // try to process it again.
                    query = "";
                    OraAddAction.selectLOBStatements.put(conf, query);
                    return null;
                }

                queryBuffer.append(" FROM ").append(table.getAttribute("name"));

                // Process the WHERE clause
                if (keys.length > 0) {
                    queryBuffer.append(" WHERE ");
                    // Add the keys to the query
                    queryBuffer.append(buildList(keys, " AND "));
                }
                query = queryBuffer.toString().trim();
                OraAddAction.selectLOBStatements.put(conf, query);
            }
        }
        return ("".equals(query)) ? null : query;
    }
}
TOP

Related Classes of org.apache.cocoon.acting.OraAddAction

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.