Package org.sonar.core.resource

Source Code of org.sonar.core.resource.ResourceIndexerDao

/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
package org.sonar.core.resource;

import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.SqlSession;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Scopes;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;

public class ResourceIndexerDao {

  private static final String SELECT_RESOURCES = "org.sonar.core.resource.ResourceIndexerMapper.selectResources";
  public static final int MINIMUM_KEY_SIZE = 3;
  public static final int SINGLE_INDEX_SIZE = 2;

  // The scopes and qualifiers that are not in the following constants are not indexed at all.
  // Directories and packages are explicitly excluded.
  private static final String[] RENAMABLE_QUALIFIERS = {Qualifiers.PROJECT, Qualifiers.MODULE, Qualifiers.VIEW, Qualifiers.SUBVIEW};
  private static final String[] RENAMABLE_SCOPES = {Scopes.PROJECT};
  private static final String[] NOT_RENAMABLE_QUALIFIERS = {Qualifiers.FILE, Qualifiers.UNIT_TEST_FILE, Qualifiers.CLASS};
  private static final String[] NOT_RENAMABLE_SCOPES = {Scopes.FILE};

  private final MyBatis mybatis;

  public ResourceIndexerDao(MyBatis mybatis) {
    this.mybatis = mybatis;
  }

  /**
   * This method is reentrant. It can be executed even if the project is already indexed.
   */
  public ResourceIndexerDao indexProject(final int rootProjectId) {
    DbSession session = mybatis.openSession(true);
    try {
      indexProject(rootProjectId, session);
      session.commit();
      return this;

    } finally {
      MyBatis.closeQuietly(session);
    }
  }

  public void indexProject(final int rootProjectId, DbSession session) {
    ResourceIndexerMapper mapper = session.getMapper(ResourceIndexerMapper.class);
    doIndexProject(rootProjectId, session, mapper);
  }

  /**
   * This method is reentrant. It can be executed even if some projects are already indexed.
   */
  public ResourceIndexerDao indexProjects() {
    final DbSession session = mybatis.openSession(true);
    try {
      final ResourceIndexerMapper mapper = session.getMapper(ResourceIndexerMapper.class);
      session.select("org.sonar.core.resource.ResourceIndexerMapper.selectRootProjectIds", /* workaround to get booleans */ResourceIndexerQuery.create(), new ResultHandler() {
        @Override
        public void handleResult(ResultContext context) {
          Integer rootProjectId = (Integer) context.getResultObject();
          doIndexProject(rootProjectId, session, mapper);
          session.commit();
        }
      });
      return this;

    } finally {
      MyBatis.closeQuietly(session);
    }
  }

  private void doIndexProject(int rootProjectId, SqlSession session, final ResourceIndexerMapper mapper) {
    // non indexed resources
    ResourceIndexerQuery query = ResourceIndexerQuery.create()
      .setNonIndexedOnly(true)
      .setQualifiers(NOT_RENAMABLE_QUALIFIERS)
      .setScopes(NOT_RENAMABLE_SCOPES)
      .setRootProjectId(rootProjectId);

    session.select(SELECT_RESOURCES, query, new ResultHandler() {
      @Override
      public void handleResult(ResultContext context) {
        ResourceDto resource = (ResourceDto) context.getResultObject();
        doIndex(resource, mapper);
      }
    });

    // some resources can be renamed, so index must be regenerated
    // -> delete existing rows and create them again
    query = ResourceIndexerQuery.create()
      .setNonIndexedOnly(false)
      .setQualifiers(RENAMABLE_QUALIFIERS)
      .setScopes(RENAMABLE_SCOPES)
      .setRootProjectId(rootProjectId);

    session.select(SELECT_RESOURCES, query, new ResultHandler() {
      @Override
      public void handleResult(ResultContext context) {
        ResourceDto resource = (ResourceDto) context.getResultObject();

        mapper.deleteByResourceId(resource.getId());
        doIndex(resource, mapper);
      }
    });
  }

  void doIndex(ResourceDto resource, ResourceIndexerMapper mapper) {
    String key = nameToKey(resource.getName());
    if (key.length() >= MINIMUM_KEY_SIZE || key.length() == SINGLE_INDEX_SIZE) {
      insertIndexEntries(key, resource.getId(), resource.getQualifier(), resource.getRootId(), resource.getName().length(), mapper);
    }
  }

  public boolean indexResource(long id) {
    boolean indexed = false;
    SqlSession session = mybatis.openSession(false);
    try {
      ResourceIndexerMapper mapper = session.getMapper(ResourceIndexerMapper.class);
      ResourceDto resource = mapper.selectResourceToIndex(id);
      if (resource != null) {
        Long rootId = resource.getRootId();
        if (rootId == null) {
          rootId = resource.getId();
        }
        indexed = indexResource(resource.getId(), resource.getName(), resource.getQualifier(), rootId, session, mapper);
      }
      return indexed;
    } finally {
      MyBatis.closeQuietly(session);
    }
  }

  public boolean indexResource(int id, String name, String qualifier, int rootId) {
    boolean indexed = false;
    SqlSession session = mybatis.openSession(false);
    ResourceIndexerMapper mapper = session.getMapper(ResourceIndexerMapper.class);
    try {
      indexed = indexResource(id, name, qualifier, rootId, session, mapper);
    } finally {
      MyBatis.closeQuietly(session);
    }
    return indexed;
  }

  private boolean indexResource(long id, String name, String qualifier, long rootId, SqlSession session, ResourceIndexerMapper mapper) {
    boolean indexed = false;
    String key = nameToKey(name);
    if (key.length() >= MINIMUM_KEY_SIZE || key.length() == SINGLE_INDEX_SIZE) {
      indexed = true;
      boolean toBeIndexed = sanitizeIndex(id, key, mapper);
      if (toBeIndexed) {
        insertIndexEntries(key, id, qualifier, rootId, name.length(), mapper);
        session.commit();
      }
    }
    return indexed;
  }

  private void insertIndexEntries(String key, long resourceId, String qualifier, long rootId, int nameLength, ResourceIndexerMapper mapper) {
    ResourceIndexDto dto = new ResourceIndexDto()
      .setResourceId(resourceId)
      .setQualifier(qualifier)
      .setRootProjectId(rootId)
      .setNameSize(nameLength);

    int maxPosition = key.length() == SINGLE_INDEX_SIZE ? 0 : key.length() - MINIMUM_KEY_SIZE;
    for (int position = 0; position <= maxPosition; position++) {
      dto.setPosition(position);
      dto.setKey(StringUtils.substring(key, position));
      mapper.insert(dto);
    }
  }

  /**
   * Return true if the resource must be indexed, false if the resource is already indexed.
   * If the resource is indexed with a different key, then this index is dropped and the
   * resource must be indexed again.
   */
  private boolean sanitizeIndex(long resourceId, String key, ResourceIndexerMapper mapper) {
    ResourceIndexDto masterIndex = mapper.selectMasterIndexByResourceId(resourceId);
    if (masterIndex != null && !StringUtils.equals(key, masterIndex.getKey())) {
      // resource has been renamed -> drop existing indexes
      mapper.deleteByResourceId(resourceId);
      masterIndex = null;
    }
    return masterIndex == null;
  }

  static String nameToKey(String input) {
    return StringUtils.lowerCase(StringUtils.trimToEmpty(input));
  }
}
TOP

Related Classes of org.sonar.core.resource.ResourceIndexerDao

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.