net.sf.eclipsecs.core.config.GlobalCheckConfigurationWorkingSet.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.eclipsecs.core.config.GlobalCheckConfigurationWorkingSet.java

Source

//============================================================================
//
// Copyright (C) 2002-2014  David Schneider, Lars Kdderitzsch
//
// This library 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 2.1 of the License, or (at your option) any later version.
//
// This library 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 library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//============================================================================

package net.sf.eclipsecs.core.config;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sf.eclipsecs.core.CheckstylePlugin;
import net.sf.eclipsecs.core.Messages;
import net.sf.eclipsecs.core.config.configtypes.BuiltInConfigurationType;
import net.sf.eclipsecs.core.config.configtypes.IConfigurationType;
import net.sf.eclipsecs.core.projectconfig.FileSet;
import net.sf.eclipsecs.core.projectconfig.IProjectConfiguration;
import net.sf.eclipsecs.core.projectconfig.ProjectConfigurationFactory;
import net.sf.eclipsecs.core.projectconfig.ProjectConfigurationWorkingCopy;
import net.sf.eclipsecs.core.util.CheckstyleLog;
import net.sf.eclipsecs.core.util.CheckstylePluginException;
import net.sf.eclipsecs.core.util.XMLUtil;

import org.apache.commons.io.IOUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;

/**
 * Working set implementation that manages global configurations configured for the Eclipse workspace.
 * 
 * @author Lars Kdderitzsch
 */
public class GlobalCheckConfigurationWorkingSet implements ICheckConfigurationWorkingSet {

    /** The internal list of working copies belonging to this working set. */
    private final List<CheckConfigurationWorkingCopy> mWorkingCopies;

    /** List of working copies that were deleted from the working set. */
    private final List<CheckConfigurationWorkingCopy> mDeletedConfigurations;

    /** The default check configuration to be used for unconfigured projects. */
    private CheckConfigurationWorkingCopy mDefaultCheckConfig;

    /** The default built-in check configuration to be used for unconfigured projects. */
    private ICheckConfiguration mDefaultBuiltInCheckConfig;

    /**
     * Creates a working set to manage global configurations.
     * 
     * @param checkConfigs
     *            the list of global check configurations
     * @param defaultConfig
     *            the defaul check configuration
     */
    GlobalCheckConfigurationWorkingSet(List<ICheckConfiguration> checkConfigs, ICheckConfiguration defaultConfig,
            ICheckConfiguration defaultBuiltInCheckConfiguration) {

        mWorkingCopies = new ArrayList<CheckConfigurationWorkingCopy>();
        mDeletedConfigurations = new ArrayList<CheckConfigurationWorkingCopy>();
        mDefaultBuiltInCheckConfig = defaultBuiltInCheckConfiguration;

        for (ICheckConfiguration cfg : checkConfigs) {

            CheckConfigurationWorkingCopy workingCopy = new CheckConfigurationWorkingCopy(cfg, this);
            mWorkingCopies.add(workingCopy);

            if (cfg == defaultConfig) {
                mDefaultCheckConfig = workingCopy;
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    public CheckConfigurationWorkingCopy newWorkingCopy(ICheckConfiguration checkConfig) {
        return new CheckConfigurationWorkingCopy(checkConfig, this);
    }

    /**
     * {@inheritDoc}
     */
    public CheckConfigurationWorkingCopy newWorkingCopy(IConfigurationType configType) {
        return new CheckConfigurationWorkingCopy(configType, this, true);
    }

    /**
     * {@inheritDoc}
     */
    public CheckConfigurationWorkingCopy[] getWorkingCopies() {
        return mWorkingCopies.toArray(new CheckConfigurationWorkingCopy[mWorkingCopies.size()]);
    }

    /**
     * {@inheritDoc}
     */
    public void addCheckConfiguration(CheckConfigurationWorkingCopy checkConfig) {
        mWorkingCopies.add(checkConfig);
    }

    /**
     * Returns the default check configuration or <code>null</code> if none is set.
     * 
     * @return the default check configuration
     */
    public CheckConfigurationWorkingCopy getDefaultCheckConfig() {
        return mDefaultCheckConfig;
    }

    /**
     * Sets the default check configuration.
     * 
     * @param defaultCheckConfig
     *            the default check configuration
     */
    public void setDefaultCheckConfig(CheckConfigurationWorkingCopy defaultCheckConfig) {
        this.mDefaultCheckConfig = defaultCheckConfig;
    }

    /**
     * {@inheritDoc}
     */
    public boolean removeCheckConfiguration(CheckConfigurationWorkingCopy checkConfig) {
        boolean used = true;
        try {
            used = ProjectConfigurationFactory.isCheckConfigInUse(checkConfig.getSourceCheckConfiguration());

            if (!used) {
                mWorkingCopies.remove(checkConfig);

                // reset default check config
                if (mDefaultCheckConfig == checkConfig) {
                    mDefaultCheckConfig = null;
                }

                mDeletedConfigurations.add(checkConfig);
            }
        } catch (CheckstylePluginException e) {
            CheckstyleLog.log(e);
        }
        return !used;
    }

    /**
     * {@inheritDoc}
     */
    public void store() throws CheckstylePluginException {
        updateProjectConfigurations();
        storeToPersistence();
        notifyDeletedCheckConfigs();
        CheckConfigurationFactory.refresh();
    }

    /**
     * {@inheritDoc}
     */
    public boolean isDirty() {
        if (mDeletedConfigurations.size() > 0) {
            return true;
        }

        boolean dirty = false;
        for (CheckConfigurationWorkingCopy workingCopy : mWorkingCopies) {
            dirty = workingCopy.isDirty();

            if (dirty) {
                break;
            }
        }
        return dirty;
    }

    /**
     * {@inheritDoc}
     */
    public Collection<IProject> getAffectedProjects() throws CheckstylePluginException {

        Set<IProject> projects = new HashSet<IProject>();

        CheckConfigurationWorkingCopy[] workingCopies = this.getWorkingCopies();
        for (int i = 0; i < workingCopies.length; i++) {

            // skip non dirty configurations
            if (!workingCopies[i].hasConfigurationChanged()) {
                continue;
            }

            List<IProject> usingProjects = ProjectConfigurationFactory.getProjectsUsingConfig(workingCopies[i]);

            for (IProject proj : usingProjects) {
                projects.add(proj);
            }
        }

        return projects;
    }

    /**
     * {@inheritDoc}
     */
    public boolean isNameCollision(CheckConfigurationWorkingCopy configuration) {

        boolean result = false;
        for (CheckConfigurationWorkingCopy tmp : mWorkingCopies) {
            if (tmp != configuration && tmp.getName().equals(configuration.getName())) {
                result = true;
                break;
            }
        }
        return result;
    }

    /**
     * Updates the project configurations that use the changed check configurations.
     * 
     * @param configurations
     *            the check configurations
     * @throws CheckstylePluginException
     *             an unexpected exception occurred
     */
    private void updateProjectConfigurations() throws CheckstylePluginException {

        for (CheckConfigurationWorkingCopy checkConfig : mWorkingCopies) {

            ICheckConfiguration original = checkConfig.getSourceCheckConfiguration();

            // only if the name of the check config differs from the original
            if (original != null && original.getName() != null
                    && !checkConfig.getName().equals(original.getName())) {

                List<IProject> projects = ProjectConfigurationFactory.getProjectsUsingConfig(checkConfig);
                for (IProject project : projects) {

                    IProjectConfiguration projectConfig = ProjectConfigurationFactory.getConfiguration(project);

                    ProjectConfigurationWorkingCopy workingCopy = new ProjectConfigurationWorkingCopy(
                            projectConfig);

                    List<FileSet> fileSets = workingCopy.getFileSets();
                    for (FileSet fileSet : fileSets) {

                        // Check if the fileset uses the check config
                        if (original.equals(fileSet.getCheckConfig())) {
                            // set the new check configuration
                            fileSet.setCheckConfig(checkConfig);
                        }
                    }

                    // store the project configuration
                    if (workingCopy.isDirty()) {
                        workingCopy.store();
                    }
                }
            }
        }
    }

    /**
     * Store the check configurations to the persistent state storage.
     */
    private void storeToPersistence() throws CheckstylePluginException {

        BufferedOutputStream out = null;

        try {

            IPath configPath = CheckstylePlugin.getDefault().getStateLocation();
            configPath = configPath.append(CheckConfigurationFactory.CHECKSTYLE_CONFIG_FILE);
            File configFile = configPath.toFile();

            ICheckConfiguration defaultConfig = mDefaultCheckConfig;

            // don't store as default when it's already the built-in default
            if (defaultConfig != null && defaultConfig.getName().equals(mDefaultBuiltInCheckConfig.getName())) {
                defaultConfig = null;
            }

            Document doc = createCheckConfigurationsDocument(mWorkingCopies, defaultConfig);

            // write to the file after the document creation was successful
            // prevents corrupted files in case of error
            out = new BufferedOutputStream(new FileOutputStream(configFile));
            out.write(XMLUtil.toByteArray(doc));
        } catch (IOException e) {
            CheckstylePluginException.rethrow(e, Messages.errorWritingConfigFile);
        } finally {
            IOUtils.closeQuietly(out);
        }
    }

    /**
     * Notifies the check configurations that have been deleted.
     * 
     * @throws CheckstylePluginException
     *             an exception while notifiing for deletion
     */
    private void notifyDeletedCheckConfigs() throws CheckstylePluginException {

        for (ICheckConfiguration checkConfig : mDeletedConfigurations) {
            checkConfig.getType().notifyCheckConfigRemoved(checkConfig);
        }
    }

    /**
     * Transforms the check configurations to a document.
     */
    private static Document createCheckConfigurationsDocument(List<CheckConfigurationWorkingCopy> configurations,
            ICheckConfiguration defaultConfig) {

        Document doc = DocumentHelper.createDocument();
        Element root = doc.addElement(XMLTags.CHECKSTYLE_ROOT_TAG);
        root.addAttribute(XMLTags.VERSION_TAG, CheckConfigurationFactory.CURRENT_CONFIG_FILE_FORMAT_VERSION);

        if (defaultConfig != null) {
            root.addAttribute(XMLTags.DEFAULT_CHECK_CONFIG_TAG, defaultConfig.getName());
        }

        for (ICheckConfiguration config : configurations) {

            // don't store built-in configurations to persistence or local
            // configurations
            if (config.getType() instanceof BuiltInConfigurationType || !config.isGlobal()) {
                continue;
            }

            Element configEl = root.addElement(XMLTags.CHECK_CONFIG_TAG);
            configEl.addAttribute(XMLTags.NAME_TAG, config.getName());
            configEl.addAttribute(XMLTags.LOCATION_TAG, config.getLocation());
            configEl.addAttribute(XMLTags.TYPE_TAG, config.getType().getInternalName());
            if (config.getDescription() != null) {
                configEl.addAttribute(XMLTags.DESCRIPTION_TAG, config.getDescription());
            }

            // Write resolvable properties
            for (ResolvableProperty prop : config.getResolvableProperties()) {

                Element propEl = configEl.addElement(XMLTags.PROPERTY_TAG);
                propEl.addAttribute(XMLTags.NAME_TAG, prop.getPropertyName());
                propEl.addAttribute(XMLTags.VALUE_TAG, prop.getValue());
            }

            for (Map.Entry<String, String> entry : config.getAdditionalData().entrySet()) {

                Element addEl = configEl.addElement(XMLTags.ADDITIONAL_DATA_TAG);
                addEl.addAttribute(XMLTags.NAME_TAG, entry.getKey());
                addEl.addAttribute(XMLTags.VALUE_TAG, entry.getValue());
            }
        }
        return doc;
    }
}