com.ibm.liberty.starter.ProjectConstructor.java Source code

Java tutorial

Introduction

Here is the source code for com.ibm.liberty.starter.ProjectConstructor.java

Source

/*******************************************************************************
 * Copyright (c) 2016 IBM Corp.
 *
 * Licensed 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.ibm.liberty.starter;

import com.ibm.liberty.starter.api.v1.model.provider.Location;
import com.ibm.liberty.starter.api.v1.model.provider.Provider;
import com.ibm.liberty.starter.api.v1.model.provider.Sample;
import com.ibm.liberty.starter.api.v1.model.registration.Service;
import com.ibm.liberty.starter.build.FeaturesToInstallProvider;
import com.ibm.liberty.starter.build.gradle.*;
import com.ibm.liberty.starter.build.maven.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import java.io.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import com.ibm.liberty.starter.api.v1.model.internal.Services;
import com.ibm.liberty.starter.api.v1.model.provider.Location;
import com.ibm.liberty.starter.api.v1.model.provider.Provider;
import com.ibm.liberty.starter.api.v1.model.provider.Sample;
import com.ibm.liberty.starter.api.v1.model.registration.Service;
import com.ibm.liberty.starter.api.v1.temp.ServiceFinder;
import com.ibm.liberty.starter.build.maven.AddDependenciesCommand;
import com.ibm.liberty.starter.build.maven.AddFeaturesCommand;
import com.ibm.liberty.starter.build.maven.AppArtifactConfigCommand;
import com.ibm.liberty.starter.build.maven.AppNameCommand;
import com.ibm.liberty.starter.build.maven.PomModifierCommand;
import com.ibm.liberty.starter.build.maven.SetDefaultProfileCommand;
import com.ibm.liberty.starter.build.maven.SetRepositoryCommand;
import com.ibm.liberty.starter.build.maven.PomModifier;

public class ProjectConstructor {

    private static final Logger log = Logger.getLogger(ProjectConstructor.class.getName());
    private ConcurrentHashMap<String, byte[]> fileMap = new ConcurrentHashMap<>();
    private static final String SKELETON_FILENAME = "services/skeletonLibertyBuildImage.zip";
    private static final String BASE_INDEX_HTML = "payloadIndex.html";
    private static final String INDEX_HTML_PATH = "src/main/webapp/index.html";
    private static final String POM_FILE = "pom.xml";
    private static final String GRADLE_BUILD_FILE = "build.gradle";
    private static final String GRADLE_SETTINGS_FILE = "settings.gradle";
    private final ProjectConstructionInputData inputData;

    public ProjectConstructor(ProjectConstructionInputData inputData) {
        this.inputData = inputData;
    }

    public enum DeployType {
        LOCAL, BLUEMIX
    }

    public enum BuildType {
        MAVEN("mvn install liberty:run-server"), GRADLE("gradle build libertyStart");
        public String runInstruction;

        BuildType(String runInstruction) {
            this.runInstruction = runInstruction;
        }
    }

    public Map<String, byte[]> getFileMap() {
        return fileMap;
    }

    public Map<String, byte[]> buildFileMap()
            throws IOException, SAXException, ParserConfigurationException, TransformerException {
        initializeMap();
        addHtmlToMap();
        addTechSamplesToMap();
        addBuildFilesToMap();
        addDynamicPackages();
        cleanup();
        return fileMap;
    }

    private void cleanup() throws IOException {
        cleanUpDynamicPackages();
    }

    private void cleanUpDynamicPackages() throws IOException {
        // Delete dynamically generated packages as they were already packaged.
        // ** Note **: Don't delete these packages prior to this stage as other operations may depend on the existence of these packages to perform certain tasks.
        for (Service service : inputData.services.getServices()) {
            String serviceId = service.getId();

            String packageLocation = inputData.workspaceDirectory + "/" + serviceId + "/" + StarterUtil.PACKAGE_DIR;
            File packageDir = new File(packageLocation);

            if (packageDir.exists() && packageDir.isDirectory()) {
                FileUtils.deleteDirectory(packageDir);
                log.log(Level.FINE,
                        "Deleted package directory for " + serviceId + " technology. : " + packageLocation);
            }
        }
    }

    private void addDynamicPackages() throws IOException {
        log.log(Level.FINE, "Entering method ProjectConstructor.addDynamicPackages()");
        if (inputData.workspaceDirectory == null || inputData.workspaceDirectory.isEmpty()
                || !(new File(inputData.workspaceDirectory).exists())) {
            log.log(Level.FINE,
                    "No dynamic packages to add since workspace doesn't exist : " + inputData.workspaceDirectory);
            return;
        }

        for (Service service : inputData.services.getServices()) {
            String serviceId = service.getId();
            String packageLocation = inputData.workspaceDirectory + "/" + serviceId + "/" + StarterUtil.PACKAGE_DIR;
            File packageDir = new File(packageLocation);

            if (packageDir.exists() && packageDir.isDirectory()) {
                log.log(Level.FINE,
                        "Package directory for " + serviceId + " technology exists : " + packageLocation);
                List<File> filesListInDir = new ArrayList<File>();
                StarterUtil.populateFilesList(packageDir, filesListInDir);

                for (File aFile : filesListInDir) {
                    String path = aFile.getAbsolutePath().replace('\\', '/').replace(packageLocation, "");

                    if (path.startsWith("/")) {
                        path = path.substring(1);
                    }
                    putFileInMap(path, FileUtils.readFileToByteArray(aFile));
                    log.log(Level.FINE, "Packaged file " + aFile.getAbsolutePath() + " to " + path);
                }
            }
        }
        log.log(Level.FINE, "Exiting method ProjectConstructor.addDynamicPackages()");
    }

    public void initializeMap() throws IOException {
        log.log(Level.INFO, "Entering method ProjectConstructor.initializeMap()");
        InputStream skeletonIS = this.getClass().getClassLoader().getResourceAsStream(SKELETON_FILENAME);
        ZipInputStream zis = new ZipInputStream(skeletonIS);
        ZipEntry ze;
        while ((ze = zis.getNextEntry()) != null) {
            String path = ze.getName();
            int length = 0;
            byte[] bytes = new byte[1024];
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            while ((length = zis.read(bytes)) != -1) {
                baos.write(bytes, 0, length);
            }
            putFileInMap(path, baos.toByteArray());
        }
        zis.close();
    }

    public void addHtmlToMap() throws IOException {
        log.log(Level.INFO, "Entering method ProjectConstructor.addHtmlToMap()");
        byte[] html = getHtmlFile();
        putFileInMap(INDEX_HTML_PATH, html);
    }

    public byte[] getHtmlFile() throws IOException {
        InputStream htmlIS = this.getClass().getClassLoader().getResourceAsStream(BASE_INDEX_HTML);
        HashMap<String, byte[]> techDescriptions = new HashMap<String, byte[]>();
        for (Service service : inputData.services.getServices()) {
            Provider provider = inputData.serviceConnector.getProvider(service);
            String description = provider.getDescription();
            byte[] bytes = description.getBytes();
            techDescriptions.put(service.getId(), bytes);
        }

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        final int MAX_SIZE = 200000;
        char[] buffer = new char[MAX_SIZE];

        try (BufferedReader reader = new BufferedReader(new InputStreamReader(htmlIS));) {
            reader.read(buffer, 0, MAX_SIZE);
        } catch (Exception e) {
            return null;
        }
        String contents = new String(buffer);
        int index = contents.indexOf("<div id=\"technologies\">");
        if (index != -1) {
            int length = contents.length();
            String first = contents.substring(0, index);
            String last = contents.substring(index, length);
            baos.write(first.getBytes());
            Set<String> keys = techDescriptions.keySet();
            for (String key : keys) {
                baos.write(techDescriptions.get(key));
            }
            baos.write(last.getBytes());
        }
        return baos.toByteArray();
    }

    public void addTechSamplesToMap() throws IOException {
        log.log(Level.INFO, "Entering method ProjectConstructor.addTechSamplesToMap()");
        for (Service service : inputData.services.getServices()) {
            Sample sample = inputData.serviceConnector.getSample(service);
            Location[] locations = sample.getLocations();
            String basePath = sample.getBase();
            for (Location location : locations) {
                String fileUrl = location.getUrl();
                InputStream is = inputData.serviceConnector.getResourceAsInputStream(basePath + fileUrl);
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                IOUtils.copy(is, baos);
                is.close();
                byte[] bytes = baos.toByteArray();
                baos.close();
                if (fileUrl.startsWith("/")) {
                    fileUrl = fileUrl.substring(1);
                }
                putFileInMap(fileUrl, bytes);
            }
        }
    }

    private void addBuildFilesToMap()
            throws SAXException, TransformerException, ParserConfigurationException, IOException {
        log.log(Level.INFO, "Entering method ProjectConstructor.addBuildFilesToMap()");
        if (BuildType.GRADLE.equals(inputData.buildType)) {
            addGradleFilesToMap();
        } else {
            addPomFileToMap();
        }
    }

    private void addGradleFilesToMap() throws IOException {
        log.log(Level.INFO, "Entering method ProjectConstructor.addGradleFilesToMap()");
        Map<String, String> buildTags = new HashMap<>();
        DependencyHandler depHand = new DependencyHandler(inputData.services, inputData.serviceConnector,
                inputData.appName);
        buildTags.putAll(new CreateAppNameTags(depHand).getTags());
        buildTags.putAll(new CreateDependencyTags(depHand).getTags());
        buildTags.putAll(new CreateFeaturesTags(
                new FeaturesToInstallProvider(inputData.services, inputData.serviceConnector)).getTags());
        buildTags.putAll(new CreateRepositoryTags(depHand).getTags());
        buildTags.putAll(new CreateArtifactConfigTags(inputData.artifactId, inputData.groupId).getTags());
        TemplatedFileToBytesConverter gradleBuildFileConverter = new TemplatedFileToBytesConverter(
                this.getClass().getClassLoader().getResourceAsStream(GRADLE_BUILD_FILE), buildTags);
        putFileInMap(GRADLE_BUILD_FILE, gradleBuildFileConverter.getBytes());

        TemplatedFileToBytesConverter gradleSettingsFileConverter = new TemplatedFileToBytesConverter(
                this.getClass().getClassLoader().getResourceAsStream(GRADLE_SETTINGS_FILE), buildTags);
        putFileInMap(GRADLE_SETTINGS_FILE, gradleSettingsFileConverter.getBytes());
    }

    public void addPomFileToMap()
            throws SAXException, IOException, ParserConfigurationException, TransformerException {
        log.log(Level.INFO, "Entering method ProjectConstructor.addPomFileToMap()");
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(POM_FILE);
        Set<PomModifierCommand> commands = new HashSet<>();
        DependencyHandler depHand = new DependencyHandler(inputData.services, inputData.serviceConnector,
                inputData.appName);
        commands.add(new AddDependenciesCommand(depHand));
        commands.add(new AppNameCommand(depHand));
        commands.add(new SetDefaultProfileCommand(inputData.deployType));
        commands.add(new SetRepositoryCommand(depHand));
        commands.add(new AddFeaturesCommand(
                new FeaturesToInstallProvider(inputData.services, inputData.serviceConnector)));
        commands.add(new AppArtifactConfigCommand(inputData.artifactId, inputData.groupId));
        PomModifier pomModifier = new PomModifier(inputStream, commands);
        byte[] bytes = pomModifier.getPomBytes();
        putFileInMap("pom.xml", bytes);
    }

    public void putFileInMap(String path, byte[] file) {
        log.log(Level.INFO, "Inserting file " + path + " into map.");
        fileMap.put(path, file);
    }

}