org.apache.openjpa.azure.util.AzureUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.openjpa.azure.util.AzureUtils.java

Source

/*
 * 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.openjpa.azure.util;

import java.beans.PropertyDescriptor;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.Embeddable;
import org.apache.commons.lang.StringUtils;
import org.apache.openjpa.azure.Federation;
import org.apache.openjpa.azure.jdbc.conf.AzureConfiguration;
import org.apache.openjpa.azure.jdbc.conf.AzureConfiguration.RangeType;
import org.apache.openjpa.jdbc.meta.MappingRepository;
import org.apache.openjpa.jdbc.schema.ForeignKey;
import org.apache.openjpa.jdbc.schema.Table;
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.azure.jdbc.AzureSliceStoreManager;
import org.apache.openjpa.slice.jdbc.DistributedJDBCStoreManager;
import org.apache.openjpa.slice.jdbc.SliceStoreManager;
import org.apache.openjpa.util.ObjectId;

public final class AzureUtils {

    private AzureUtils() {
    }

    public static Connection useFederation(final Connection conn, final Federation federation) throws SQLException {

        final MemberDistribution memberDistribution = getMemberDistribution(conn, federation);
        return useFederation(conn, federation, memberDistribution.iterator().next());
    }

    public static Connection useFederation(final Connection conn, final Federation federation, final Object oid)
            throws SQLException {

        final String distribution = RangeType.UNIQUEIDENTIFIER == federation.getRangeMappingType()
                ? getUidAsString(oid)
                : getObjectIdAsString(oid);

        final String distributionName = federation.getDistributionName();

        Statement stmt = null;
        try {
            stmt = conn.createStatement();
            stmt.execute("USE FEDERATION " + federation + " (" + distributionName + " = " + distribution + ") "
                    + "WITH FILTERING=OFF, RESET");
        } finally {
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException ignore) {
                    // ignore exception
                }
            }
        }

        return conn;
    }

    public static boolean checkForFederationMember(final Federation federation, final Object member, Object oid) {

        if (federation == null || member == null) {
            return false;
        }

        final RangeType type = federation.getRangeMappingType();

        if (RangeType.UNIQUEIDENTIFIER == type) {
            final String left, right;

            if (oid instanceof byte[]) {
                left = new String((byte[]) oid);
                right = new String((byte[]) member);
            } else {
                left = oid.toString();
                right = member.toString();
                return left.compareTo(right) >= 0;
            }

            return left.compareTo(right) >= 0;
        } else {
            if (oid instanceof byte[]) {
                final String left = "0x" + new String(HexEncoderDecoder.encode((byte[]) oid));
                final String right = "0x" + new String(HexEncoderDecoder.encode((byte[]) member));
                return left.compareTo(right) >= 0;
            } else {
                return Long.parseLong(oid.toString()) >= Long.parseLong(member.toString());
            }
        }
    }

    public static Object getMemberDistribution(final Connection conn, final Federation federation, final Object oid)
            throws SQLException {

        final RangeType type = federation.getRangeMappingType();

        final String rangeId = RangeType.UNIQUEIDENTIFIER == type
                ? "CAST(" + getUidAsString(oid) + " AS UNIQUEIDENTIFIER)"
                : getObjectIdAsString(oid);

        Statement stm = null;
        ResultSet federation_id = null;
        ResultSet member_distribution = null;

        Object res = null;

        try {
            stm = conn.createStatement();

            federation_id = stm.executeQuery(
                    "SELECT * " + "FROM sys.Federations " + "WHERE name = '" + federation.getName() + "'");

            if (federation_id.next()) {
                member_distribution = stm.executeQuery("SELECT CAST(MAX(range_low) as " + type.getValue()
                        + ") FROM sys.federation_member_distributions " + "WHERE federation_id="
                        + federation_id.getInt(1) + " and range_low<=" + rangeId);

                if (member_distribution.next()) {
                    res = member_distribution.getObject(1);
                }
            }

        } finally {
            if (stm != null) {
                stm.close();
            }

            if (federation_id != null) {
                federation_id.close();
            }

            if (member_distribution != null) {
                member_distribution.close();
            }
        }

        return res;
    }

    public static MemberDistribution getMemberDistribution(final Connection conn, final Federation federation)
            throws SQLException {

        final RangeType type = federation.getRangeMappingType();
        final MemberDistribution memberDistribution = new MemberDistribution(type);

        Statement stm = null;
        ResultSet federation_id = null;
        ResultSet member_distribution = null;
        try {
            stm = conn.createStatement();

            federation_id = stm.executeQuery(
                    "SELECT * " + "FROM sys.Federations " + "WHERE name = '" + federation.getName() + "'");

            if (federation_id.next()) {
                member_distribution = stm.executeQuery("SELECT CAST(range_low as " + type.getValue() + ") AS low "
                        + "FROM sys.federation_member_distributions " + "WHERE federation_id="
                        + federation_id.getInt(1) + " ORDER BY low");

                while (member_distribution.next()) {
                    memberDistribution.addValue(member_distribution.getObject(1));
                }
            }

        } finally {
            if (stm != null) {
                stm.close();
            }
            if (federation_id != null) {
                federation_id.close();
            }
            if (member_distribution != null) {
                member_distribution.close();
            }
        }

        return memberDistribution;
    }

    /**
     * Check if table exist.
     *
     * @param conn given connection.
     * @param table table to be verified.
     * @param oid range id.
     * @return TRUE if exists; FALSE otherwise.
     * @throws SQLException
     */
    public static boolean tableExists(final Connection conn, final Table table) throws SQLException {

        boolean res = false;

        Statement stm = null;
        ResultSet rs = null;
        try {
            stm = conn.createStatement();

            rs = stm.executeQuery("SELECT DISTINCT OBJECT_NAME (object_id) AS[ObjectName] "
                    + "FROM sys.dm_db_partition_stats " + "WHERE OBJECT_NAME(object_id) ='" + table + "'");

            if (rs.next()) {
                res = true;
            }
        } finally {
            if (rs != null) {
                rs.close();
            }

            if (stm != null) {
                stm.close();
            }
        }

        return res;
    }

    public static Set<Federation> getTargetFederation(final AzureConfiguration conf, final Table table,
            Set<String> tablesToBeExcluded) {

        if (tablesToBeExcluded == null) {
            tablesToBeExcluded = new HashSet<String>();
        }

        tablesToBeExcluded.add(table.getFullIdentifier().getName());

        final Set<Federation> federations = new HashSet<Federation>(conf.getFederations(table));

        final ForeignKey[] fks = table.getForeignKeys();

        for (ForeignKey fk : fks) {
            final Table extTable = fk.getPrimaryKeyTable();
            if (!tablesToBeExcluded.contains(extTable.getFullIdentifier().getName())) {
                federations.addAll(getTargetFederation(conf, extTable, tablesToBeExcluded));
            }
        }

        return federations;
    }

    public static String getTableName(final AzureConfiguration conf, final ClassMetaData meta) {
        return meta == null ? null : getTableName(conf, meta.getDescribedType());
    }

    public static Table getTable(final AzureConfiguration conf, final ClassMetaData meta) {
        return meta == null ? null : getTable(conf, meta.getDescribedType());
    }

    public static String getTableName(final AzureConfiguration conf, final Class describedType) {
        try {
            final Table table = getTable(conf, describedType);
            return table == null ? null : table.getFullIdentifier().getName();
        } catch (Exception e) {
            // ignore exception and search for table by using all the connections
            return null;
        }
    }

    public static Table getTable(final AzureConfiguration conf, final Class describedType) {
        try {
            final MappingRepository repo = conf.getMappingRepositoryInstance();
            final Table table = repo.getMapping(describedType, conf.getClass().getClassLoader(), true).getTable();
            return table;
        } catch (Exception e) {
            // ignore exception and search for table by using all the connections
            return null;
        }
    }

    public static Map.Entry<String, Object> getTargetId(final AzureConfiguration conf, final Class candidate) {
        String tableName = getTableName(conf, candidate);

        // TODO: improve looking for distribution value.
        return new AbstractMap.SimpleEntry<String, Object>(tableName, null);
    }

    public static Map.Entry<String, Object> getTargetId(final AzureConfiguration conf, final ClassMetaData meta) {
        String tableName = getTableName(conf, meta);

        // TODO: improve looking for distribution value.
        return new AbstractMap.SimpleEntry<String, Object>(tableName, null);
    }

    public static String getObjectIdAsString(final Object oid) {
        return oid instanceof byte[] ? "0x" + new String(HexEncoderDecoder.encode((byte[]) oid)) : oid.toString();
    }

    private static String getUidAsString(final Object oid) {
        return oid instanceof byte[] ? new String((byte[]) oid) : "'" + oid.toString() + "'";
    }

    public static Object getObjectId(final Federation fed, final OpenJPAStateManager sm, final String dn) {
        return StringUtils.isNotBlank(dn) ? getObjectIdValue(sm.getObjectId(), dn) : null;
    }

    public static Object getObjectIdValue(final Object oid, final String key) {
        Object value = null;

        if (StringUtils.isNotBlank(key)) {
            try {
                if (oid instanceof ObjectId) {
                    final Object idObject = ((ObjectId) oid).getIdObject();
                    value = new PropertyDescriptor(key, idObject.getClass()).getReadMethod().invoke(idObject);
                } else {
                    final Embeddable embeddable = oid.getClass().getAnnotation(Embeddable.class);
                    if (embeddable == null) {
                        value = oid;
                    } else {
                        value = new PropertyDescriptor(key, oid.getClass()).getReadMethod().invoke(oid);
                    }
                }
            } catch (Exception ignore) {
                // ignore
            }
        }

        return value;
    }

    public static List<String> getTargetSlice(final DistributedJDBCStoreManager store, final List<String> slices,
            final Federation fed, final Object id) {

        final List<String> res = new ArrayList<String>();

        boolean firstMatchOnly = id != null;

        for (int i = slices.size() - 1; i >= 0 || firstMatchOnly; i--) {

            final SliceStoreManager sliceStore = store.getSlice(i);

            final Object fedLowerBound = ((AzureSliceStoreManager) sliceStore).getFedLowerBound();
            final boolean isSingleMember = !((AzureSliceStoreManager) sliceStore).isFedMultiMember();

            if (fed.getName().equals(((AzureSliceStoreManager) sliceStore).getFedName())) {
                if (isSingleMember || !firstMatchOnly) {
                    res.add(sliceStore.getName());
                } else if (AzureUtils.checkForFederationMember(fed, fedLowerBound, id)) {
                    res.add(sliceStore.getName());
                    return res;
                }
            }
        }

        if (res.isEmpty()) {
            res.add("ROOT");
        }

        return res;
    }

    public static String getFederationName(final String sliceName) {
        int index = sliceName.lastIndexOf(".");

        return index < 0 ? sliceName : sliceName.substring(0, index);
    }

    public static int getSliceMemberIndex(final String sliceName) {
        int index = sliceName.lastIndexOf(".");

        return index < 0 ? 0 : Integer.parseInt(sliceName.substring(index + 1, sliceName.length()));
    }

    public static String getSliceName(final String openjpaId) {
        int index = openjpaId.indexOf(".");

        return index < 0 ? openjpaId : openjpaId.substring(index + 1, openjpaId.length());
    }
}