package org.springframework.roo.addon.cloud.foundry.converter; import java.io.File; import java.io.IOException; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.List; import java.util.Set; import java.util.logging.Logger; import org.apache.commons.lang3.StringUtils; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.Service; import org.springframework.roo.addon.cloud.foundry.model.CloudDeployableFile; import org.springframework.roo.file.monitor.event.FileDetails; import org.springframework.roo.process.manager.FileManager; import org.springframework.roo.project.MavenOperationsImpl; import org.springframework.roo.project.ProjectOperations; import org.springframework.roo.shell.Completion; import org.springframework.roo.shell.Converter; import org.springframework.roo.shell.MethodTarget; import org.springframework.roo.support.logging.HandlerUtils; /** * Provides conversion to and from Cloud Foundry model classes. * * @author James Tyrrell * @author Andrew Swan * @since 1.2.0 */ @Component @Service public class CloudDeployableFileConverter implements Converter<CloudDeployableFile> { private static final String CREATE_OPTION = "CREATE"; private static final Logger LOGGER = HandlerUtils .getLogger(CloudDeployableFileConverter.class); public static String escapeString(final String toEscape) { final StringBuilder result = new StringBuilder(); final StringCharacterIterator iterator = new StringCharacterIterator( toEscape); char character = iterator.current(); while (character != CharacterIterator.DONE) { switch (character) { case '.': { result.append("\\."); break; } case '\\': { result.append("\\\\"); break; } case '?': { result.append("\\?"); break; } case '*': { result.append("\\*"); break; } case '+': { result.append("\\+"); break; } case '&': { result.append("\\&"); break; } case ':': { result.append("\\:"); break; } case '{': { result.append("\\{"); break; } case '}': { result.append("\\}"); break; } case '[': { result.append("\\["); break; } case ']': { result.append("\\]"); break; } case '(': { result.append("\\("); break; } case ')': { result.append("\\)"); break; } case '^': { result.append("\\^"); break; } case '$': { result.append("\\$"); break; } default: { result.append(character); } } character = iterator.next(); } return result.toString(); } @Reference private FileManager fileManager; @Reference private ProjectOperations projectOperations; public CloudDeployableFile convertFromText(String value, final Class<?> requiredType, final String optionContext) { if (StringUtils.isBlank(value)) { return null; } if (CREATE_OPTION.equals(value)) { if (projectOperations instanceof MavenOperationsImpl) { try { if (projectOperations.getPathResolver() == null) { return null; } ((MavenOperationsImpl) projectOperations) .executeMvnCommand("clean package"); final String rootPath = projectOperations .getFocusedModule().getRoot(); final Set<FileDetails> fileDetails = fileManager .findMatchingAntPath(rootPath + File.separator + "**" + File.separator + "*.war"); if (fileDetails.size() > 0) { final FileDetails fileToDeploy = fileDetails.iterator() .next(); return new CloudDeployableFile(fileToDeploy); } } catch (final IOException e) { throw new IllegalStateException(e); } } return null; } final String oppositeFileSeparator = getOppositeFileSeparator(); if (value.contains(oppositeFileSeparator)) { value = value.replaceAll(escapeString(oppositeFileSeparator), escapeString(File.separator)); } final String path = projectOperations.getFocusedModule().getRoot() + value; if (!new File(path).exists()) { LOGGER.severe("The file at path '" + path + "' doesn't exist; cannot continue"); return null; } final FileDetails fileToDeploy = fileManager.readFile(projectOperations .getFocusedModule().getRoot() + value); return new CloudDeployableFile(fileToDeploy); } public boolean getAllPossibleValues(final List<Completion> completions, final Class<?> requiredType, final String existingData, final String optionContext, final MethodTarget target) { if (projectOperations.getPathResolver() == null) { LOGGER.warning("A project has not been created please specify the full path of the file you wish to deploy"); return false; } final String rootPath = projectOperations.getFocusedModule().getRoot(); final Set<FileDetails> fileDetails = fileManager .findMatchingAntPath(rootPath + File.separator + "**" + File.separator + "*.war"); if (fileDetails.isEmpty()) { LOGGER.warning("No deployable files found in the project directory. Please use the '" + CREATE_OPTION + "' option to build the war."); completions.add(new Completion(CREATE_OPTION)); } for (final FileDetails fileDetail : fileDetails) { completions.add(new Completion(fileDetail.getCanonicalPath() .replaceAll(escapeString(rootPath), ""))); } return false; } private String getOppositeFileSeparator() { final Character fileSeparator = File.separatorChar; if (fileSeparator.equals('/')) { return "\\"; } else if (fileSeparator.equals('\\')) { return "/"; } throw new IllegalStateException( "Unexpected file separator character encountered; cannot continue"); } public boolean supports(final Class<?> requiredType, final String optionContext) { return CloudDeployableFile.class.isAssignableFrom(requiredType); } }