Java tutorial
/* * Ejisto, a powerful developer assistant * * Copyright (C) 2010-2014 Celestino Bellone * * Ejisto is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Ejisto 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.ejisto.modules.vertx.handler; import com.ejisto.constants.StringConstants; import com.ejisto.core.container.ContainerManager; import com.ejisto.event.EventManager; import com.ejisto.event.def.ApplicationInstallFinalization; import com.ejisto.modules.cargo.NotInstalledException; import com.ejisto.modules.controller.wizard.installer.workers.ApplicationScanningWorker; import com.ejisto.modules.controller.wizard.installer.workers.FileExtractionWorker; import com.ejisto.modules.dao.entities.MockedField; import com.ejisto.modules.dao.entities.TemporaryWebApplicationDescriptor; import com.ejisto.modules.dao.entities.WebApplicationDescriptor; import com.ejisto.modules.dao.local.LocalWebApplicationDescriptorDao; import com.ejisto.modules.repository.ClassPoolRepository; import com.ejisto.modules.repository.ContainersRepository; import com.ejisto.modules.repository.CustomObjectFactoryRepository; import com.ejisto.modules.repository.MockedFieldsRepository; import com.ejisto.modules.vertx.handler.service.ApplicationInstallerRegistry; import com.ejisto.modules.web.util.JSONUtil; import com.ejisto.util.IOUtils; import com.ejisto.util.collector.MockedFieldCollector; import io.netty.handler.codec.http.HttpResponseStatus; import javassist.ClassPool; import lombok.extern.log4j.Log4j; import org.apache.commons.lang3.StringUtils; import org.vertx.java.core.Handler; import org.vertx.java.core.MultiMap; import org.vertx.java.core.buffer.Buffer; import org.vertx.java.core.http.HttpServerRequest; import org.vertx.java.core.http.RouteMatcher; import java.beans.PropertyChangeListener; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; import static com.ejisto.constants.StringConstants.GUI_TASK_EXCEPTION_PROPERTY; import static com.ejisto.modules.vertx.VertxManager.publishEvent; import static com.ejisto.modules.vertx.handler.Boilerplate.writeError; import static com.ejisto.modules.vertx.handler.Boilerplate.writeOutputAsJSON; /** * Created by IntelliJ IDEA. * User: celestino * Date: 4/30/14 * Time: 8:05 AM */ @Log4j public class ApplicationInstallerWizardHandler implements ContextHandler { private static final String SESSION_ID = "sessionID"; private final MockedFieldsRepository mockedFieldsRepository; private final CustomObjectFactoryRepository customObjectFactoryRepository; private final ContainerManager containerManager; private final LocalWebApplicationDescriptorDao webApplicationDescriptorDao; private final EventManager eventManager; private final ContainersRepository containersRepository; private final Handler<HttpServerRequest> uploadHandler = req -> { req.expectMultiPart(true); req.uploadHandler(fileHandler -> { String key = StringUtils.defaultString(req.params().get(SESSION_ID), UUID.randomUUID().toString()); ApplicationInstallerRegistry.putDescriptorIfAbsent(key, new TemporaryWebApplicationDescriptor()); TemporaryWebApplicationDescriptor session = ApplicationInstallerRegistry.getDescriptor(key) .map(TemporaryWebApplicationDescriptor.class::cast).orElseThrow(IllegalStateException::new); String fileName = fileHandler.filename(); Path war = Paths.get(System.getProperty("java.io.tmpdir"), key, fileName); initDirectory(war.getParent()); fileHandler.streamToFileSystem(war.toString()); fileHandler.exceptionHandler(event -> writeError(req, event)); fileHandler.endHandler(end -> { try { session.setWarFile(war.toFile()); FileExtractionWorker worker = new FileExtractionWorker(session, event -> { String propertyName = event.getPropertyName(); if (propertyName.equals("startProgress")) { publishEvent("StartFileExtraction", null); } else if (propertyName.equals("progressDescriptor")) { publishEvent("FileExtractionProgress", JSONUtil.encode(event.getNewValue())); } }); worker.work(); worker.get(); Map<String, Object> result = new HashMap<>(2); result.put(SESSION_ID, key); result.put("resources", session.getIncludedJars()); writeOutputAsJSON(result, req.response()); } catch (Exception e) { writeError(req, e); } }); }); }; private final Handler<HttpServerRequest> scanHandler = req -> { String sessionId = req.params().get(ApplicationInstallerWizardHandler.SESSION_ID); if (ApplicationInstallerRegistry.isPresent(sessionId)) { scanApplication(req, sessionId); } }; public ApplicationInstallerWizardHandler(MockedFieldsRepository mockedFieldsRepository, CustomObjectFactoryRepository customObjectFactoryRepository, ContainerManager containerManager, LocalWebApplicationDescriptorDao webApplicationDescriptorDao, EventManager eventManager, ContainersRepository containersRepository) { this.mockedFieldsRepository = mockedFieldsRepository; this.customObjectFactoryRepository = customObjectFactoryRepository; this.containerManager = containerManager; this.webApplicationDescriptorDao = webApplicationDescriptorDao; this.eventManager = eventManager; this.containersRepository = containersRepository; } @Override public void addRoutes(RouteMatcher routeMatcher) { routeMatcher.put("/application/new/upload", uploadHandler) .put("/application/new/:" + SESSION_ID + "/include", scanHandler) .post("/application/new/:" + SESSION_ID + "/publish", req -> { final MultiMap params = req.params(); req.bodyHandler(buffer -> { try { handleApplicationPublish(req, params, buffer); } catch (Exception e) { writeError(req, e); } }); }); } private void handleApplicationPublish(HttpServerRequest req, MultiMap params, Buffer buffer) throws NotInstalledException { List<MockedField> newFields = JSONUtil.decode(buffer.toString(), Boilerplate.MF_LIST_TYPE_REFERENCE); String sessionID = params.get(SESSION_ID); final Optional<TemporaryWebApplicationDescriptor> optional = ApplicationInstallerRegistry .getDescriptor(sessionID).map(TemporaryWebApplicationDescriptor.class::cast); if (!optional.isPresent()) { writeError(req, HttpResponseStatus.BAD_REQUEST.code(), "invalid sessionID"); return; } TemporaryWebApplicationDescriptor temporaryDescriptor = optional.get(); final Collection<MockedField> descriptorFields = temporaryDescriptor.getFields(); newFields.forEach(field -> descriptorFields.stream() .filter(f -> f.getComparisonKey().equals(field.getComparisonKey())).findFirst().ifPresent(f -> { f.setActive(true); f.setFieldValue(field.getFieldValue()); f.setExpression(field.getExpression()); })); final WebApplicationDescriptor descriptor = WebApplicationDescriptor.copyOf(temporaryDescriptor); descriptorFields.stream().forEach(f -> f.setContextPath(descriptor.getContextPath())); mockedFieldsRepository.deleteContext(descriptor.getContextPath()); mockedFieldsRepository.insert(descriptorFields); webApplicationDescriptorDao.insert(descriptor); ClassPool classPool = ClassPoolRepository.getRegisteredClassPool(temporaryDescriptor.getContextPath()); ClassPoolRepository.replaceClassPool(descriptor.getContextPath(), classPool); String containerID = Optional.ofNullable(descriptor.getContainerId()) .orElse(StringConstants.DEFAULT_CONTAINER_ID.getValue()); eventManager.publishEvent(new ApplicationInstallFinalization(this, descriptor, containersRepository.loadContainer(containerID))); req.response().setStatusCode(HttpResponseStatus.OK.code()).end(); } private void scanApplication(HttpServerRequest req, String sessionId) { final TemporaryWebApplicationDescriptor descriptor = ApplicationInstallerRegistry.getDescriptor(sessionId) .map(TemporaryWebApplicationDescriptor.class::cast).orElseThrow(IllegalStateException::new); Optional.ofNullable(req.params().get("resources")).map(s -> s.split(",")) .ifPresent(a -> descriptor.setWhiteList(Arrays.asList(a))); try { PropertyChangeListener listener = e -> { if (e.getPropertyName().equals(GUI_TASK_EXCEPTION_PROPERTY.getValue())) { writeError(req, (Throwable) e.getNewValue()); } }; descriptor.setId(sessionId); ApplicationScanningWorker worker = new ApplicationScanningWorker(listener, descriptor, mockedFieldsRepository, customObjectFactoryRepository, containerManager.getDefaultHome(), true); worker.addTaskExecutionListener(e -> { switch (e) { case DONE: writeOutputAsJSON(descriptor.getFields().parallelStream().collect(new MockedFieldCollector()), req.response()); break; case CANCELED: writeError(req, HttpResponseStatus.GONE.code(), "task has been canceled"); break; default: break; } }); worker.work(); } catch (Exception e) { writeError(req, e); log.error("error during application scanning", e); } } private void initDirectory(Path dir) { try { IOUtils.initPath(dir); } catch (IOException e) { throw new IllegalStateException(e); } } }