001/*
002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Florent Guillaume
018 */
019package org.nuxeo.ecm.core.storage.sql.jdbc;
020
021import java.io.Serializable;
022import java.sql.PreparedStatement;
023import java.sql.ResultSet;
024import java.sql.SQLException;
025import java.util.ArrayList;
026import java.util.Calendar;
027import java.util.Iterator;
028import java.util.List;
029
030import org.nuxeo.ecm.core.storage.sql.ACLRow;
031import org.nuxeo.ecm.core.storage.sql.Model;
032import org.nuxeo.ecm.core.storage.sql.RowMapper.RowUpdate;
033import org.nuxeo.ecm.core.storage.sql.jdbc.db.Column;
034
035/**
036 * Collection IO for arrays of ACLs.
037 */
038public class ACLCollectionIO implements CollectionIO {
039
040    /** Whether we always write all the row elements in a RowUpdate or just the values starting from pos. */
041    protected final boolean insertAll;
042
043    public ACLCollectionIO(boolean insertAll) {
044        this.insertAll = insertAll;
045    }
046
047    @Override
048    public ACLRow getCurrentFromResultSet(ResultSet rs, List<Column> columns, Model model, Serializable[] returnId,
049            int[] returnPos) throws SQLException {
050        Serializable id = null;
051        String name = null;
052        boolean grant = false;
053        String permission = null;
054        String creator = null;
055        Calendar begin = null;
056        Calendar end = null;
057        String user = null;
058        String group = null;
059        Long status = null;
060        int i = 0;
061        for (Column column : columns) {
062            i++;
063            String key = column.getKey();
064            Serializable v = column.getFromResultSet(rs, i);
065            switch (key) {
066            case Model.MAIN_KEY:
067                id = v;
068                break;
069            case Model.ACL_NAME_KEY:
070                name = (String) v;
071                break;
072            case Model.ACL_GRANT_KEY:
073                grant = v == null ? false : (Boolean) v;
074                break;
075            case Model.ACL_PERMISSION_KEY:
076                permission = (String) v;
077                break;
078            case Model.ACL_CREATOR_KEY:
079                creator = (String) v;
080                break;
081            case Model.ACL_BEGIN_KEY:
082                begin = (Calendar) v;
083                break;
084            case Model.ACL_END_KEY:
085                end = (Calendar) v;
086                break;
087            case Model.ACL_USER_KEY:
088                user = (String) v;
089                break;
090            case Model.ACL_GROUP_KEY:
091                group = (String) v;
092                break;
093            case Model.ACL_STATUS_KEY:
094                status = (Long) v;
095                break;
096            case Model.ACL_POS_KEY:
097                // ignore, query already sorts by pos
098                break;
099            default:
100                throw new RuntimeException(key);
101            }
102        }
103        Serializable prevId = returnId[0];
104        returnId[0] = id;
105        int pos = (id != null && !id.equals(prevId)) ? 0 : returnPos[0] + 1;
106        returnPos[0] = pos;
107        return new ACLRow(pos, name, grant, permission, user, group, creator, begin, end, status);
108    }
109
110    @Override
111    public void executeInserts(PreparedStatement ps, List<RowUpdate> rowus, List<Column> columns,
112            boolean supportsBatchUpdates, String sql, JDBCConnection connection) throws SQLException {
113        List<Serializable> debugValues = connection.logger.isLogEnabled() ? new ArrayList<>() : null;
114        boolean batched = supportsBatchUpdates && rowus.size() > 1;
115        String loggedSql = batched ? sql + " -- BATCHED" : sql;
116        int batch = 0;
117        for (Iterator<RowUpdate> rowIt = rowus.iterator(); rowIt.hasNext();) {
118            RowUpdate rowu = rowIt.next();
119            int start;
120            if (rowu.pos == -1 || insertAll) {
121                start = 0;
122            } else {
123                start = rowu.pos;
124            }
125            Serializable id = rowu.row.id;
126            Serializable[] array = rowu.row.values;
127            for (int i = start; i < array.length; i++) {
128                ACLRow acl = (ACLRow) array[i];
129                int n = 0;
130                for (Column column : columns) {
131                    n++;
132                    String key = column.getKey();
133                    Serializable v;
134                    switch (key) {
135                    case Model.MAIN_KEY:
136                        v = id;
137                        break;
138                    case Model.ACL_POS_KEY:
139                        v = (long) acl.pos;
140                        break;
141                    case Model.ACL_NAME_KEY:
142                        v = acl.name;
143                        break;
144                    case Model.ACL_GRANT_KEY:
145                        v = acl.grant;
146                        break;
147                    case Model.ACL_PERMISSION_KEY:
148                        v = acl.permission;
149                        break;
150                    case Model.ACL_CREATOR_KEY:
151                        v = acl.creator;
152                        break;
153                    case Model.ACL_BEGIN_KEY:
154                        v = acl.begin;
155                        break;
156                    case Model.ACL_END_KEY:
157                        v = acl.end;
158                        break;
159                    case Model.ACL_STATUS_KEY:
160                        v = acl.status;
161                        break;
162                    case Model.ACL_USER_KEY:
163                        v = acl.user;
164                        break;
165                    case Model.ACL_GROUP_KEY:
166                        v = acl.group;
167                        break;
168                    default:
169                        throw new RuntimeException(key);
170                    }
171                    column.setToPreparedStatement(ps, n, v);
172                    if (debugValues != null) {
173                        debugValues.add(v);
174                    }
175                }
176                if (debugValues != null) {
177                    connection.logger.logSQL(loggedSql, debugValues);
178                    debugValues.clear();
179                }
180                if (batched) {
181                    ps.addBatch();
182                    batch++;
183                    if (batch % JDBCRowMapper.UPDATE_BATCH_SIZE == 0 || !rowIt.hasNext()) {
184                        ps.executeBatch();
185                        connection.countExecute();
186                    }
187                } else {
188                    ps.execute();
189                    connection.countExecute();
190                }
191            }
192        }
193    }
194
195}