com.headwire.aem.tooling.intellij.action.VerifyConfigurationAction.java Source code

Java tutorial

Introduction

Here is the source code for com.headwire.aem.tooling.intellij.action.VerifyConfigurationAction.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 com.headwire.aem.tooling.intellij.action;

import com.headwire.aem.tooling.intellij.communication.MessageManager;
import com.headwire.aem.tooling.intellij.communication.ServerConnectionManager;
import com.headwire.aem.tooling.intellij.config.ServerConfiguration;
import com.headwire.aem.tooling.intellij.config.ServerConfigurationManager;
import com.headwire.aem.tooling.intellij.explorer.SlingServerTreeSelectionHandler;
import com.headwire.aem.tooling.intellij.util.ComponentProvider;
import com.headwire.aem.tooling.intellij.util.Constants;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.impl.SimpleDataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
import org.apache.sling.ide.filter.Filter;
import org.apache.sling.ide.filter.FilterResult;
import org.apache.sling.ide.io.ConnectorException;
import org.apache.sling.ide.transport.Repository;
import org.apache.sling.ide.transport.ResourceProxy;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * Created by Andreas Schaefer (Headwire.com) on 6/12/15.
 */
public class VerifyConfigurationAction extends AbstractProjectAction {

    public static final String VERIFY_CONTENT_WITH_WARNINGS = "VerifyContentWithWarnings";

    private volatile CountDownLatch stopSignal = new CountDownLatch(1);

    public VerifyConfigurationAction() {
        super("action.verify.configuration");
    }

    @Override
    protected boolean isAsynchronous() {
        return false;
    }

    @Override
    protected void execute(@NotNull Project project, @NotNull DataContext dataContext,
            final ProgressHandler progressHandler) {
        DataContext wrappedDataContext = SimpleDataContext.getSimpleContext(VERIFY_CONTENT_WITH_WARNINGS, true,
                dataContext);
        boolean verificationSuccessful = doVerify(project, wrappedDataContext, progressHandler);
        // Notification are added
        if (ApplicationManager.getApplication().isDispatchThread()) {
            getMessageManager(project).showAlertWithArguments(NotificationType.INFORMATION,
                    verificationSuccessful ? "server.configuration.verification.successful"
                            : "server.configuration.verification.failed");
        } else {
            getMessageManager(project)
                    .sendNotification(verificationSuccessful ? "server.configuration.verification.successful"
                            : "server.configuration.verification.failed", NotificationType.INFORMATION);
        }
    }

    @Override
    protected boolean isEnabled(@NotNull Project project, @NotNull DataContext dataContext) {
        ServerConnectionManager serverConnectionManager = ComponentProvider.getComponent(project,
                ServerConnectionManager.class);
        // A user should be able to verify the project without connecting to it as it is done already
        return serverConnectionManager != null && serverConnectionManager.isConfigurationSelected();
    }

    /**
     * Verity the project setup
     * @param project
     * @param dataContext
     * @param progressHandler Progress Handler
     * @return True if the project was successfully verified
     */
    public boolean doVerify(final Project project, final DataContext dataContext,
            final ProgressHandler progressHandler) {
        ProgressHandler progressHandlerSubTask = progressHandler == null ? new EmptyProgresssHandler()
                : progressHandler.startSubTasks(1, "progress.verify.project", project.getName());
        progressHandlerSubTask.next("progress.verify.check.environment");
        MessageManager messageManager = getMessageManager(project);
        boolean ret = true;
        int exitNow = Messages.OK;
        SlingServerTreeSelectionHandler selectionHandler = getSelectionHandler(project);
        ServerConnectionManager serverConnectionManager = ComponentProvider.getComponent(project,
                ServerConnectionManager.class);
        ServerConfigurationManager serverConfigurationManager = getConfigurationManager(project);
        if (selectionHandler != null && serverConnectionManager != null && messageManager != null) {
            ServerConfiguration source = selectionHandler.getCurrentConfiguration();
            if (source != null) {
                try {
                    progressHandlerSubTask.next("progress.verify.rebind.module");
                    messageManager.sendInfoNotification("server.configuration.start.verification",
                            source.getName());
                    // Before we can verify we need to ensure the Configuration is properly bound to Maven
                    List<ServerConfiguration.Module> unboundModules = null;
                    try {
                        unboundModules = serverConnectionManager.findUnboundModules(source);
                    } catch (IllegalArgumentException e) {
                        messageManager.showAlertWithOptions(NotificationType.ERROR,
                                "server.configuration.verification.failed.due.to.bind.exception", source.getName(),
                                e.getMessage());
                        return false;
                    } finally {
                        serverConfigurationManager.updateCurrentServerConfiguration();
                    }
                    if (unboundModules != null && !unboundModules.isEmpty()) {
                        progressHandlerSubTask.next("progress.verify.update.server.configuration");
                        ret = false;
                        ProgressHandler progressHandlerSubTaskLoop = progressHandlerSubTask
                                .startSubTasks(unboundModules.size(), "Check Server Configuration Modules");
                        for (ServerConfiguration.Module module : unboundModules) {
                            progressHandlerSubTaskLoop.next("progress.veriy.update.server.configuration",
                                    module.getName());
                            exitNow = messageManager.showAlertWithOptions(NotificationType.WARNING,
                                    "server.configuration.unresolved.module", module.getName());
                            if (exitNow == 1) {
                                source.removeModule(module);
                                if (serverConfigurationManager != null) {
                                    serverConfigurationManager.updateServerConfiguration(source);
                                }
                            } else if (exitNow == Messages.CANCEL) {
                                return false;
                            }
                        }
                    }
                    // Verify each Module to see if all prerequisites are met
                    Repository repository = ServerConnectionManager.obtainRepository(source, messageManager);
                    if (repository != null) {
                        progressHandlerSubTask.next("progress.verify.check.modules");
                        ProgressHandler progressHandlerSubTaskLoop = progressHandlerSubTask
                                .startSubTasks(2 * source.getModuleList().size(), "progress.verify.check.modules");
                        for (ServerConfiguration.Module module : source.getModuleList()) {
                            progressHandlerSubTaskLoop.next("progress.verify.check.module", module.getName());
                            if (module.isSlingPackage()) {
                                // Check if the Filter is available for Content Modules
                                Filter filter = null;
                                try {
                                    filter = module.getSlingProject().loadFilter();
                                    if (filter == null) {
                                        ret = false;
                                        exitNow = messageManager.showAlertWithOptions(NotificationType.ERROR,
                                                "server.configuration.filter.file.not.found", module.getName());
                                        module.setStatus(ServerConfiguration.SynchronizationStatus.compromised);
                                        if (exitNow == Messages.CANCEL) {
                                            return false;
                                        }
                                    }
                                } catch (ConnectorException e) {
                                    ret = false;
                                    exitNow = messageManager.showAlertWithOptions(NotificationType.ERROR,
                                            "server.configuration.filter.file.failure", module.getName(),
                                            e.getMessage());
                                    module.setStatus(ServerConfiguration.SynchronizationStatus.compromised);
                                    if (exitNow == Messages.CANCEL) {
                                        return false;
                                    }
                                }
                                // Check if the Content Modules have a Content Resource
                                List<String> resourceList = serverConnectionManager.findContentResources(module);
                                if (resourceList.isEmpty()) {
                                    ret = false;
                                    exitNow = messageManager.showAlertWithOptions(NotificationType.ERROR,
                                            "server.configuration.content.folder.not.found", module.getName());
                                    module.setStatus(ServerConfiguration.SynchronizationStatus.compromised);
                                    if (exitNow == Messages.CANCEL) {
                                        return false;
                                    }
                                }
                                // Check if Content Module Folders all have a .content.xml
                                Object temp = dataContext.getData(VERIFY_CONTENT_WITH_WARNINGS);
                                boolean verifyWithWarnings = !(temp instanceof Boolean) || ((Boolean) temp);
                                if (verifyWithWarnings && filter != null) {
                                    progressHandlerSubTaskLoop.next("progress.verify.check.resource.files");
                                    ProgressHandler progressHandlerSubTaskLoop2 = progressHandlerSubTaskLoop
                                            .startSubTasks(resourceList.size(), "Check Resources");
                                    // Get the Content Root /jcr_root)
                                    for (String contentPath : resourceList) {
                                        progressHandlerSubTaskLoop2.next("progress.verify.check.resource.files",
                                                contentPath);
                                        VirtualFile rootFile = project.getProjectFile().getFileSystem()
                                                .findFileByPath(contentPath);
                                        if (rootFile != null) {
                                            // Loop over all folders and check if .content.xml file is there
                                            Result childResult = checkFolderContent(repository, messageManager,
                                                    serverConnectionManager, module, null, rootFile, filter);
                                            if (childResult.isCancelled) {
                                                return false;
                                            } else if (!childResult.isOk) {
                                                ret = false;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    } else {
                        ret = false;
                    }
                } catch (RuntimeException e) {
                    messageManager.sendUnexpectedException(e);
                } finally {
                    messageManager.sendInfoNotification("server.configuration.end.verification", source.getName());
                }
            }
        }
        return ret;
    }

    private Result checkFolderContent(Repository repository, MessageManager messageManager,
            ServerConnectionManager serverConnectionManager, ServerConfiguration.Module module, File rootDirectory,
            VirtualFile parentDirectory, Filter filter) {
        int exitNow = Messages.OK;
        Result ret = new Result();
        // Loop over all files in the given folder
        for (VirtualFile child : parentDirectory.getChildren()) {
            // We only need to check Folders
            if (child.isDirectory()) {
                // If the Root Directory is null then just started -> Create Root Directory File and work on its children
                if (rootDirectory == null) {
                    rootDirectory = new File(parentDirectory.getPath());
                } else {
                    // Get Relative Paths
                    String relativeParentPath = parentDirectory.getPath()
                            .substring(rootDirectory.getPath().length());
                    String relativeChildPath = child.getPath().substring(rootDirectory.getPath().length());
                    List<ResourceProxy> childNodes = null;
                    FilterResult filterResult = null;
                    if (filter != null) {
                        // Check if the Resource is part of the Filter
                        filterResult = filter.filter(relativeChildPath);
                    }
                    // We don't need to check anything if it is part of one of the filter entries
                    if (filterResult != FilterResult.ALLOW) {
                        if (filterResult == FilterResult.DENY) {
                            ret.failed();
                            // File is not part of a filter entry so it will never be deployed
                            exitNow = messageManager.showAlertWithOptions(NotificationType.ERROR,
                                    "server.configuration.content.folder.filtered.out", relativeChildPath,
                                    module.getName());
                            module.setStatus(ServerConfiguration.SynchronizationStatus.compromised);
                            if (exitNow == Messages.CANCEL) {
                                return ret.doExit();
                            }
                        } else if (child.findChild(Constants.CONTENT_FILE_NAME) == null) {
                            boolean isOk = false;
                            if (repository != null && childNodes == null) {
                                // First check if there are only folders as children and if all of them are inside the filters
                                boolean isGood = true;
                                for (VirtualFile grandChild : child.getChildren()) {
                                    filterResult = filter.filter(relativeChildPath + "/" + grandChild.getName());
                                    if (filterResult != FilterResult.ALLOW) {
                                        isGood = false;
                                        break;
                                    }
                                }
                                if (isGood) {
                                    isOk = true;
                                } else {
                                    // .content.xml file not found in the filter -> check if that folder exists on the Server
                                    childNodes = serverConnectionManager.getChildrenNodes(repository,
                                            relativeParentPath);
                                    for (ResourceProxy childNode : childNodes) {
                                        String path = childNode.getPath();
                                        boolean found = path.equals(relativeChildPath);
                                        if (found) {
                                            isOk = true;
                                            break;
                                        }
                                    }
                                }
                            }
                            if (!isOk) {
                                ret.failed();
                                exitNow = messageManager.showAlertWithOptions(NotificationType.ERROR,
                                        "server.configuration.content.folder.configuration.not.found",
                                        relativeChildPath, module.getName());
                                module.setStatus(ServerConfiguration.SynchronizationStatus.compromised);
                                if (exitNow == Messages.CANCEL) {
                                    return ret.doExit();
                                }
                            }
                        }
                    }
                }
                // Check the children of the current folder
                Result childResult = checkFolderContent(repository, messageManager, serverConnectionManager, module,
                        rootDirectory, child, filter);
                if (childResult.isCancelled) {
                    return ret.doExit();
                } else if (!childResult.isOk) {
                    ret.failed();
                }
            }
        }
        return ret;
    }

    private static class Result {
        private boolean isCancelled = false;
        private boolean isOk = true;

        public Result doExit() {
            isCancelled = true;
            isOk = false;
            return this;
        }

        public Result failed() {
            isOk = false;
            return this;
        }
    }

    public static class EmptyProgresssHandler implements ProgressHandler {

        @Override
        public ProgressHandler startSubTasks(int Steps, String title) {
            return new EmptyProgresssHandler();
        }

        @Override
        public ProgressHandler startSubTasks(int Steps, String title, String... params) {
            return new EmptyProgresssHandler();
        }

        @Override
        public void next(String task) {
        }

        @Override
        public void next(String task, String... params) {

        }

        @Override
        public String getTitle() {
            return "Empty";
        }

        @Override
        public void markAsCancelled() {
        }

        @Override
        public boolean isMarkedAsCancelled() {
            return false;
        }

        @Override
        public void setNotCancelable(boolean notCancelable) {
        }

        @Override
        public boolean isNotCancelable() {
            return false;
        }
    }
}