Java tutorial
/* * LICENCE : CloudUnit is available under the GNU Affero General Public License : https://gnu.org/licenses/agpl.html * but CloudUnit is licensed too under a standard commercial license. * Please contact our sales team if you would like to discuss the specifics of our Enterprise license. * If you are not sure whether the AGPL is right for you, * you can always test our software under the AGPL and inspect the source code before you contact us * about purchasing a commercial license. * * LEGAL TERMS : "CloudUnit" is a registered trademark of Treeptik and can't be used to endorse * or promote products derived from this project without prior written permission from Treeptik. * Products or services derived from this software may not be called "CloudUnit" * nor may "Treeptik" or similar confusing terms appear in their names without prior written permission. * For any questions, contact us : contact@treeptik.fr */ package cn.org.once.cstack.service.impl; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import javax.inject.Inject; import cn.org.once.cstack.dto.FileUnit; import cn.org.once.cstack.dto.SourceUnit; import cn.org.once.cstack.enums.RemoteExecAction; import cn.org.once.cstack.exception.CheckException; import cn.org.once.cstack.exception.ServiceException; import cn.org.once.cstack.filters.explorer.ExplorerFactory; import cn.org.once.cstack.filters.explorer.ExplorerFilter; import cn.org.once.cstack.service.FileService; import cn.org.once.cstack.utils.AlphaNumericsCharactersCheckUtils; import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import cn.org.once.cstack.exception.FatalDockerJSONException; import cn.org.once.cstack.service.DockerService; import cn.org.once.cstack.utils.FilesUtils; /** * Service for file management into container Created by nicolas on 20/05/15. */ @Service public class FileServiceImpl implements FileService { private Logger logger = LoggerFactory.getLogger(FileServiceImpl.class); @Inject private DockerService dockerService; @Value("${docker.socket.location}") private String dockerManagerIp; @Value("${docker.endpoint.mode}") private String dockerEndpointMode; /** * File Explorer Feature * <p> * Delete all resources (files and folders) for an application + container + * path. * * @param applicationName * @param containerId * @param path * @throws ServiceException */ public void deleteFilesFromContainer(String applicationName, String containerId, String path) throws ServiceException { try { final String command = "rm -rf " + path; dockerService.execCommand(containerId, command); } catch (FatalDockerJSONException e) { throw new ServiceException("Cannot delete files " + path + " for " + containerId, e); } } @Override public void createDirectory(String applicationName, String containerId, String path) throws ServiceException { try { final String command = "mkdir -p " + path; dockerService.execCommand(containerId, command); } catch (FatalDockerJSONException e) { throw new ServiceException("Cannot create directory " + path + " for " + containerId, e); } } /** * Logs Display Feature * <p> * List the files into the Log directory * * @param containerId * @return * @throws ServiceException */ public List<SourceUnit> listLogsFilesByContainer(String containerId) throws ServiceException { List<SourceUnit> files = new ArrayList<>(); try { String logDirectory = getLogDirectory(containerId); // if logs directory is stdout, we don't need to search the files list if (logDirectory.equalsIgnoreCase("stdout")) { files.add(new SourceUnit("stdout")); return files; } String containerName = dockerService.getContainerNameFromId(containerId); final String command = "find " + logDirectory + " -type f ! -size 0 "; String execOutput = dockerService.execCommand(containerName, command); if (execOutput != null && execOutput.contains("cannot access") == false) { if (logger.isDebugEnabled()) { logger.debug(execOutput); } StringTokenizer lignes = new StringTokenizer(execOutput, "\n"); while (lignes.hasMoreTokens()) { String name = lignes.nextToken(); name = name.substring(name.lastIndexOf("/") + 1); SourceUnit sourceUnit = new SourceUnit(name); files.add(sourceUnit); } } } catch (FatalDockerJSONException e) { throw new ServiceException("Error in listByContainerIdAndPath", e); } return files; } /** * Logs Display Feature * <p> * List the files and folder for a container * * @param containerId * @return * @throws ServiceException */ public String tailFile(String containerId, String filename, Integer maxRows) throws ServiceException { String execOutput = ""; String command = null; try { String logDir = getLogDirectory(containerId); if (!logDir.endsWith("/")) { logDir = logDir + "/"; } command = "tail -n " + maxRows + " " + logDir + filename; execOutput = dockerService.execCommand(containerId, command); if (execOutput != null && execOutput.contains("cannot access") == false) { return execOutput; } } catch (FatalDockerJSONException e) { StringBuilder builder = new StringBuilder(256); builder.append(command); builder.append(", containerId=").append(containerId); builder.append(",file=").append(filename); builder.append(",nbRows=").append(maxRows); throw new ServiceException(builder.toString(), e); } return execOutput; } /** * File Explorer Feature * <p> * List the files by Container and Path * * @param containerId * @param path * @return * @throws ServiceException */ public List<FileUnit> listByContainerIdAndPath(String containerId, String path) throws ServiceException { List<FileUnit> files = new ArrayList<>(); try { final String command = "ls -laF " + path; String execOutput = dockerService.execCommand(containerId, command); String containerName = dockerService.getContainerNameFromId(containerId); ExplorerFilter filter = ExplorerFactory.getInstance().getCustomFilter(containerName); if (execOutput != null && execOutput.contains("cannot access") == false) { if (logger.isDebugEnabled()) { logger.debug(execOutput); } StringTokenizer lignes = new StringTokenizer(execOutput, "\n"); while (lignes.hasMoreTokens()) { String ligne = lignes.nextToken(); if (logger.isDebugEnabled()) { logger.debug(ligne); } if (ligne.startsWith("total")) continue; StringTokenizer fields = new StringTokenizer(ligne, " "); String rights = fields.nextToken(); String id = fields.nextToken(); String user = fields.nextToken(); String group = fields.nextToken(); String size = fields.nextToken(); String month = fields.nextToken(); String day = fields.nextToken(); String hour = fields.nextToken(); String name = fields.nextToken(); boolean dir = false; boolean exec = false; if (name.endsWith("/")) { dir = true; name = name.substring(0, name.length() - 1); } else { boolean isNotAuth = FilesUtils.isNotAuthorizedExtension(name); if (isNotAuth) { continue; } } if (name.endsWith("*")) { exec = true; name = name.substring(0, name.length() - 1); } StringBuilder absolutePath = new StringBuilder(128); absolutePath.append(path).append(name); if (name.equalsIgnoreCase(".")) continue; if (name.equalsIgnoreCase("..")) continue; FileUnit fileUnit = new FileUnit(name, user, day, month, hour, false, dir, exec, absolutePath.toString()); if (filter.isValid(fileUnit)) { filter.isRemovable(fileUnit); filter.isSafe(fileUnit); files.add(fileUnit); } } } } catch (FatalDockerJSONException e) { throw new ServiceException(containerId, e); } return files; } /** * File Explorer feature * <p> * Send a file into a container * * @param containerId * @Param destination * @throws ServiceException */ @Override public void sendFileToContainer(String containerId, String destination, MultipartFile fileUpload, String contentFileName, String contentFileData) throws ServiceException, CheckException { try { File file = null; File createTempHomeDirPerUsage = null; File homeDirectory = null; try { homeDirectory = org.apache.commons.io.FileUtils.getUserDirectory(); createTempHomeDirPerUsage = new File( homeDirectory.getAbsolutePath() + "/tmp" + System.currentTimeMillis()); if (createTempHomeDirPerUsage.mkdirs()) { String fileName = null; // usecase : upload a file if (fileUpload != null) { if (contentFileName == null) { fileName = fileUpload.getOriginalFilename(); fileName = AlphaNumericsCharactersCheckUtils.deAccent(fileName); fileName = fileName.replace(" ", "_"); } else { fileName = contentFileName; } file = new File(createTempHomeDirPerUsage.getAbsolutePath() + "/" + fileName); fileUpload.transferTo(file); } // usecase : save the content file else { fileName = contentFileName; file = new File(createTempHomeDirPerUsage.getAbsolutePath() + "/" + contentFileName); FileUtils.write(file, contentFileData); } dockerService.sendFileToContainer(containerId, file.getParent(), fileName, destination); } else { throw new ServiceException("Cannot create : " + createTempHomeDirPerUsage.getAbsolutePath()); } } finally { if (createTempHomeDirPerUsage != null) { boolean deleted = file.delete(); logger.debug(file.getAbsolutePath() + " is deleted ? " + deleted); deleted = createTempHomeDirPerUsage.delete(); logger.debug(createTempHomeDirPerUsage.getAbsolutePath() + " is deleted ? " + deleted); } } if (destination.contains("/opt/cloudunit")) { dockerService.execCommand(containerId, RemoteExecAction.CHANGE_CU_RIGHTS.getCommand(), true); } } catch (FatalDockerJSONException | IOException e) { StringBuilder msgError = new StringBuilder(512); msgError.append(",").append("containerId=").append(containerId); msgError.append(",").append("fileUpload=").append(fileUpload); msgError.append(",").append("destFile=").append(destination); throw new ServiceException("error in send file into the container : " + msgError, e); } } /** * File Explorer feature * <p> * Gather a file from a container * * @param containerId * @return * @throws ServiceException */ @Override public int getFileFromContainer(String containerId, String pathFile, OutputStream outputStream) throws ServiceException { try { return dockerService.getFileFromContainer(containerId, pathFile, outputStream); } catch (FatalDockerJSONException e) { StringBuilder msgError = new StringBuilder(); msgError.append(", containerId=").append("=").append(containerId); throw new ServiceException(msgError.toString(), e); } } public String getLogDirectory(String containerId) throws ServiceException { String location = null; try { location = dockerService.getEnv(containerId, "CU_LOGS"); } catch (Exception e) { logger.error(containerId, e); } return location; } }