diff --git a/maven/pom.xml b/maven/pom.xml
new file mode 100644
index 0000000000..6bad10be0e
--- /dev/null
+++ b/maven/pom.xml
@@ -0,0 +1,32 @@
+
+
+
+ 4.0.0
+
+
+ sonia.scm
+ scm
+ 1.0-M2-SNAPSHOT
+
+
+ sonia.scm.maven
+ scm-maven-plugins
+ pom
+ 1.0-M2-SNAPSHOT
+ scm-maven-plugins
+
+
+ scm-web-compressor
+
+
+
+
+
+ sonia.scm
+ scm-core
+ 1.0-M2-SNAPSHOT
+
+
+
+
+
\ No newline at end of file
diff --git a/maven/scm-web-compressor/lib/compiler-20100917.jar b/maven/scm-web-compressor/lib/compiler-20100917.jar
new file mode 100644
index 0000000000..4dfa5ad0b9
Binary files /dev/null and b/maven/scm-web-compressor/lib/compiler-20100917.jar differ
diff --git a/maven/scm-web-compressor/pom.xml b/maven/scm-web-compressor/pom.xml
new file mode 100644
index 0000000000..a2025ffa38
--- /dev/null
+++ b/maven/scm-web-compressor/pom.xml
@@ -0,0 +1,48 @@
+
+
+
+ 4.0.0
+
+
+ sonia.scm.maven
+ scm-maven-plugins
+ 1.0-M2-SNAPSHOT
+
+
+ sonia.scm.maven
+ scm-web-compressor
+ jar
+ 1.0-M2-SNAPSHOT
+ scm-web-compressor
+
+
+
+
+ org.apache.maven
+ maven-plugin-api
+ 2.2.1
+
+
+
+ org.jsoup
+ jsoup
+ 1.3.3
+
+
+
+ com.yahoo.platform.yui
+ yuicompressor
+ 2.4.2
+
+
+
+ com.google.closure
+ compiler
+ 20100917
+ system
+ ${basedir}/lib/compiler-20100917.jar
+
+
+
+
+
\ No newline at end of file
diff --git a/maven/scm-web-compressor/src/main/java/sonia/scm/maven/AbstractWebCompressor.java b/maven/scm-web-compressor/src/main/java/sonia/scm/maven/AbstractWebCompressor.java
new file mode 100644
index 0000000000..21fc05dfc6
--- /dev/null
+++ b/maven/scm-web-compressor/src/main/java/sonia/scm/maven/AbstractWebCompressor.java
@@ -0,0 +1,267 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of SCM-Manager; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.maven;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import sonia.scm.util.ChecksumUtil;
+import sonia.scm.util.IOUtil;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public abstract class AbstractWebCompressor implements WebCompressor
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @param document
+ * @param path
+ */
+ protected abstract void appendElement(Document document, String path);
+
+ /**
+ * Method description
+ *
+ *
+ * @param source
+ * @param target
+ * @param encoding
+ *
+ * @throws IOException
+ * @throws MojoExecutionException
+ * @throws MojoFailureException
+ */
+ protected abstract void compress(File source, File target, String encoding)
+ throws IOException, MojoExecutionException, MojoFailureException;
+
+ /**
+ * Method description
+ *
+ *
+ * @param document
+ *
+ * @return
+ */
+ protected abstract Elements selectElements(Document document);
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ protected abstract String getExtension();
+
+ /**
+ * Method description
+ *
+ *
+ * @param inputDirectory
+ * @param element
+ *
+ * @return
+ */
+ protected abstract File getFile(File inputDirectory, Element element);
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param document
+ * @param inputDirectory
+ * @param outputDirectory
+ * @param encoding
+ * @param outputPrefix
+ * @param concat
+ *
+ * @throws IOException
+ * @throws MojoExecutionException
+ * @throws MojoFailureException
+ */
+ @Override
+ public void compress(Document document, File inputDirectory,
+ File outputDirectory, String encoding,
+ String outputPrefix, boolean concat)
+ throws IOException, MojoExecutionException, MojoFailureException
+ {
+ Elements elements = selectElements(document);
+
+ if ((elements != null) &&!elements.isEmpty())
+ {
+ if (concat)
+ {
+ File uncompressedFile = concat(elements, inputDirectory);
+
+ compress(document, encoding, outputDirectory, outputPrefix,
+ uncompressedFile);
+ }
+ else
+ {
+ for (Element element : elements)
+ {
+ File uncompressedFile = getFile(inputDirectory, element);
+
+ compress(document, encoding, outputDirectory, outputPrefix,
+ uncompressedFile);
+ }
+ }
+ }
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param source
+ * @param target
+ *
+ * @throws IOException
+ */
+ private void append(File source, File target) throws IOException
+ {
+ FileInputStream input = null;
+ FileOutputStream output = null;
+
+ try
+ {
+ input = new FileInputStream(source);
+ output = new FileOutputStream(target, true);
+ IOUtil.copy(input, output);
+ }
+ finally
+ {
+ IOUtil.close(input);
+ IOUtil.close(output);
+ }
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param document
+ * @param encoding
+ * @param outputDirectory
+ * @param outputPrefix
+ * @param uncompressedFile
+ *
+ * @throws IOException
+ * @throws MojoExecutionException
+ * @throws MojoFailureException
+ */
+ private void compress(Document document, String encoding,
+ File outputDirectory, String outputPrefix,
+ File uncompressedFile)
+ throws IOException, MojoExecutionException, MojoFailureException
+ {
+ File compressedFile = File.createTempFile("scm-", ".compressed");
+
+ compress(uncompressedFile, compressedFile, encoding);
+ IOUtil.delete(uncompressedFile);
+
+ String checksum = ChecksumUtil.createChecksum(compressedFile);
+ String name = checksum.concat(".").concat(getExtension());
+ File scriptFile = new File(outputDirectory, name);
+
+ compressedFile.renameTo(scriptFile);
+
+ if (!scriptFile.exists())
+ {
+
+ // TODO copy and remove
+ throw new IOException("could not move ".concat(compressedFile.getPath()));
+ }
+
+ StringBuilder path = new StringBuilder(outputPrefix);
+
+ if (!outputPrefix.endsWith("/"))
+ {
+ path.append("/");
+ }
+
+ path.append(name);
+ appendElement(document, path.toString());
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param elements
+ * @param inputDirectory
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ private File concat(Elements elements, File inputDirectory) throws IOException
+ {
+ File tempFile = File.createTempFile("scm-", ".concat");
+
+ for (Element scriptEl : elements)
+ {
+ File file = getFile(inputDirectory, scriptEl);
+
+ if (file.exists())
+ {
+ append(file, tempFile);
+ scriptEl.remove();
+ }
+ }
+
+ return tempFile;
+ }
+}
diff --git a/maven/scm-web-compressor/src/main/java/sonia/scm/maven/ClosureWebCompressor.java b/maven/scm-web-compressor/src/main/java/sonia/scm/maven/ClosureWebCompressor.java
new file mode 100644
index 0000000000..6f351df573
--- /dev/null
+++ b/maven/scm-web-compressor/src/main/java/sonia/scm/maven/ClosureWebCompressor.java
@@ -0,0 +1,169 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of SCM-Manager; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.maven;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.javascript.jscomp.CompilerOptions;
+import com.google.javascript.jscomp.JSSourceFile;
+import com.google.javascript.jscomp.Result;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import sonia.scm.util.IOUtil;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class ClosureWebCompressor extends AbstractWebCompressor
+{
+
+ /** Field description */
+ public static final String EXTENSION = "js";
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param document
+ * @param path
+ */
+ @Override
+ protected void appendElement(Document document, String path)
+ {
+ document.head().appendElement("script").attr("type",
+ "text/javascript").attr("src", path);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param sourceFile
+ * @param targetFile
+ * @param encoding
+ *
+ * @throws IOException
+ * @throws MojoExecutionException
+ * @throws MojoFailureException
+ */
+ @Override
+ protected void compress(File sourceFile, File targetFile, String encoding)
+ throws IOException, MojoExecutionException, MojoFailureException
+ {
+ com.google.javascript.jscomp.Compiler compiler =
+ new com.google.javascript.jscomp.Compiler();
+ CompilerOptions options = new CompilerOptions();
+ final JSSourceFile extern = JSSourceFile.fromCode("externs.js",
+ "function alert(x) {}");
+ JSSourceFile source = JSSourceFile.fromFile(sourceFile);
+ Result result = compiler.compile(extern, source, options);
+
+ if (!result.success)
+ {
+ throw new MojoFailureException("compression failed");
+ }
+ else
+ {
+ FileOutputStream output = null;
+
+ try
+ {
+ output = new FileOutputStream(targetFile);
+ output.write(compiler.toSource().getBytes(encoding));
+ }
+ finally
+ {
+ IOUtil.close(output);
+ }
+ }
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param document
+ *
+ * @return
+ */
+ @Override
+ protected Elements selectElements(Document document)
+ {
+ return document.select("script[type=text/javascript][src]");
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ protected String getExtension()
+ {
+ return EXTENSION;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param inputDirectory
+ * @param element
+ *
+ * @return
+ */
+ @Override
+ protected File getFile(File inputDirectory, Element element)
+ {
+ return new File(inputDirectory, element.attr("src"));
+ }
+}
diff --git a/maven/scm-web-compressor/src/main/java/sonia/scm/maven/WebCompressor.java b/maven/scm-web-compressor/src/main/java/sonia/scm/maven/WebCompressor.java
new file mode 100644
index 0000000000..9f4414724b
--- /dev/null
+++ b/maven/scm-web-compressor/src/main/java/sonia/scm/maven/WebCompressor.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of SCM-Manager; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.maven;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+import java.io.IOException;
+import org.jsoup.nodes.Document;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public interface WebCompressor
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @param head
+ * @param elements
+ * @param inputDirectory
+ * @param outputDirectory
+ * @param outputPrefix
+ * @param concat
+ *
+ * @throws IOException
+ * @throws MojoExecutionException
+ * @throws MojoFailureException
+ */
+ public void compress(Document document, File inputDirectory,
+ File outputDirectory, String encoding, String outputPrefix,
+ boolean concat)
+ throws IOException, MojoExecutionException, MojoFailureException;
+}
diff --git a/maven/scm-web-compressor/src/main/java/sonia/scm/maven/WebCompressorMojo.java b/maven/scm-web-compressor/src/main/java/sonia/scm/maven/WebCompressorMojo.java
new file mode 100644
index 0000000000..652cbb756b
--- /dev/null
+++ b/maven/scm-web-compressor/src/main/java/sonia/scm/maven/WebCompressorMojo.java
@@ -0,0 +1,259 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of SCM-Manager; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.maven;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+
+import sonia.scm.util.IOUtil;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class WebCompressorMojo extends AbstractMojo
+{
+
+ /**
+ * Constructs ...
+ *
+ */
+ public WebCompressorMojo()
+ {
+ compressorSet = new LinkedHashSet();
+ compressorSet.add(new ClosureWebCompressor());
+ compressorSet.add(new YuiWebCompressor());
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @throws MojoExecutionException
+ * @throws MojoFailureException
+ */
+ @Override
+ public void execute() throws MojoExecutionException, MojoFailureException
+ {
+ OutputStream output = null;
+
+ try
+ {
+ Document document = Jsoup.parse(inputFile, encoding);
+ File inputDirectory = inputFile.getParentFile();
+
+ for (WebCompressor compressor : compressorSet)
+ {
+ compressor.compress(document, inputDirectory, outputDirectory,
+ encoding, outputPrefix, true);
+ }
+
+ output = new FileOutputStream(outputFile);
+ output.write(document.html().getBytes(encoding));
+ }
+ catch (IOException ex)
+ {
+ throw new MojoExecutionException(ex.getMessage(), ex);
+ }
+ finally
+ {
+ IOUtil.close(output);
+ }
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public String getEncoding()
+ {
+ return encoding;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public File getInputFile()
+ {
+ return inputFile;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public File getOutputDirectory()
+ {
+ return outputDirectory;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public File getOutputFile()
+ {
+ return outputFile;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ public String getOutputPrefix()
+ {
+ return outputPrefix;
+ }
+
+ //~--- set methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param encoding
+ */
+ public void setEncoding(String encoding)
+ {
+ this.encoding = encoding;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param inputFile
+ */
+ public void setInputFile(File inputFile)
+ {
+ this.inputFile = inputFile;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param outputDirectory
+ */
+ public void setOutputDirectory(File outputDirectory)
+ {
+ this.outputDirectory = outputDirectory;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param outputFile
+ */
+ public void setOutputFile(File outputFile)
+ {
+ this.outputFile = outputFile;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param outputPrefix
+ */
+ public void setOutputPrefix(String outputPrefix)
+ {
+ this.outputPrefix = outputPrefix;
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private Set compressorSet;
+
+ /**
+ * @parameter
+ */
+ private String encoding = "UTF-8";
+
+ /**
+ * @parameter
+ * @required
+ */
+ private File inputFile;
+
+ /**
+ * @parameter
+ */
+ private File outputDirectory;
+
+ /**
+ * @parameter
+ * @required
+ */
+ private File outputFile;
+
+ /**
+ * @parameter
+ * @required
+ */
+ private String outputPrefix;
+}
diff --git a/maven/scm-web-compressor/src/main/java/sonia/scm/maven/YuiWebCompressor.java b/maven/scm-web-compressor/src/main/java/sonia/scm/maven/YuiWebCompressor.java
new file mode 100644
index 0000000000..3ce1c568fc
--- /dev/null
+++ b/maven/scm-web-compressor/src/main/java/sonia/scm/maven/YuiWebCompressor.java
@@ -0,0 +1,159 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of SCM-Manager; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.maven;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.yahoo.platform.yui.compressor.CssCompressor;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import sonia.scm.util.IOUtil;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class YuiWebCompressor extends AbstractWebCompressor
+{
+
+ /** Field description */
+ public static final String EXTENSION = "css";
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param document
+ * @param path
+ */
+ @Override
+ protected void appendElement(Document document, String path)
+ {
+ document.appendElement("link").attr("type", "text/css").attr("rel",
+ "stylesheet").attr("href", path);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param source
+ * @param target
+ * @param encoding
+ *
+ * @throws IOException
+ * @throws MojoExecutionException
+ * @throws MojoFailureException
+ */
+ @Override
+ protected void compress(File source, File target, String encoding)
+ throws IOException, MojoExecutionException, MojoFailureException
+ {
+ FileReader reader = null;
+ FileWriter writer = null;
+
+ try
+ {
+ reader = new FileReader(source);
+
+ CssCompressor compressor = new CssCompressor(reader);
+
+ writer = new FileWriter(target);
+ compressor.compress(writer, 5000);
+ }
+ finally
+ {
+ IOUtil.close(reader);
+ IOUtil.close(writer);
+ }
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param document
+ *
+ * @return
+ */
+ @Override
+ protected Elements selectElements(Document document)
+ {
+ return document.select("link[type=text/css][href]");
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ protected String getExtension()
+ {
+ return EXTENSION;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param inputDirectory
+ * @param element
+ *
+ * @return
+ */
+ @Override
+ protected File getFile(File inputDirectory, Element element)
+ {
+ return new File(inputDirectory, element.attr("href"));
+ }
+}
diff --git a/maven/scm-web-compressor/src/test/java/sonia/scm/WebCompressorTest.java b/maven/scm-web-compressor/src/test/java/sonia/scm/WebCompressorTest.java
new file mode 100644
index 0000000000..1725dd0213
--- /dev/null
+++ b/maven/scm-web-compressor/src/test/java/sonia/scm/WebCompressorTest.java
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of SCM-Manager; nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+package sonia.scm;
+
+import java.io.File;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.junit.Test;
+import sonia.scm.maven.WebCompressorMojo;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class WebCompressorTest
+{
+
+ @Test
+ public void compress() throws MojoExecutionException, MojoFailureException
+ {
+ WebCompressorMojo mojo = new WebCompressorMojo();
+ mojo.setInputFile( new File("/tmp/compressor/index.html") );
+ mojo.setOutputDirectory( new File("/tmp") );
+ mojo.setOutputFile( new File("/tmp/index.html") );
+ mojo.setOutputPrefix("");
+ mojo.execute();
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index e0989289cb..b733c7e693 100644
--- a/pom.xml
+++ b/pom.xml
@@ -38,6 +38,7 @@
third-party
scm-core
+ maven
scm-cli
scm-web-api
scm-server-api
diff --git a/scm-core/src/main/java/sonia/scm/security/MessageDigestEncryptionHandler.java b/scm-core/src/main/java/sonia/scm/security/MessageDigestEncryptionHandler.java
index 661c0d06df..2176f6fde1 100644
--- a/scm-core/src/main/java/sonia/scm/security/MessageDigestEncryptionHandler.java
+++ b/scm-core/src/main/java/sonia/scm/security/MessageDigestEncryptionHandler.java
@@ -29,11 +29,14 @@
*
*/
+
+
package sonia.scm.security;
//~--- non-JDK imports --------------------------------------------------------
import sonia.scm.util.AssertUtil;
+import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------
@@ -132,22 +135,7 @@ public class MessageDigestEncryptionHandler implements EncryptionHandler
messageDigest.reset();
messageDigest.update(value.getBytes());
- byte hashCode[] = messageDigest.digest();
- StringBuilder hashString = new StringBuilder();
-
- for (int i = 0; i < hashCode.length; i++)
- {
- int x = hashCode[i] & 0xff;
-
- if (x < 16)
- {
- hashString.append('0');
- }
-
- hashString.append(Integer.toString(x, 16));
- }
-
- return hashString.toString();
+ return Util.toString(messageDigest.digest());
}
//~--- fields ---------------------------------------------------------------
diff --git a/scm-core/src/main/java/sonia/scm/util/ChecksumUtil.java b/scm-core/src/main/java/sonia/scm/util/ChecksumUtil.java
index 211478f508..96f0b909cc 100644
--- a/scm-core/src/main/java/sonia/scm/util/ChecksumUtil.java
+++ b/scm-core/src/main/java/sonia/scm/util/ChecksumUtil.java
@@ -29,6 +29,8 @@
*
*/
+
+
package sonia.scm.util;
//~--- JDK imports ------------------------------------------------------------
@@ -94,9 +96,7 @@ public class ChecksumUtil
}
}
- byte[] b = digest.digest();
-
- return toHexString(b);
+ return Util.toString(digest.digest());
}
/**
@@ -114,26 +114,6 @@ public class ChecksumUtil
return createChecksum(new FileInputStream(file));
}
- /**
- * Method description
- *
- *
- * @param byteArray
- *
- * @return
- */
- private static String toHexString(byte[] byteArray)
- {
- StringBuilder buffer = new StringBuilder();
-
- for (byte b : byteArray)
- {
- buffer.append(Integer.toHexString(b));
- }
-
- return buffer.toString();
- }
-
//~--- get methods ----------------------------------------------------------
/**
diff --git a/scm-core/src/main/java/sonia/scm/util/Util.java b/scm-core/src/main/java/sonia/scm/util/Util.java
index 3512223c1a..d58528bfc5 100644
--- a/scm-core/src/main/java/sonia/scm/util/Util.java
+++ b/scm-core/src/main/java/sonia/scm/util/Util.java
@@ -29,6 +29,8 @@
*
*/
+
+
package sonia.scm.util;
//~--- JDK imports ------------------------------------------------------------
@@ -219,4 +221,33 @@ public class Util
{
return (array != null) && (array.length > 0);
}
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param byteValue
+ *
+ * @return
+ */
+ public static String toString(byte[] byteValue)
+ {
+ StringBuilder buffer = new StringBuilder();
+
+ for (int i = 0; i < byteValue.length; i++)
+ {
+ int x = byteValue[i] & 0xff;
+
+ if (x < 16)
+ {
+ buffer.append('0');
+ }
+
+ buffer.append(Integer.toString(x, 16));
+ }
+
+ return buffer.toString();
+ }
}
diff --git a/scm-webapp/src/main/webapp/resources/js/sonia.repository.js b/scm-webapp/src/main/webapp/resources/js/sonia.repository.js
index a005b27325..34f59189d0 100644
--- a/scm-webapp/src/main/webapp/resources/js/sonia.repository.js
+++ b/scm-webapp/src/main/webapp/resources/js/sonia.repository.js
@@ -223,7 +223,7 @@ Sonia.repository.Panel = Ext.extend(Ext.Panel, {
{xtype: 'tbbutton', text: 'Add', scope: this, handler: this.showAddForm},
{xtype: 'tbbutton', text: 'Remove', scope: this, handler: this.removeRepository},
'-',
- {xtype: 'tbbutton', text: 'Reload', scope: this, handler: this.reload},
+ {xtype: 'tbbutton', text: 'Reload', scope: this, handler: this.reload}
],
items: [{
id: 'repositoryGrid',
diff --git a/scm-webapp/src/main/webapp/resources/js/sonia.user.js b/scm-webapp/src/main/webapp/resources/js/sonia.user.js
index 7b1532b691..25551c8ed1 100644
--- a/scm-webapp/src/main/webapp/resources/js/sonia.user.js
+++ b/scm-webapp/src/main/webapp/resources/js/sonia.user.js
@@ -228,7 +228,7 @@ Sonia.user.Panel = Ext.extend(Ext.Panel, {
{xtype: 'tbbutton', text: 'Add', scope: this, handler: this.showAddPanel},
{xtype: 'tbbutton', text: 'Remove', scope: this, handler: this.removeUser},
'-',
- {xtype: 'tbbutton', text: 'Reload', scope: this, handler: this.reload},
+ {xtype: 'tbbutton', text: 'Reload', scope: this, handler: this.reload}
],
items: [{
id: 'userGrid',