/* * Copyright 2014-2016 CyberVision, Inc. * * 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.kaaproject.kaa.server.datamigration; import static com.datastax.driver.core.querybuilder.QueryBuilder.eq; import static com.datastax.driver.core.querybuilder.QueryBuilder.select; import static com.datastax.driver.core.querybuilder.QueryBuilder.set; import static com.datastax.driver.core.querybuilder.QueryBuilder.update; import static org.kaaproject.kaa.server.datamigration.utils.Utils.encodeUuids; import com.datastax.driver.core.BatchStatement; import com.datastax.driver.core.Cluster; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; import com.datastax.driver.core.Session; import com.mongodb.MongoClient; import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.Filters; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.ResultSetHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.bson.Document; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.map.ObjectMapper; import org.kaaproject.kaa.server.datamigration.model.Configuration; import org.kaaproject.kaa.server.datamigration.utils.Options; import java.io.IOException; import java.sql.Connection; import java.sql.SQLException; import java.util.List; public class UpdateUuidsMigration { private Connection connection; private MongoClient client; private Cluster cluster; private String dbName; private String nosql; /** * Create a new instance of UpdateUuidsMigration. * * @param connection the connection to relational database * @param options the options for configuring NoSQL databases */ public UpdateUuidsMigration(Connection connection, Options options) { this.connection = connection; client = new MongoClient(options.getHost()); cluster = Cluster.builder() .addContactPoint(options.getHost()) .build(); dbName = options.getDbName(); this.nosql = options.getNoSql(); } /** * Change encoding of uuids from Latin1 to Base64 in relational and NoSQL databases. * */ public void transform() throws IOException, SQLException { QueryRunner run = new QueryRunner(); ResultSetHandler<List<Configuration>> rsHandler = new BeanListHandler<>(Configuration.class); List<Configuration> configs = run.query(connection, "SELECT * FROM configuration", rsHandler); for (Configuration config : configs) { JsonNode json = new ObjectMapper().readTree(config.getConfigurationBody()); JsonNode jsonEncoded = encodeUuids(json); byte[] encodedConfigurationBody = jsonEncoded.toString().getBytes(); int updates = run.update(connection, "UPDATE configuration SET configuration_body=? WHERE id=?", encodedConfigurationBody, config.getId() ); if (updates != 1) { System.err.println("Error: failed to update configuration: " + config); } } if (nosql.equals(Options.DEFAULT_NO_SQL)) { MongoDatabase database = client.getDatabase(dbName); MongoCollection<Document> userConfiguration = database.getCollection("user_configuration"); FindIterable<Document> documents = userConfiguration.find(); for (Document d : documents) { String body = (String) d.get("body"); JsonNode json = new ObjectMapper().readTree(body); JsonNode jsonEncoded = encodeUuids(json); userConfiguration.updateOne( Filters.eq("_id", d.get("_id")), Filters.eq("$set", Filters.eq("body", jsonEncoded)) ); } } else { Session session = cluster.connect(dbName); BatchStatement batchStatement = new BatchStatement(); String tableName = "user_conf"; ResultSet results = session.execute(select().from(tableName)); for (Row row : results) { String userId = row.getString("user_id"); String appToken = row.getString("app_token"); int schemaVersion = row.getInt("schema_version"); String body = row.getString("body"); String bodyEncoded = encodeUuids(new ObjectMapper().readTree(body)).toString(); batchStatement.add( update(tableName) .with(set("body", bodyEncoded)) .where(eq("user_id", userId)) .and(eq("app_token", appToken)) .and(eq("schema_version", schemaVersion)) ); } session.execute(batchStatement); session.close(); cluster.close(); } } }