org.sonar.plugins.openedge.foundation.OpenEdgeComponents.java Source code

Java tutorial

Introduction

Here is the source code for org.sonar.plugins.openedge.foundation.OpenEdgeComponents.java

Source

/*
 * OpenEdge plugin for SonarQube
 * Copyright (C) 2013-2016 Riverside Software
 * contact AT riverside DASH software DOT fr
 * 
 * This program 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.
 *
 * This program 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  02
 */
package org.sonar.plugins.openedge.foundation;

import java.lang.reflect.Field;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.BatchSide;
import org.sonar.api.batch.rule.ActiveRule;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.platform.Server;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.MessageException;
import org.sonar.check.RuleProperty;
import org.sonar.plugins.openedge.api.CheckRegistrar;
import org.sonar.plugins.openedge.api.LicenceRegistrar;
import org.sonar.plugins.openedge.api.LicenceRegistrar.Licence;
import org.sonar.plugins.openedge.api.checks.OpenEdgeCheck;
import org.sonar.plugins.openedge.api.checks.OpenEdgeDumpFileCheck;
import org.sonar.plugins.openedge.api.checks.OpenEdgeProparseCheck;
import org.sonar.plugins.openedge.api.checks.OpenEdgeXrefCheck;
import org.sonar.plugins.openedge.api.com.google.common.base.Strings;

@BatchSide
public class OpenEdgeComponents {
    private static final Logger LOG = LoggerFactory.getLogger(OpenEdgeComponents.class);

    // IoC
    private final Server server;
    private final ActiveRules activeRules;

    private final List<Class<? extends OpenEdgeCheck>> checkClasses = new ArrayList<>();

    private final Map<ActiveRule, OpenEdgeProparseCheck> ppChecksMap = new HashMap<>();
    private final Map<ActiveRule, OpenEdgeXrefCheck> xrefChecksMap = new HashMap<>();
    private final Map<ActiveRule, OpenEdgeDumpFileCheck> dfChecksMap = new HashMap<>();

    private boolean initialized = false;
    private final List<OpenEdgeProparseCheck> ppChecks = new ArrayList<>();
    private final List<OpenEdgeXrefCheck> xrefChecks = new ArrayList<>();
    private final List<OpenEdgeDumpFileCheck> dfChecks = new ArrayList<>();

    private final Map<String, Licence> licences = new HashMap<>();

    public OpenEdgeComponents(ActiveRules activeRules, Server server, CheckRegistrar[] checkRegistrars,
            LicenceRegistrar[] licRegistrars) {
        this.activeRules = activeRules;
        this.server = server;

        if (checkRegistrars != null) {
            registerChecks(checkRegistrars);
        }
        if (licRegistrars != null) {
            registerLicences(licRegistrars, Strings.nullToEmpty(server.getPermanentServerId()));
        }
    }

    private void registerChecks(CheckRegistrar[] checkRegistrars) {
        for (CheckRegistrar reg : checkRegistrars) {
            CheckRegistrar.RegistrarContext registrarContext = new CheckRegistrar.RegistrarContext();
            reg.register(registrarContext);
            for (Class<? extends OpenEdgeXrefCheck> analyzer : registrarContext.getXrefCheckClasses()) {
                LOG.debug("{} XREF check registered", analyzer.getName());
                checkClasses.add(analyzer);
            }
            for (Class<? extends OpenEdgeProparseCheck> analyzer : registrarContext.getProparseCheckClasses()) {
                LOG.debug("{} Proparse check registered", analyzer.getName());
                checkClasses.add(analyzer);
            }
            for (Class<? extends OpenEdgeDumpFileCheck> analyzer : registrarContext.getDbCheckClasses()) {
                LOG.debug("{} DF check registered", analyzer.getName());
                checkClasses.add(analyzer);
            }
        }
    }

    private void registerLicences(LicenceRegistrar[] licRegistrars, String permanentId) {
        for (LicenceRegistrar reg : licRegistrars) {
            LicenceRegistrar.Licence lic = new LicenceRegistrar.Licence();
            reg.register(lic);
            if (lic.getRepositoryName().isEmpty()) {
                continue;
            }
            LOG.info("Found {} licence - Permanent ID '{}' - Customer '{}' - Repository '{}' - Expiration date {}",
                    lic.getType().toString(), lic.getPermanentId(), lic.getCustomerName(), lic.getRepositoryName(),
                    DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG)
                            .format(new Date(lic.getExpirationDate())));
            if (!lic.getPermanentId().isEmpty() && !permanentId.equals(lic.getPermanentId())) {
                LOG.info("Skipped licence as it doesn't match permanent ID '{}'", permanentId);
                continue;
            }
            // Licence with highest expiration date wins
            Licence existingLic = licences.get(lic.getRepositoryName());
            if ((existingLic == null) || (existingLic.getExpirationDate() < lic.getExpirationDate())) {
                licences.put(lic.getRepositoryName(), lic);
                LOG.info("Installed !");
            } else {
                LOG.info("Conflict, skipped licence");
            }
        }
        for (Entry<String, Licence> entry : licences.entrySet()) {
            LOG.info(
                    "Licence summary - Repository '{}' associated with {} licence permanent ID '{}' - Customer '{}' - Expiration date {}",
                    entry.getKey(), entry.getValue().getType().toString(), entry.getValue().getPermanentId(),
                    entry.getValue().getCustomerName(),
                    DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG)
                            .format(new Date(entry.getValue().getExpirationDate())));
        }
    }

    public void initializeChecks(SensorContext context) {
        if (initialized)
            return;

        for (ActiveRule rule : activeRules.findByLanguage(OpenEdge.KEY)) {
            RuleKey ruleKey = rule.ruleKey();
            // AFAIK, no way to be sure if a rule is based on a template or not
            String clsName = rule.templateRuleKey() == null ? ruleKey.rule() : rule.templateRuleKey();
            OpenEdgeCheck lint = getAnalyzer(clsName, ruleKey, context, getLicence(ruleKey.repository()),
                    Strings.nullToEmpty(server.getPermanentServerId()));
            if (lint != null) {
                configureFields(rule, lint);
                lint.initialize();
                switch (lint.getCheckType()) {
                case DUMP_FILE:
                    dfChecks.add((OpenEdgeDumpFileCheck) lint);
                    dfChecksMap.put(rule, (OpenEdgeDumpFileCheck) lint);
                    break;
                case PROPARSE:
                    ppChecks.add((OpenEdgeProparseCheck) lint);
                    ppChecksMap.put(rule, (OpenEdgeProparseCheck) lint);
                    break;
                case XREF:
                    xrefChecks.add((OpenEdgeXrefCheck) lint);
                    xrefChecksMap.put(rule, (OpenEdgeXrefCheck) lint);
                    break;
                }
            }
        }
        initialized = true;
    }

    public Collection<OpenEdgeProparseCheck> getProparseChecks() {
        return Collections.unmodifiableList(ppChecks);
    }

    public Map<ActiveRule, OpenEdgeProparseCheck> getProparseRules() {
        return Collections.unmodifiableMap(ppChecksMap);
    }

    public Collection<OpenEdgeDumpFileCheck> getDumpFileChecks() {
        return Collections.unmodifiableList(dfChecks);
    }

    public Map<ActiveRule, OpenEdgeDumpFileCheck> getDumpFileRules() {
        return Collections.unmodifiableMap(dfChecksMap);
    }

    public Collection<OpenEdgeXrefCheck> getXrefChecks() {
        return Collections.unmodifiableList(xrefChecks);
    }

    public Map<ActiveRule, OpenEdgeXrefCheck> getXrefRules() {
        return Collections.unmodifiableMap(xrefChecksMap);
    }

    private Licence getLicence(String repoName) {
        return licences.get(repoName);
    }

    private OpenEdgeCheck getAnalyzer(String internalKey, RuleKey ruleKey, SensorContext context, Licence licence,
            String permanentId) {
        try {
            for (Class<? extends OpenEdgeCheck> clz : checkClasses) {
                if (clz.getCanonicalName().equalsIgnoreCase(internalKey)) {
                    return clz.getConstructor(RuleKey.class, SensorContext.class, Licence.class, String.class)
                            .newInstance(ruleKey, context, licence, permanentId);
                }
            }
            return null;
        } catch (ReflectiveOperationException caught) {
            LOG.error("Unable to instantiate Proparse rule " + internalKey);
            return null;
        }
    }

    private static void configureFields(ActiveRule activeRule, Object check) {
        for (String param : activeRule.params().keySet()) {
            Field field = getField(check, param);
            if (field == null) {
                throw MessageException.of("The field " + param
                        + " does not exist or is not annotated with @RuleProperty in the class "
                        + check.getClass().getName());
            }
            if (StringUtils.isNotBlank(activeRule.param(param))) {
                configureField(check, field, activeRule.param(param));
            }
        }
    }

    private static void configureField(Object check, Field field, String value) {
        try {
            field.setAccessible(true);

            if (field.getType().equals(String.class)) {
                field.set(check, value);
            } else if (int.class == field.getType()) {
                field.setInt(check, Integer.parseInt(value));
            } else if (short.class == field.getType()) {
                field.setShort(check, Short.parseShort(value));
            } else if (long.class == field.getType()) {
                field.setLong(check, Long.parseLong(value));
            } else if (double.class == field.getType()) {
                field.setDouble(check, Double.parseDouble(value));
            } else if (boolean.class == field.getType()) {
                field.setBoolean(check, Boolean.parseBoolean(value));
            } else if (byte.class == field.getType()) {
                field.setByte(check, Byte.parseByte(value));
            } else if (Integer.class == field.getType()) {
                field.set(check, new Integer(Integer.parseInt(value)));
            } else if (Long.class == field.getType()) {
                field.set(check, new Long(Long.parseLong(value)));
            } else if (Double.class == field.getType()) {
                field.set(check, new Double(Double.parseDouble(value)));
            } else if (Boolean.class == field.getType()) {
                field.set(check, Boolean.valueOf(Boolean.parseBoolean(value)));
            } else {
                throw MessageException
                        .of("The type of the field " + field + " is not supported: " + field.getType());
            }
        } catch (IllegalAccessException e) {
            throw MessageException.of(
                    "Can not set the value of the field " + field + " in the class: " + check.getClass().getName(),
                    e);
        }
    }

    private static Field getField(Object check, String key) {
        Field[] fields = check.getClass().getDeclaredFields();
        for (Field field : fields) {
            RuleProperty propertyAnnotation = field.getAnnotation(RuleProperty.class);
            if (propertyAnnotation != null) {
                if (StringUtils.equals(key, field.getName()) || StringUtils.equals(key, propertyAnnotation.key())) {
                    return field;
                }
            }
        }
        return null;
    }

}