/* * 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 net.grinder; import net.grinder.communication.CommunicationException; import net.grinder.engine.communication.AgentUpdateGrinderMessage; import net.grinder.util.VersionNumber; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.builder.ToStringBuilder; import org.ngrinder.common.constants.AgentConstants; import org.ngrinder.common.util.CompressionUtils; import org.ngrinder.infra.AgentConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; import static org.ngrinder.common.constants.InternalConstants.PROP_INTERNAL_NGRINDER_VERSION; import static org.ngrinder.common.util.Preconditions.checkTrue; /** * Agent Update Message Handler. * * @author JunHo Yoon * @since 3.1 */ @SuppressWarnings("ResultOfMethodCallIgnored") public class AgentUpdateHandler implements Closeable { private static final Logger LOGGER = LoggerFactory.getLogger(AgentUpdateHandler.class); private final AgentConfig agentConfig; private File download; @SuppressWarnings("FieldCanBeLocal") private int offset = 0; private FileOutputStream agentOutputStream; /** * Agent Update handler. * * @param agentConfig agentConfig * @param message AgentUpdateGrinderMessage */ public AgentUpdateHandler(AgentConfig agentConfig, AgentUpdateGrinderMessage message) throws FileNotFoundException { if (!agentConfig.getAgentProperties().getPropertyBoolean(AgentConstants.PROP_AGENT_UPDATE_ALWAYS)) { checkTrue(isNewer(message.getVersion(), agentConfig.getInternalProperties().getProperty(PROP_INTERNAL_NGRINDER_VERSION)), "Update request was sent. But it's the older version " + message.getVersion()); } this.agentConfig = agentConfig; this.download = new File(agentConfig.getHome().getTempDirectory(), "ngrinder-agent.tar"); this.agentOutputStream = new FileOutputStream(download); LOGGER.info("AgentUpdateHandler is initialized!"); } boolean isNewer(String newVersion, String installedVersion) { if (newVersion.contains("-SNAPSHOT")) { return true; } installedVersion = installedVersion.replaceAll("\\(.*\\)", "").trim(); newVersion = newVersion.replaceAll("\\(.*\\)", "").trim(); return new VersionNumber(newVersion).compareTo(new VersionNumber(installedVersion)) > 0; } public void close() { IOUtils.closeQuietly(agentOutputStream); FileUtils.deleteQuietly(download); } /** * Update agent based on the current message. * * @param message message to be sent */ public void update(AgentUpdateGrinderMessage message) throws CommunicationException { if (message.getOffset() != offset) { throw new CommunicationException("Expected " + offset + " offset," + " but " + message.getOffset() + " was sent. " + ToStringBuilder.reflectionToString(message)); } try { IOUtils.write(message.getBinary(), agentOutputStream); offset = message.getNext(); } catch (IOException e) { throw new CommunicationException("Error while writing binary", e); } if (message.getNext() == 0) { IOUtils.closeQuietly(agentOutputStream); decompressDownloadPackage(); // Then just exist to run the agent update process. System.exit(0); } } void decompressDownloadPackage() { File interDir = new File(agentConfig.getHome().getTempDirectory(), "update_package_unpacked"); File toDir = new File(agentConfig.getCurrentDirectory(), "update_package"); interDir.mkdirs(); toDir.mkdirs(); if (FilenameUtils.isExtension(download.getName(), "tar")) { File outFile = new File(toDir, "ngrinder-agent.tar"); CompressionUtils.untar(download, interDir); FileUtils.deleteQuietly(outFile); } else { LOGGER.error("{} is not allowed to be unpacked.", download.getName()); } try { FileUtils.deleteQuietly(toDir); FileUtils.moveDirectory(new File(interDir, "ngrinder-agent"), toDir); } catch (IOException e) { LOGGER.error("Error while moving a file ", e); } FileUtils.deleteQuietly(download); FileUtils.deleteQuietly(interDir); } }