Package com.abiquo.server.core.appslibrary

Source Code of com.abiquo.server.core.appslibrary.VirtualMachineTemplateDAO

/**
* Copyright (C) 2008 - Abiquo Holdings S.L. All rights reserved.
*
* Please see /opt/abiquo/tomcat/webapps/legal/ on Abiquo server
* or contact contact@abiquo.com for licensing information.
*/
package com.abiquo.server.core.appslibrary;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.persistence.EntityManager;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.sql.JoinFragment;

import com.abiquo.model.enumerator.ConversionState;
import com.abiquo.model.enumerator.DiskFormatType;
import com.abiquo.model.enumerator.HypervisorType;
import com.abiquo.model.enumerator.OSType;
import com.abiquo.model.enumerator.StatefulInclusion;
import com.abiquo.model.enumerator.VolumeState;
import com.abiquo.server.core.cloud.VirtualAppliance;
import com.abiquo.server.core.cloud.VirtualDatacenter;
import com.abiquo.server.core.cloud.VirtualMachine;
import com.abiquo.server.core.common.persistence.DefaultDAOBase;
import com.abiquo.server.core.enterprise.Enterprise;
import com.abiquo.server.core.enterprise.User;
import com.abiquo.server.core.infrastructure.Repository;
import com.abiquo.server.core.infrastructure.management.Rasd;
import com.abiquo.server.core.infrastructure.management.RasdManagement;
import com.abiquo.server.core.infrastructure.storage.StoragePool;
import com.abiquo.server.core.infrastructure.storage.Tier;
import com.abiquo.server.core.infrastructure.storage.VolumeManagement;
import com.abiquo.server.core.pricing.CostCode;
import com.abiquo.server.core.util.FilterOptions;
import com.abiquo.server.core.util.PagedList;
import com.softwarementors.bzngine.entities.PersistentEntity;

@org.springframework.stereotype.Repository("jpaVirtualMachineTemplateDAO")
/* package */class VirtualMachineTemplateDAO extends
    DefaultDAOBase<Integer, VirtualMachineTemplate>
{
    public VirtualMachineTemplateDAO()
    {
        super(VirtualMachineTemplate.class);
    }

    public VirtualMachineTemplateDAO(final EntityManager entityManager)
    {
        super(VirtualMachineTemplate.class, entityManager);
    }

    public List<VirtualMachineTemplate> findByEnterprise(final Enterprise enterprise)
    {
        Criteria criteria = createCriteria(sameEnterpriseOrShared(enterprise));
        criteria.addOrder(Order.asc(VirtualMachine.NAME_PROPERTY));
        return getResultList(criteria);
    }

    public List<VirtualMachineTemplate> findInPrecreatedVirtualMachineTemplate(final String ovfId,
        final Enterprise enterprise,
        final com.abiquo.server.core.infrastructure.Repository repository)
    {
        Criteria criteria =
            createCriteria(Restrictions.and(sameEnterpriseOrSharedInRepo(enterprise, repository),//
                Restrictions.eq(VirtualMachineTemplate.OVFID_PROPERTY, ovfId)));

        criteria.addOrder(Order.asc(VirtualMachine.NAME_PROPERTY));
        return getResultList(criteria);
    }

    public List<VirtualMachineTemplate> findByEnterpriseAndRepository(final Enterprise enterprise,
        final com.abiquo.server.core.infrastructure.Repository repository)
    {
        Criteria criteria = createCriteria(sameEnterpriseOrSharedInRepo(enterprise, repository));
        criteria.addOrder(Order.asc(VirtualMachine.NAME_PROPERTY));
        return getResultList(criteria);
    }

    /**
     * @param ostype, optionally filter by operating system (null for any filter)
     * @param is64b, optionally filter by x64 architecture. It requires ''ostype'' param set to null
     *            (null for any filter)
     * @param filters The pagination and search filters
     */
    @SuppressWarnings("unchecked")
    public List<VirtualMachineTemplate> findBy(final Enterprise enterprise,
        final com.abiquo.server.core.infrastructure.Repository repository, final Category category,
        final HypervisorType hypervisor, final OSType ostype, final Boolean is64b,
        final boolean imported, final FilterOptions filters)
    {
        Criteria criteria =
            createFindTemplateCriteria(enterprise, repository, category, hypervisor, ostype, is64b,
                imported, filters);

        // As we added a distinct as a result transformer in the criteria we need to get the count
        // result applying this distinct to match the results
        Integer size = count(criteria, PersistentEntity.ID_PROPERTY).intValue();

        // Rebuild the criteria since the count modified it
        criteria =
            createFindTemplateCriteria(enterprise, repository, category, hypervisor, ostype, is64b,
                imported, filters);

        // FIXME SCG: I promise to look for a best solution.
        // Note that Projections.groupProperty() returns a list of single properties (and not
        // entities), so isn't the solution.
        criteria.add(Restrictions.sqlRestriction("1=1 group by this_."
            + VirtualMachineTemplate.ID_COLUMN));

        if (filters.getLimit() == 0)
        {
            criteria.setFirstResult(0);
            criteria.setMaxResults(size);
        }
        else
        {
            criteria.setFirstResult(filters.getStartwith());
            criteria.setMaxResults(filters.getLimit());
        }

        PagedList<VirtualMachineTemplate> templates =
            new PagedList<VirtualMachineTemplate>(criteria.list());
        templates.setTotalResults(size);
        templates.setPageSize(filters.getLimit() > size ? size : filters.getLimit());
        templates.setCurrentElement(filters.getStartwith());

        return templates;
    }

    public List<VirtualMachineTemplate> findBy(final Category category)
    {
        Criteria criteria = createCriteria(sameCategory(category));
        criteria.addOrder(Order.asc(VirtualMachineTemplate.NAME_PROPERTY));

        List<VirtualMachineTemplate> result = getResultList(criteria);
        return result;
    }

    public List<VirtualMachineTemplate> findByCostCode(final CostCode costCode)
    {
        Criteria criteria = createCriteria(sameCostCode(costCode));

        List<VirtualMachineTemplate> result = getResultList(criteria);
        return result;
    }

    private Criterion importedVirtualMachineTemplate(final Enterprise enterprise)
    {
        return Restrictions.and(sameEnterprise(enterprise), repositoryNull());
    }

    /** Virtual Machine Template compatible or some conversion compatible. */
    private Criterion compatibleOrConversions(final HypervisorType hypervisorType,
        final Criteria criteria)
    {
        return Restrictions.or(compatible(Arrays.asList(hypervisorType.compatibilityTable)), //
            compatibleConversions(Arrays.asList(hypervisorType.compatibilityTable), criteria));
    }

    /** Virtual Machine Template is compatible. */
    private Criterion compatible(final List<DiskFormatType> types)
    {
        return Restrictions.in(VirtualMachineTemplate.DISKFORMAT_TYPE_PROPERTY, types);
    }

    /**
     * If (finished) conversions check some compatible. Left join to {@link VirtualImageConversion}
     */
    private Criterion compatibleConversions(final List<DiskFormatType> types,
        final Criteria criteria)
    {
        criteria.createAlias(VirtualMachineTemplate.CONVERSIONS_PROPERTY, "conversions",
            JoinFragment.LEFT_OUTER_JOIN);

        Criterion finished =
            Restrictions.eq("conversions." + VirtualImageConversion.STATE_PROPERTY,
                ConversionState.FINISHED);

        Criterion compatible =
            Restrictions.in("conversions." + VirtualImageConversion.TARGET_TYPE_PROPERTY, types);

        return Restrictions.and(finished, compatible);
    }

    /** ######### */

    public VirtualMachineTemplate findByName(final String name)
    {
        return findUniqueByProperty(VirtualMachineTemplate.NAME_PROPERTY, name);
    }

    public VirtualMachineTemplate findByPath(final Enterprise enterprise,
        final com.abiquo.server.core.infrastructure.Repository repository, final String path)
    {
        Criteria criteria =
            createCriteria(sameEnterpriseOrSharedInRepo(enterprise, repository, path));
        criteria.addOrder(Order.asc(VirtualMachine.NAME_PROPERTY));

        return getSingleResult(criteria);
    }

    public boolean existWithSamePath(final Enterprise enterprise,
        final com.abiquo.server.core.infrastructure.Repository repository, final String path)
    {
        Criteria criteria =
            createCriteria(sameEnterpriseOrSharedInRepo(enterprise, repository, path));
        criteria.addOrder(Order.asc(VirtualMachine.NAME_PROPERTY));
        List<VirtualMachineTemplate> result = getResultList(criteria);

        return CollectionUtils.isEmpty(result) ? false : true;
    }

    /**
     * @param ostype, optionally filter by operating system (null for any filter)
     * @param is64b, optionally filter by x64 architecture. It requires ''ostype'' param set to null
     *            (null for any filter)
     */
    @SuppressWarnings("unchecked")
    public List<VirtualMachineTemplate> findStatefulsByCategoryAndDatacenter(final User user,
        final Enterprise enterprise, final Category category, final Repository repository,
        final VirtualDatacenter vdc, final StatefulInclusion stateful, final OSType ostype,
        final Boolean is64b, final FilterOptions filters)
    {
        Criteria crit =
            createFindPersistentCriteria(user, enterprise, category, repository, vdc, stateful,
                ostype, is64b, filters);

        Integer size = count(crit).intValue();

        // Recreate the criteria since the count modified it
        crit =
            createFindPersistentCriteria(user, enterprise, category, repository, vdc, stateful,
                ostype, is64b, filters);

        if (filters.getLimit() == 0)
        {
            crit.setFirstResult(0);
            crit.setMaxResults(size);
        }
        else
        {
            crit.setFirstResult(filters.getStartwith());
            crit.setMaxResults(filters.getLimit());
        }

        PagedList<VirtualMachineTemplate> templates =
            new PagedList<VirtualMachineTemplate>(crit.list());
        templates.setTotalResults(size);
        templates.setPageSize(filters.getLimit() > size ? size : filters.getLimit());
        templates.setCurrentElement(filters.getStartwith());

        return templates;
    }

    /**
     * @param ostype, optionally filter by operating system (null for any filter)
     * @param is64b, optionally filter by x64 architecture. It requires ''ostype'' param set to null
     *            (null for any filter)
     */
    @SuppressWarnings("unchecked")
    public List<Integer> getPersistentIds(final User user, final Enterprise enterprise,
        final Category category, final Repository repository, final StatefulInclusion stateful,
        final OSType ostype, final Boolean is64b, final FilterOptions filters)
    {
        Criteria crit;
        if (filters == null)
        {
            crit = criteriaWithStatefulNavigation(stateful);
            crit.add(statefulVirtualMachineTemplate(stateful, crit));
            if (category != null)
            {
                crit.add(sameCategory(category));
            }

            if (ostype != null)
            {
                crit.add(sameOSType(ostype));
            }
            else if (is64b != null)
            {
                crit.add(sameArch(is64b));
            }
            if (!StringUtils.isEmpty(user.getAvailableVirtualDatacenters()))
            {
                crit.add(checkAllowedVirtualDatacenter(user));
            }

            crit.add(sameStatefulRepository(repository));
            crit.addOrder(Order.asc(VirtualMachineTemplate.NAME_PROPERTY));
        }
        else
        {
            crit =
                createFindPersistentCriteria(user, enterprise, category, repository, null,
                    stateful, ostype, is64b, filters);
        }
        crit.setProjection(Projections.property(PersistentEntity.ID_PROPERTY));
        return crit.list();
        // return getResultList(crit);
    }

    public List<VirtualMachineTemplate> findByMaster(final VirtualMachineTemplate master)
    {
        Criteria criteria = createCriteria(sameMaster(master));
        return getResultList(criteria);
    }

    @Override
    public VirtualMachineTemplate findById(final Integer id)
    {
        return getEntityManager().find(VirtualMachineTemplate.class, id);
    }

    public boolean isMaster(final VirtualMachineTemplate vmtemplate)
    {
        Criteria criteria = createCriteria(sameMaster(vmtemplate));
        return CollectionUtils.isEmpty(getResultList(criteria)) ? false : true;
    }

    private static Criterion sameCategory(final Category category)
    {
        return Restrictions.eq(VirtualMachineTemplate.CATEGORY_PROPERTY, category);
    }

    private static Criterion sameCostCode(final CostCode costCode)
    {
        return Restrictions.eq(VirtualMachineTemplate.COST_CODE_PROPERTY, costCode.getId());
    }

    public static Criterion sameOSType(final OSType ostype)
    {
        return Restrictions.eq(VirtualMachineTemplate.OS_TYPE_PROPERTY, ostype);
    }

    public static Criterion sameArch(final Boolean isArch64)
    {
        return Restrictions.in(VirtualMachineTemplate.OS_TYPE_PROPERTY, isArch64 ? OSType.arch64
            : OSType.arch32);
    }

    private static Criterion sameEnterprise(final Enterprise enterprise)
    {
        return Restrictions.eq(VirtualMachineTemplate.ENTERPRISE_PROPERTY, enterprise);
    }

    private static Criterion sameRepositoryAndNotStatefull(
        final com.abiquo.server.core.infrastructure.Repository repository)
    {
        // return Restrictions.and(Restrictions.eq(VirtualMachineTemplate.STATEFUL_PROPERTY, false),
        // Restrictions.eq(VirtualMachineTemplate.REPOSITORY_PROPERTY, repository));
        return Restrictions.eq(VirtualMachineTemplate.REPOSITORY_PROPERTY, repository);

    }

    private static Criterion repositoryNull()
    {
        return Restrictions.isNull(VirtualMachineTemplate.REPOSITORY_PROPERTY);
    }

    private static Criterion sharedVirtualMachineTemplate()
    {
        return Restrictions.eq(VirtualMachineTemplate.SHARED_PROPERTY, true);
    }

    private static Criterion statefulVirtualMachineTemplate(final StatefulInclusion stateful,
        final Criteria criteria)
    {
        Criterion cri = Restrictions.eq(VirtualMachineTemplate.STATEFUL_PROPERTY, true);

        switch (stateful)
        {
            case ALL:
                /*
                 * NEW_PERSISTENT FEATURE: With this feature may exist "pre templates" created and
                 * IN_PROGRESS or FAILED, in these cases the templates won't have got a relation
                 * with volume
                 */
                // Restrictions.and(cri,
                // Restrictions.isNotNull(VirtualMachineTemplate.VOLUME_PROPERTY));
                return cri;
            case USED:
                // use function criteriaWithStatefulNavigation before
                return Restrictions.and(cri,
                    Restrictions.eq("vl." + VolumeManagement.STATE_PROPERTY, VolumeState.ATTACHED));
            case NOTUSED:
                // use function criteriaWithStatefulNavigation before
                return Restrictions.and(cri,
                    Restrictions.or(Restrictions.isNull("vl."
                        + VolumeManagement.VIRTUAL_MACHINE_TEMPLATE_PROPERTY), Restrictions.and(
                        Restrictions.isNotNull("vl."
                            + VolumeManagement.VIRTUAL_MACHINE_TEMPLATE_PROPERTY), Restrictions.eq(
                            "vl." + VolumeManagement.STATE_PROPERTY, VolumeState.DETACHED))));
        }
        return cri;
    }

    private static Criterion sameEnterpriseOrShared(final Enterprise enterprise)
    {
        return Restrictions.or(sameEnterprise(enterprise), sharedVirtualMachineTemplate());
    }

    private static Criterion sameEnterpriseOrSharedInRepo(final Enterprise enterprise,
        final com.abiquo.server.core.infrastructure.Repository repository)
    {
        return Restrictions.and(sameRepositoryAndNotStatefull(repository),
            Restrictions.or(sameEnterprise(enterprise), sharedVirtualMachineTemplate()));
    }

    private static Criterion sameEnterpriseOrSharedInRepo(final Enterprise enterprise,
        final com.abiquo.server.core.infrastructure.Repository repository, final String path)
    {
        Criterion sameEnterpriseOrSharedInRepo =
            Restrictions.and(sameRepositoryAndNotStatefull(repository),
                Restrictions.or(sameEnterprise(enterprise), sharedVirtualMachineTemplate()));

        return Restrictions.and(Restrictions.eq(VirtualMachineTemplate.PATH_PROPERTY, path),
            sameEnterpriseOrSharedInRepo);
    }

    private static Criterion sameMaster(final VirtualMachineTemplate vmtemplate)
    {
        return Restrictions.eq(VirtualMachineTemplate.MASTER_PROPERTY, vmtemplate);
    }

    private static Criterion sameStatefulRepository(final Repository repository)
    {
        return Restrictions.and(Restrictions.isNotNull(VirtualMachineTemplate.MASTER_PROPERTY),
            Restrictions.eq("ms." + VirtualMachineTemplate.REPOSITORY_PROPERTY, repository));

    }

    private static Criterion sameStatefulVirtualDatacenter(final VirtualDatacenter virtualDatacenter)
    {
        return Restrictions.eq("vl." + RasdManagement.VIRTUAL_DATACENTER_PROPERTY,
            virtualDatacenter);
    }

    private Criteria criteriaWithStatefulNavigation(final StatefulInclusion stateful)
    {
        Criteria crit = createCriteria();
        crit.createAlias(VirtualMachineTemplate.MASTER_PROPERTY, "ms");
        switch (stateful)
        {
            case USED:
                crit.createAlias(VirtualMachineTemplate.VOLUME_PROPERTY, "vl");
                crit.createAlias("vl." + VolumeManagement.STORAGE_POOL_PROPERTY, "pool");
                crit.createAlias("pool." + StoragePool.DEVICE_PROPERTY, "device");
                crit.createAlias("pool." + StoragePool.TIER_PROPERTY, "tier");
                crit.createAlias("vl." + RasdManagement.RASD_PROPERTY, "rasd");
                crit.createAlias("vl." + RasdManagement.VIRTUAL_DATACENTER_PROPERTY, "vdc");
                crit.createAlias("vl." + RasdManagement.VIRTUAL_APPLIANCE_PROPERTY, "vapp");
                crit.createAlias("vl." + RasdManagement.VIRTUAL_MACHINE_PROPERTY, "vm");
                break;
            case NOTUSED:
            case ALL:
                crit.createAlias(VirtualMachineTemplate.VOLUME_PROPERTY, "vl",
                    JoinFragment.LEFT_OUTER_JOIN);
                crit.createAlias("vl." + VolumeManagement.STORAGE_POOL_PROPERTY, "pool",
                    JoinFragment.LEFT_OUTER_JOIN);
                crit.createAlias("pool." + StoragePool.DEVICE_PROPERTY, "device",
                    JoinFragment.LEFT_OUTER_JOIN);
                crit.createAlias("pool." + StoragePool.TIER_PROPERTY, "tier",
                    JoinFragment.LEFT_OUTER_JOIN);
                crit.createAlias("vl." + RasdManagement.RASD_PROPERTY, "rasd",
                    JoinFragment.LEFT_OUTER_JOIN);
                crit.createAlias("vl." + RasdManagement.VIRTUAL_DATACENTER_PROPERTY, "vdc",
                    JoinFragment.LEFT_OUTER_JOIN);
                crit.createAlias("vl." + RasdManagement.VIRTUAL_APPLIANCE_PROPERTY, "vapp",
                    JoinFragment.LEFT_OUTER_JOIN);
                crit.createAlias("vl." + RasdManagement.VIRTUAL_MACHINE_PROPERTY, "vm",
                    JoinFragment.LEFT_OUTER_JOIN);
                break;
        }
        return crit;
    }

    private Criteria createFindPersistentCriteria(final User user, final Enterprise enterprise,
        final Category category, final Repository repository, final VirtualDatacenter vdc,
        final StatefulInclusion stateful, final OSType ostype, final Boolean is64b,
        final FilterOptions filters)
    {
        Criteria crit = criteriaWithStatefulNavigation(stateful);
        crit.add(statefulVirtualMachineTemplate(stateful, crit));
        crit.add(sameEnterprise(enterprise));
        crit.add(sameStatefulRepository(repository));
        if (category != null)
        {
            crit.add(sameCategory(category));
        }
        if (vdc != null)
        {
            crit.add(sameStatefulVirtualDatacenter(vdc));
        }
        if (!StringUtils.isEmpty(user.getAvailableVirtualDatacenters()))
        {
            crit.add(checkAllowedVirtualDatacenter(user));
        }
        if (ostype != null)
        {
            crit.add(sameOSType(ostype));
        }
        else if (is64b != null)
        {
            crit.add(sameArch(is64b));
        }

        // Search criterias
        crit.add(filterBy(filters, VirtualMachineTemplate.NAME_PROPERTY, "ms."
            + VirtualMachineTemplate.NAME_PROPERTY, "vdc." + VirtualDatacenter.NAME_PROPERTY,
            "vapp." + VirtualAppliance.NAME_PROPERTY, "vm." + VirtualMachine.NAME_PROPERTY, "tier."
                + Tier.NAME_PROPERTY));

        // Set ordering
        if (filters.getOrderBy() != null && !filters.getOrderBy().isEmpty())
        {
            String sortColumn =
                PersistentTemplateOrder.valueOf(filters.getOrderBy().toUpperCase()).getHqlColumn();

            crit.addOrder(filters.getAsc() == null || filters.getAsc().booleanValue() ? Order
                .asc(sortColumn) : Order.desc(sortColumn));
        }

        return crit;
    }

    private Criteria createFindTemplateCriteria(final Enterprise enterprise,
        final com.abiquo.server.core.infrastructure.Repository repository, final Category category,
        final HypervisorType hypervisor, final OSType ostype, final Boolean is64b,
        final boolean imported, final FilterOptions filters)
    {
        Criteria crit = null;
        Criterion sameEnterpriseOrShared = sameEnterpriseOrSharedInRepo(enterprise, repository);

        if (imported)
        {
            Criterion importedTemplate = importedVirtualMachineTemplate(enterprise);
            crit = createCriteria(Restrictions.or(sameEnterpriseOrShared, importedTemplate));
        }
        else
        {
            crit = createCriteria(sameEnterpriseOrShared);
        }

        if (category != null)
        {
            crit.add(sameCategory(category));
        }

        if (hypervisor != null)
        {
            crit.add(compatibleOrConversions(hypervisor, crit));
        }

        if (ostype != null)
        {
            crit.add(sameOSType(ostype));
        }
        else if (is64b != null)
        {
            crit.add(sameArch(is64b));
        }

        // Search criterias
        crit.add(filterBy(filters, VirtualMachineTemplate.NAME_PROPERTY));

        // Set ordering
        if (filters.getOrderBy() != null && !filters.getOrderBy().isEmpty())
        {
            crit.addOrder(filters.getAsc() == null || filters.getAsc().booleanValue() ? Order
                .asc(VirtualMachineTemplate.NAME_PROPERTY) : Order
                .desc(VirtualMachineTemplate.NAME_PROPERTY));
        }

        // The query may return duplicates. Add a distinct by id
        crit.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);

        return crit;
    }

    private static enum PersistentTemplateOrder
    {
        ID(VirtualMachineTemplate.ID_PROPERTY), //
        NAME(VirtualMachineTemplate.NAME_PROPERTY), //
        MASTER("ms." + VirtualMachineTemplate.NAME_PROPERTY), //
        VIRTUALDATACENTER("vdc." + VirtualDatacenter.NAME_PROPERTY), //
        VIRTUALAPPLIANCE("vapp." + VirtualAppliance.NAME_PROPERTY), //
        VIRTUALMACHINE("vm." + VirtualMachine.NAME_PROPERTY), //
        TIER("tier." + Tier.NAME_PROPERTY), //
        SIZE("rasd." + Rasd.LIMIT_PROPERTY);

        private String hqlColumn;

        private PersistentTemplateOrder(final String hqlColumn)
        {
            this.hqlColumn = hqlColumn;
        }

        public String getHqlColumn()
        {
            return hqlColumn;
        }

    }

    private Criterion checkAllowedVirtualDatacenter(final User user)
    {
        List<Integer> allowedVdcs = new ArrayList<Integer>();
        // Assume that user.getAvailableVirtualDatacenters() is empty or not has been checked
        // previously, to add or not the restriction
        for (String id : user.getAvailableVirtualDatacenters().split(","))
        {
            allowedVdcs.add(new Integer(id));
        }
        return Restrictions.in("vdc." + PersistentEntity.ID_PROPERTY, allowedVdcs);
    }
}
TOP

Related Classes of com.abiquo.server.core.appslibrary.VirtualMachineTemplateDAO

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.