Commit ebc64bfc authored by Marijan Milicevic's avatar Marijan Milicevic

ESSENTIALS-746 Support for copy action in DirectoryInstruction

- rename fileutils to avoid name conflict
- add copy support (jar resources)
parent 150432ab
......@@ -353,7 +353,7 @@ plugin-sdk/implementation/src/main/java/org/onehippo/cms7/essentials/dashboard/u
plugin-sdk/implementation/src/main/java/org/onehippo/cms7/essentials/dashboard/utils/DependencyUtils.java -text
plugin-sdk/implementation/src/main/java/org/onehippo/cms7/essentials/dashboard/utils/DocumentTemplateUtils.java -text
plugin-sdk/implementation/src/main/java/org/onehippo/cms7/essentials/dashboard/utils/EssentialConst.java -text
plugin-sdk/implementation/src/main/java/org/onehippo/cms7/essentials/dashboard/utils/FileUtils.java -text
plugin-sdk/implementation/src/main/java/org/onehippo/cms7/essentials/dashboard/utils/EssentialsFileUtils.java -text
plugin-sdk/implementation/src/main/java/org/onehippo/cms7/essentials/dashboard/utils/GalleryUtils.java -text
plugin-sdk/implementation/src/main/java/org/onehippo/cms7/essentials/dashboard/utils/GlobalUtils.java -text
plugin-sdk/implementation/src/main/java/org/onehippo/cms7/essentials/dashboard/utils/HippoNodeUtils.java -text
......
......@@ -39,6 +39,7 @@
<xs:simpleType name="directoryActionType">
<xs:restriction base="xs:string">
<xs:enumeration value="create"/>
<xs:enumeration value="copy"/>
<xs:enumeration value="delete"/>
</xs:restriction>
</xs:simpleType>
......
......@@ -18,22 +18,34 @@ package org.onehippo.cms7.essentials.dashboard.instruction;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.onehippo.cms7.essentials.dashboard.ctx.PluginContext;
import org.onehippo.cms7.essentials.dashboard.instructions.InstructionStatus;
import org.onehippo.cms7.essentials.dashboard.utils.EssentialConst;
import org.onehippo.cms7.essentials.dashboard.utils.FileUtils;
import org.onehippo.cms7.essentials.dashboard.utils.EssentialsFileUtils;
import org.onehippo.cms7.essentials.dashboard.utils.TemplateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.google.common.base.Strings;
/**
* @version "$Id$"
*/
......@@ -45,10 +57,31 @@ public class DirectoryInstruction extends PluginInstruction {
private PluginContext context;
private String target;
private String action;
private String source;
private String message;
private boolean overwrite;
private static final Set<String> SUPPORTED_EXTENSIONS = new ImmutableSet.Builder<String>()
.add("properties")
.add("jspf")
.add("java")
.add("jsp")
.add("xml")
.add("html")
.add("htm")
.add("txt")
.add("ftl")
.add("css")
.add("js")
.build();
private static final Set<String> SUPPORTED_ACTIONS = new ImmutableSet.Builder<String>()
.add("create")
.add("copy")
.build();
@Override
public InstructionStatus process(final PluginContext context, final InstructionStatus previousStatus) {
this.context = context;
if (Strings.isNullOrEmpty(action)) {
log.warn("DirectoryInstruction: action was empty");
message = "Failed to process instruction: invalid action";
......@@ -59,23 +92,47 @@ public class DirectoryInstruction extends PluginInstruction {
message = "Failed to create directory: invalid name";
return InstructionStatus.FAILED;
}
if (!action.equals("create")) {
if (!SUPPORTED_ACTIONS.contains(action)) {
message = "Failed to process instruction: invalid action";
throw new IllegalStateException("Not implemented yet: " + action);
}
processPlaceholders(context.getPlaceholderData());
switch (action) {
case "create":
return create();
case "copy":
return copy(context.getPlaceholderData());
}
return InstructionStatus.FAILED;
}
private InstructionStatus copy(final Map<String, Object> placeholderData) {
if (Strings.isNullOrEmpty(source)) {
log.warn("Source was not defined");
return InstructionStatus.FAILED;
}
if (Strings.isNullOrEmpty(target)) {
log.warn("target was not defined");
return InstructionStatus.FAILED;
}
return copyResources(source, new File(target), placeholderData);
}
private InstructionStatus create() {
log.debug("Creating directory: {}", target);
try {
FileUtils.createParentDirectories(new File(target));
EssentialsFileUtils.createParentDirectories(new File(target));
} catch (IOException e) {
log.error("Error creating directory: " + target, e);
message = "Failed to create directory " + target;
return InstructionStatus.FAILED;
}
this.context = context;
message = "Created directory " + target;
return InstructionStatus.SUCCESS;
}
@Override
......@@ -106,17 +163,123 @@ public class DirectoryInstruction extends PluginInstruction {
this.target = target;
}
@XmlAttribute
@Override
public String getAction() {
return action;
}
@XmlAttribute
@Override
public void setAction(final String action) {
this.action = action;
}
@XmlAttribute
public String getSource() {
return source;
}
public void setSource(final String source) {
this.source = source;
}
@XmlAttribute
public boolean isOverwrite() {
return overwrite;
}
public void setOverwrite(final boolean overwrite) {
this.overwrite = overwrite;
}
//############################################
//
//############################################
private InstructionStatus copyResources(final String source, final File targetDirectory, final Map<String, Object> placeholderData) {
if (!targetDirectory.exists()) {
log.warn("Directory {} doesn't exist, creating new one", targetDirectory);
try {
EssentialsFileUtils.createParentDirectories(targetDirectory);
} catch (IOException e) {
log.error("Error creating directory", e);
return InstructionStatus.FAILED;
}
}
try {
final JarURLConnection connection = createConnection(source);
if (connection == null) {
log.warn("Couldn't process jar source: {}", source);
return InstructionStatus.FAILED;
}
final String name = connection.getEntryName();
log.debug("Processing zip file for connection: {}", name);
final JarFile jarFile = connection.getJarFile();
final Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
final JarEntry jarEntry = entries.nextElement();
final String entryName = jarEntry.getName();
log.debug("Processing jar entry: {}", entryName);
if (entryName.startsWith(name + '/')) {
final String fileName = entryName.substring(name.length());
final File file = new File(targetDirectory, fileName);
if (file.exists()) {
if (overwrite) {
final boolean delete = file.delete();
log.info("Deleted existing file: {},{}", file, delete);
} else {
log.info("File already exists, skipping copy: {}", file);
continue;
}
}
if (jarEntry.isDirectory()) {
final boolean created = file.mkdirs();
log.debug("Created directory:{}, {}", file, created);
} else {
final InputStream is = jarFile.getInputStream(jarEntry);
final OutputStream out = org.apache.commons.io.FileUtils.openOutputStream(file);
IOUtils.copy(is, out);
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(out);
log.info("Copied file {}", file);
final String ext = FilenameUtils.getExtension(file.getAbsolutePath());
if (SUPPORTED_EXTENSIONS.contains(ext.toLowerCase())) {
TemplateUtils.replaceFileTemplateData(file.toPath(), placeholderData);
} else {
log.debug("Skipping processing of template placeholders: {}", ext);
}
}
}
}
} catch (IOException e) {
log.error("Error extracting files", e);
return InstructionStatus.FAILED;
}
return InstructionStatus.SUCCESS;
}
private JarURLConnection createConnection(final String source) throws IOException {
if (Strings.isNullOrEmpty(source)) {
return null;
}
final URL resource = getClass().getResource(source);
if (resource == null) {
return null;
}
log.info("Processing resource {}", resource);
final URLConnection urlConnection = resource.openConnection();
if (urlConnection instanceof JarURLConnection) {
return (JarURLConnection)urlConnection;
}
return null;
}
}
......@@ -24,9 +24,9 @@ import java.util.Deque;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class FileUtils {
public final class EssentialsFileUtils {
private static final Logger log = LoggerFactory.getLogger(FileUtils.class);
private static final Logger log = LoggerFactory.getLogger(EssentialsFileUtils.class);
public static void createParentDirectories(final File directory) throws IOException {
if (directory == null) {
......@@ -46,7 +46,7 @@ public final class FileUtils {
* @param directory directory to delete
* @return boolean on success
*/
public static boolean deleteDirectory(final File directory) {
public static boolean deleteSingleDirectory(final File directory) {
if (directory == null) {
throw new IllegalArgumentException("Directory was null");
}
......
......@@ -28,6 +28,12 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import com.github.mustachejava.DefaultMustacheFactory;
import com.github.mustachejava.Mustache;
import com.github.mustachejava.MustacheFactory;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.WordUtils;
import org.eclipse.jdt.core.dom.MethodDeclaration;
......@@ -39,12 +45,6 @@ import org.onehippo.cms7.essentials.dashboard.utils.code.ExistingMethodsVisitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.mustachejava.DefaultMustacheFactory;
import com.github.mustachejava.Mustache;
import com.github.mustachejava.MustacheFactory;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
/**
* @version "$Id$"
......@@ -171,6 +171,26 @@ public final class TemplateUtils {
return content;
}
public static void replaceFileTemplateData(final Path path, final Map<String, Object> data) {
final String content = GlobalUtils.readTextFile(path).toString();
if (Strings.isNullOrEmpty(content)) {
return;
}
try {
final Writer writer = new StringWriter();
final MustacheFactory mf = new DefaultMustacheFactory();
final StringReader reader = new StringReader(content);
final Mustache mustache = mf.compile(reader, content);
mustache.execute(writer, data);
writer.flush();
GlobalUtils.writeToFile(writer.toString(), path);
} catch (IOException e) {
log.error("Error flushing template", e);
}
}
public static String injectTemplate(final String templateName, final Map<String, Object> data, final Class<?> clazz) {
final InputStream stream = clazz.getClassLoader().getResourceAsStream(templateName);
if (stream == null) {
......
......@@ -20,13 +20,17 @@ import java.io.File;
import javax.inject.Inject;
import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Test;
import org.onehippo.cms7.essentials.BaseResourceTest;
import org.onehippo.cms7.essentials.dashboard.ctx.PluginContext;
import org.onehippo.cms7.essentials.dashboard.instructions.InstructionExecutor;
import org.onehippo.cms7.essentials.dashboard.instructions.InstructionSet;
import org.onehippo.cms7.essentials.dashboard.instructions.InstructionStatus;
import org.onehippo.cms7.essentials.dashboard.utils.FileUtils;
import org.onehippo.cms7.essentials.dashboard.utils.EssentialsFileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import static org.junit.Assert.assertTrue;
......@@ -38,6 +42,7 @@ public class DirectoryInstructionTest extends BaseResourceTest {
public static final String THIRD = "EssentialsDirectoryInstructionTest";
public static final String DIR = File.separator + THIRD + File.separator + SECOND + File.separator + FIRST;
private static final Logger log = LoggerFactory.getLogger(DirectoryInstructionTest.class);
@Inject
private InstructionExecutor executor;
@Inject
......@@ -45,7 +50,9 @@ public class DirectoryInstructionTest extends BaseResourceTest {
private DirectoryInstruction createInstruction;
@Inject
@Qualifier("directoryInstruction")
private DirectoryInstruction deleteInstruction;
private DirectoryInstruction copyInstruction;
private File targetDir;
private static String createPlaceHolder(final String placeholderProjectRoot) {
return "{{" + placeholderProjectRoot + "}}";
......@@ -66,14 +73,32 @@ public class DirectoryInstructionTest extends BaseResourceTest {
}
@Test
public void testCopy() throws Exception {
targetDir = new File(System.getProperty("java.io.tmpdir") + File.separatorChar + getClass().getSimpleName());
log.info("testing copy to: {}", targetDir);
final InstructionSet set = new PluginInstructionSet();
set.addInstruction(copyInstruction);
final PluginContext context = getContext();
InstructionStatus status = executor.execute(set, context);
assertTrue(status == InstructionStatus.FAILED);
copyInstruction.setSource("/");
copyInstruction.setAction("copy");
copyInstruction.setTarget(targetDir.getAbsolutePath());
status = executor.execute(set, context);
assertTrue("Expected to fail: " + status, status == InstructionStatus.FAILED);
}
@Override
@After
public void tearDown() throws Exception {
boolean deleted = FileUtils.deleteDirectory(new File(System.getProperty("java.io.tmpdir") + DIR));
assertTrue(deleted);
deleted = FileUtils.deleteDirectory(new File(System.getProperty("java.io.tmpdir") + File.separator + THIRD + File.separator + SECOND));
assertTrue(deleted);
deleted = FileUtils.deleteDirectory(new File(System.getProperty("java.io.tmpdir") + File.separator + THIRD));
assertTrue(deleted);
EssentialsFileUtils.deleteSingleDirectory(new File(System.getProperty("java.io.tmpdir") + DIR));
EssentialsFileUtils.deleteSingleDirectory(new File(System.getProperty("java.io.tmpdir") + File.separator + THIRD + File.separator + SECOND));
EssentialsFileUtils.deleteSingleDirectory(new File(System.getProperty("java.io.tmpdir") + File.separator + THIRD));
if (targetDir != null) {
FileUtils.deleteDirectory(targetDir);
}
}
}
......@@ -131,7 +131,7 @@
<level value="warn"/>
</logger>
<logger name="org.onehippo.cms7.essentials">
<level value="warn"/>
<level value="debug"/>
</logger>
<logger name="org.onehippo.repository.testutils.ExecuteOnLogLevel">
<level value="warn"/>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment