You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@click.apache.org by sa...@apache.org on 2009/07/18 15:11:42 UTC
svn commit: r795360 - in /incubator/click/trunk/tools/standalone: ./
dev-tasks/src/ dev-tasks/src/org/apache/click/tools/deploy/
Author: sabob
Date: Sat Jul 18 13:11:42 2009
New Revision: 795360
URL: http://svn.apache.org/viewvc?rev=795360&view=rev
Log:
added ant deploy task
Added:
incubator/click/trunk/tools/standalone/CHANGELOG.txt (with props)
incubator/click/trunk/tools/standalone/README.txt
- copied, changed from r728294, incubator/click/trunk/tools/standalone/readme.text
incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/
incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/Deploy.java
incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/DeployReport.java
incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/DeployReportEntry.java
incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/DeployTask.java
incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/TaskUtils.java
incubator/click/trunk/tools/standalone/dev-tasks/src/report-template.html (with props)
Removed:
incubator/click/trunk/tools/standalone/readme.text
Modified:
incubator/click/trunk/tools/standalone/NOTICE.txt
incubator/click/trunk/tools/standalone/build.xml
Added: incubator/click/trunk/tools/standalone/CHANGELOG.txt
URL: http://svn.apache.org/viewvc/incubator/click/trunk/tools/standalone/CHANGELOG.txt?rev=795360&view=auto
==============================================================================
--- incubator/click/trunk/tools/standalone/CHANGELOG.txt (added)
+++ incubator/click/trunk/tools/standalone/CHANGELOG.txt Sat Jul 18 13:11:42 2009
@@ -0,0 +1,13 @@
+Changelog
+=========
+
+Version 1.1 - 2009-08-15
+------------------------
+
+* Added DeployTask to deploy static resources during build time.
+ [https://issues.apache.org/jira/browse/CLK-564]
+
+Version 1.0 - 2009-02-15
+------------------------
+
+* Initial release
Propchange: incubator/click/trunk/tools/standalone/CHANGELOG.txt
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: incubator/click/trunk/tools/standalone/NOTICE.txt
URL: http://svn.apache.org/viewvc/incubator/click/trunk/tools/standalone/NOTICE.txt?rev=795360&r1=795359&r2=795360&view=diff
==============================================================================
--- incubator/click/trunk/tools/standalone/NOTICE.txt (original)
+++ incubator/click/trunk/tools/standalone/NOTICE.txt Sat Jul 18 13:11:42 2009
@@ -1,5 +1,5 @@
Apache Click
-Copyright 2008 The Apache Software Foundation
+Copyright 2008-2009 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
Copied: incubator/click/trunk/tools/standalone/README.txt (from r728294, incubator/click/trunk/tools/standalone/readme.text)
URL: http://svn.apache.org/viewvc/incubator/click/trunk/tools/standalone/README.txt?p2=incubator/click/trunk/tools/standalone/README.txt&p1=incubator/click/trunk/tools/standalone/readme.text&r1=728294&r2=795360&rev=795360&view=diff
==============================================================================
--- incubator/click/trunk/tools/standalone/readme.text (original)
+++ incubator/click/trunk/tools/standalone/README.txt Sat Jul 18 13:11:42 2009
@@ -1,6 +1,10 @@
Standalone Tools for the Click Framework
========================================
-* dev-tasks - a set of ANT tasks to help in the development of Click Framework
- itself, Click based 3rd party controls and Click based webapplications.
+This project contains the following packages:
+
+* deploy - provides an Ant task to deploy Click resources from a given source
+ folder to a target folder.
+* devtasks - a set of ANT tasks to help in the development of Click Framework
+ itself, Click based 3rd party controls and Click based webapplications.
Modified: incubator/click/trunk/tools/standalone/build.xml
URL: http://svn.apache.org/viewvc/incubator/click/trunk/tools/standalone/build.xml?rev=795360&r1=795359&r2=795360&view=diff
==============================================================================
--- incubator/click/trunk/tools/standalone/build.xml (original)
+++ incubator/click/trunk/tools/standalone/build.xml Sat Jul 18 13:11:42 2009
@@ -3,7 +3,7 @@
<!--
Project Properties
-->
- <property name="version" value="1.0"/>
+ <property name="version" value="1.1"/>
<!--
Path Definitions
@@ -23,6 +23,7 @@
</copy>
<copy file="LICENSE.txt" todir="dev-tasks/classes/META-INF"/>
<copy file="NOTICE.txt" todir="dev-tasks/classes/META-INF"/>
+ <copy file="README.txt" todir="dev-tasks/classes/META-INF"/>
<!-- 1. Compile the tasks -->
<javac srcdir="dev-tasks/src"
@@ -30,7 +31,7 @@
debug="true"
excludes="**/Test*"
encoding="ISO-8859-1"
- source="1.4">
+ source="1.5">
<classpath refid="classpath.dev-tasks"/>
</javac>
Added: incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/Deploy.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/Deploy.java?rev=795360&view=auto
==============================================================================
--- incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/Deploy.java (added)
+++ incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/Deploy.java Sat Jul 18 13:11:42 2009
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.click.tools.deploy;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * Provides resourceName deployment operations to copying resources from a source
+ * jar/folder to a target folder.
+ * <p/>
+ * This class also tracks which resources were deployed, skipped or outdated.
+ * This information can then be used to write a summary report of the resources.
+ */
+class Deploy {
+
+ // -------------------------------------------------------------- Variables
+
+ /** The outdated report entries. */
+ private List<DeployReportEntry> outdated = new ArrayList();
+
+ /** The deployed report entries. */
+ private List<DeployReportEntry> deployed = new ArrayList();
+
+ // ------------------------------------------------------ Public Properties
+
+ /**
+ * Return the outdated report entries.
+ *
+ * @return the outdated report entries.
+ */
+ public List<DeployReportEntry> getOutdated() {
+ return outdated;
+ }
+
+ /**
+ * Return the deployed report entries.
+ *
+ * @return the deployed report entries.
+ */
+ public List<DeployReportEntry> getDeployed() {
+ return deployed;
+ }
+
+ // --------------------------------------------------------- Public Methods
+
+ /**
+ * Deploy all resources from the jar to the given target folder.
+ *
+ * @param jar the jar file to extract resources from
+ * @param target the target folder to deploy the resources to
+ * @return true if resources was deployed, false otherwise
+ * @throws IOException if a IO exception occurs
+ */
+ public boolean deployResourcesInJar(File jar, File target) throws IOException {
+ boolean hasDeployed = false;
+
+ // Mark the size of the reportEntries before deployment
+ int before1 = deployed.size();
+ int before2 = outdated.size();
+
+ // example jar -> lib/click-core-2.1.0.jar
+ // example target -> c:/dev/webapp/
+ if (jar == null) {
+ throw new IllegalArgumentException("Jar cannot be null");
+ }
+
+ JarFile jarFile = null;
+
+ try {
+
+ jarFile = new JarFile(jar);
+ JarEntry jarEntry = null;
+
+ // Indicates whether feedback should be logged on the jar being
+ // deployed
+ boolean logFeedback = true;
+ Enumeration<JarEntry> en = jarFile.entries();
+
+ while (en.hasMoreElements()) {
+ jarEntry = en.nextElement();
+
+ // jarEntryName example -> META-INF/web/click/table.css
+ String jarEntryName = jarEntry.getName();
+
+ String prefix = "META-INF/web/";
+ // Only deploy resources from "META-INF/web/"
+ int pathIndex = jarEntryName.indexOf(prefix);
+ if (pathIndex == 0) {
+ if (logFeedback) {
+ System.out.println("deploy files from jar -> "
+ + jar.getCanonicalPath());
+
+ // Only provide feedback once per jar
+ logFeedback = false;
+ }
+ pathIndex += prefix.length();
+ // resourceName example -> click/table.css
+ String resourceName = jarEntryName.substring(pathIndex);
+ int index = resourceName.lastIndexOf('/');
+
+ File targetDir = new File(target.getPath());
+ if (index != -1) {
+ // resourceDir example -> click
+ String resourceDir =
+ resourceName.substring(0, index);
+ targetDir = new File(targetDir, resourceDir);
+ }
+
+ InputStream inputStream = null;
+ try {
+ inputStream = jarFile.getInputStream(jarEntry);
+ byte[] resourceData = TaskUtils.toByteArray(inputStream);
+
+ // Copy resources to web folder
+ deployFile(jarEntryName, resourceData, targetDir);
+
+ } finally {
+ TaskUtils.close(inputStream);
+ }
+ }
+ }
+ } finally {
+ TaskUtils.close(jarFile);
+ }
+
+ int after1 = deployed.size();
+ int after2 = outdated.size();
+
+ // If new reportEntries was added, set hasDeployeed to true
+ if (before1 != after1 || before2 != after2) {
+ hasDeployed = true;
+ }
+ return hasDeployed;
+ }
+
+ /**
+ * Deploy all resources from the source folder to the given target folder.
+ *
+ * @param jar the jar file to extract resources from
+ * @param target the target folder to deploy the resources to
+ * @return true if resources was deployed, false otherwise
+ * @throws IOException if a IO exception occurs
+ */
+ public boolean deployResourcesInDir(File source, File target) throws IOException {
+ boolean hasDeployed = false;
+
+ // Mark the size of the reportEntries before deployment
+ int before1 = deployed.size();
+ int before2 = outdated.size();
+
+ // example source -> c:/source/webapp/WEB-INF/classes
+ // example target -> c:/dev/webapp/
+ if (source == null) {
+ throw new IllegalArgumentException("Jar cannot be null");
+ }
+
+ final String prefix = "META-INF/web";
+
+ if (source.exists()) {
+
+ Iterator files = TaskUtils.listFiles(new File(source, prefix), new FilenameFilter() {
+ public boolean accept(File file, String name) {
+ if (file.isDirectory()) {
+ return false;
+ }
+
+ String path = file.getAbsolutePath();
+ path = path.replace('\\', '/');
+ return path.indexOf(prefix) >= 0;
+ }
+ }).iterator();
+
+ boolean logFeedback = true;
+ while (files.hasNext()) {
+ // example file -> c:/source/webapp/WEB-INF/classes/META-INF/web/click/table.css
+ File file = (File) files.next();
+
+ // Guard against loading folders -> META-INF/web/click/
+ if (file.isDirectory()) {
+ continue;
+ }
+
+ String fileName = file.getCanonicalPath().replace('\\', '/');
+
+ // Only deploy resources from "META-INF/web/"
+ int pathIndex = fileName.indexOf(prefix);
+ if (pathIndex != -1) {
+ if (logFeedback) {
+ System.out.println("load files from folder -> " +
+ source.getAbsolutePath());
+
+ // Only provide feedback once per source
+ logFeedback = false;
+ }
+ pathIndex += prefix.length();
+
+ fileName = fileName.substring(pathIndex);
+ int index = fileName.lastIndexOf('/');
+
+ File targetDir = new File(target.getPath());
+ if (index != -1) {
+ // resourceDir example -> click
+ String resourceDir =
+ fileName.substring(0, index);
+ targetDir = new File(targetDir, resourceDir);
+ }
+
+ InputStream inputStream = null;
+ try {
+ inputStream = new FileInputStream(file);
+ byte[] resourceData = TaskUtils.toByteArray(inputStream);
+
+ // Copy resources to web folder
+ deployFile(fileName, resourceData, targetDir);
+
+ } finally {
+ TaskUtils.close(inputStream);
+ }
+ }
+ }
+ }
+
+ int after1 = deployed.size();
+ int after2 = outdated.size();
+
+ // If new reportEntries was added, set hasDeployeed to true
+ if (before1 != after1 || before2 != after2) {
+ hasDeployed = true;
+ }
+
+ return hasDeployed;
+ }
+
+ /**
+ * Deploy a resource consisting of the resourceName and resourceData to the
+ * target folder.
+ *
+ * @param resourceName the name of the resource to deploy
+ * @param resourceData the resource data as a byte array
+ * @param target the target folder to deploy the resource to
+ * @throws IOException if a IO exception occurs
+ */
+ private void deployFile(String resourceName, byte[] resourceData, File target) {
+
+ if (TaskUtils.isBlank(resourceName)) {
+ String msg = "resource parameter cannot be empty";
+ throw new IllegalArgumentException(msg);
+ }
+
+ if (target == null) {
+ String msg = "Null targetDir parameter";
+ throw new IllegalArgumentException(msg);
+ }
+
+ if (resourceData == null) {
+ String msg = "Null resourceData parameter";
+ throw new IllegalArgumentException(msg);
+ }
+
+ try {
+
+ // Create files deployment directory
+ if (!target.mkdirs()) {
+ if (!target.exists()) {
+ String msg = "could not create deployment directory: "
+ + target.getCanonicalPath();
+ throw new IOException(msg);
+ }
+ }
+
+ String destination = resourceName;
+ int index = resourceName.lastIndexOf('/');
+ if (index != -1) {
+ destination = resourceName.substring(index + 1);
+ }
+
+ File destinationFile = new File(target, destination);
+
+ if (destinationFile.exists()) {
+
+ // Skip directories
+ if (!destinationFile.isDirectory()) {
+
+ InputStream existingResource = new FileInputStream(
+ destinationFile);
+ try {
+ byte[] existingResourceData =
+ TaskUtils.toByteArray(existingResource);
+
+ boolean contentEquals = TaskUtils.areEqual(resourceData,
+ existingResourceData);
+
+ if (!contentEquals) {
+ // Indicate that an updated version of the resourceName
+ // is available
+ outdated.add(new DeployReportEntry(resourceName, resourceName.replace("META-INF/web", "")));
+ }
+
+ } finally {
+ TaskUtils.close(existingResource);
+ }
+ }
+
+ } else {
+
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(destinationFile);
+ fos.write(resourceData, 0, resourceData.length);
+
+ int lastIndex =
+ destination.lastIndexOf(File.separatorChar);
+ if (lastIndex != -1) {
+ destination =
+ destination.substring(lastIndex + 1);
+ }
+ deployed.add(new DeployReportEntry(resourceName, resourceName.replace("META-INF/web", "")));
+
+ } finally {
+ TaskUtils.close(fos);
+ }
+ }
+
+ } catch (IOException ioe) {
+ String msg =
+ "error occured deploying resource " + resourceName
+ + ", error " + ioe;
+ throw new RuntimeException(msg, ioe);
+
+ } catch (SecurityException se) {
+ String msg =
+ "error occured deploying resource " + resourceName
+ + ", error " + se;
+ throw new RuntimeException(msg, se);
+ }
+ }
+}
Added: incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/DeployReport.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/DeployReport.java?rev=795360&view=auto
==============================================================================
--- incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/DeployReport.java (added)
+++ incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/DeployReport.java Sat Jul 18 13:11:42 2009
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.click.tools.deploy;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.List;
+
+/**
+ * Provides a entries writer for deployed resources.
+ */
+class DeployReport {
+
+ /**
+ * Write the given entries entries to the given writer.
+ *
+ * @param source the source folder where the resources are located
+ * @param destination the destination folder where the resources are
+ * deployed to
+ * @param deployed the list of resources that was deployed
+ * @param outdated the list of resources that was outdated
+ * @param writer the writer to write the entries to
+ * @throws IOException if a write error occurs
+ */
+ public void writeReport(String source, String destination,
+ List<DeployReportEntry> deployed, List<DeployReportEntry> outdated,
+ Writer writer) throws IOException {
+
+ if (source == null) {
+ throw new IllegalArgumentException("source is null");
+ }
+ if (destination == null) {
+ throw new IllegalArgumentException("destination is null");
+ }
+ if (writer == null) {
+ throw new IllegalArgumentException("writer is null");
+ }
+
+ if (deployed.size() < 0 && outdated.size() < 0) {
+ return;
+ }
+
+ writer.append("<div class='container'>\n");
+ writer.append("<h4><a name='").append(TaskUtils.getFilename(source)).append("'></a>");
+ if (source.endsWith(".jar")) {
+ writer.append("Jar: ");
+ } else {
+ writer.append("Folder: ");
+ }
+ writer.append(source);
+ writer.append("</h4>\n");
+
+ if (deployed.size() > 0) {
+ writer.append("<div class='deployedHeader'>Deployed Successfully</div>\n");
+ writeReportEntries(source, destination, deployed, writer);
+ }
+ if (outdated.size() > 0) {
+ writer.append("<div class='outdatedHeader'>Outdated</div>\n");
+ writeReportEntries(source, destination, outdated, writer);
+ }
+
+ writer.append("</div>\n");
+ }
+
+ /**
+ * Write the given entries entries to the given writer.
+ *
+ * @param source the source folder where the resources are located
+ * @param destination the destination folder where the resources are
+ * deployed to
+ * @param entries the list of resources that was deployed
+ * @param writer the writer to write the entries to
+ * @throws IOException if a write error occurs
+ */
+ private void writeReportEntries(String source, String destination,
+ List<DeployReportEntry> entries, Writer writer) throws IOException {
+
+ if (entries.size() > 0) {
+ writer.append("<table>\n");
+ writer.append("<tr>");
+ writer.append("<th>Destination - ").append(destination).append("</th>");
+ writer.append("<th>Source - ").append(source).append("</th>");
+ writer.append("</tr>\n");
+ for (DeployReportEntry entry : entries) {
+ writer.append("<tr>");
+ writer.append("<td>");
+ writer.append(entry.destination);
+ writer.append("</td>");
+ writer.append("<td>");
+ writer.append(entry.source);
+ writer.append("</td>");
+ writer.append("</tr>\n");
+ }
+ writer.append("</table>\n");
+ }
+
+ }
+}
Added: incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/DeployReportEntry.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/DeployReportEntry.java?rev=795360&view=auto
==============================================================================
--- incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/DeployReportEntry.java (added)
+++ incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/DeployReportEntry.java Sat Jul 18 13:11:42 2009
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.click.tools.deploy;
+
+/**
+ * Provides a report entry.
+ */
+class DeployReportEntry {
+
+ /** Specify the destination path of a resource. */
+ public String destination;
+
+ /** Specify the source path of a resource. */
+ public String source;
+
+ /**
+ * Default constructor for the given source and destination.
+ *
+ * @param source path of a resource
+ * @param destination path of a resource
+ */
+ public DeployReportEntry(String source, String destination) {
+ this.source = source;
+ this.destination = destination;
+ }
+}
Added: incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/DeployTask.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/DeployTask.java?rev=795360&view=auto
==============================================================================
--- incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/DeployTask.java (added)
+++ incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/DeployTask.java Sat Jul 18 13:11:42 2009
@@ -0,0 +1,295 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.click.tools.deploy;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.jar.JarFile;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.FileSet;
+
+/**
+ * Provides an Ant task to deploy Click resources from a given source folder to
+ * a target folder.
+ * <p/>
+ * An HTML report is generated which summarizes resources that was deployed and
+ * resources that are outdated.
+ */
+public class DeployTask extends Task {
+
+ // -------------------------------------------------------------- Variables
+
+ /** Directory where filenames can be found. */
+ private File dir;
+
+ /** Directory where filenames should be deployed to. */
+ private File toDir;
+
+ /** The include filter to use when scanning {@link #dir}. */
+ private String includes;
+
+ /** The exclude filter to use when scanning {@link #dir}. */
+ private String excludes;
+
+ /** FileSet that specifies jars and folders to check for filenames. */
+ private FileSet fileSet;
+
+ // ----------------------------------------------------------- Constructors
+
+ /**
+ * Creates a default DeployTask instance.
+ */
+ public DeployTask() {
+ fileSet = new FileSet();
+ }
+
+ // ------------------------------------------------------ Public properties
+
+ /**
+ * Set the directory consisting of JARs and folders where filenames are
+ * deployed from.
+ *
+ * @param dir the directory consisting of JARs and folders where filenames
+ * are deployed from.
+ */
+ public void setDir(File dir) {
+ this.dir = dir;
+ }
+
+ /**
+ * Set the target directory where filenames are deployed to.
+ *
+ * @param toDir the target directory where filenames are deployed to.
+ */
+ public void setToDir(File toDir) {
+ this.toDir = toDir;
+ }
+
+ /**
+ * Set the Ant <tt>excludes</tt> pattern for the source {@link #dir}.
+ *
+ * @param excludes the Ant <tt>excludes</tt> pattern for the source
+ * {@link #dir}.
+ */
+ public void setExcludes(String excludes) {
+ this.excludes = excludes;
+ fileSet.setExcludes(excludes);
+ }
+
+ /**
+ * Set the Ant <tt>includes</tt> pattern for the source {@link #dir}.
+ *
+ * @param includes the Ant <tt>includes</tt> pattern for the source
+ * {@link #dir}.
+ */
+ public void setIncludes(String includes) {
+ this.includes = includes;
+ fileSet.setIncludes(includes);
+ }
+
+ /**
+ * Return the Ant <tt>includes</tt> pattern for the source {@link #dir}.
+ *
+ * @return the Ant <tt>includes</tt> pattern for the source {@link #dir}.
+ */
+ public String getIncludes() {
+ return includes;
+ }
+
+ // --------------------------------------------------------- Public Methods
+
+ /**
+ * Execute the task.
+ *
+ * @throws BuildException if the build fails
+ */
+ public void execute() throws BuildException {
+ if(dir == null) {
+ throw new BuildException("dir attribute must be set!");
+ }
+ if(!dir.exists()) {
+ throw new BuildException("dir does not exist!");
+ }
+ if(!dir.isDirectory()) {
+ throw new BuildException("dir is not a directory!");
+ }
+
+ if(toDir == null) {
+ throw new BuildException("todir attribute must be set!");
+ }
+ if(!toDir.exists()) {
+ if (!toDir.mkdirs()) {
+ throw new BuildException("Could not create todir '" + toDir + "'!");
+ }
+ System.out.println("todir '" + toDir + "' created.");
+ }
+ if(!toDir.isDirectory()) {
+ throw new BuildException("todir is not a directory!");
+ }
+
+ fileSet.setDir(dir);
+ fileSet.setDefaultexcludes(true);
+ if (getIncludes() == null) {
+ // Set default standard includes
+ fileSet.setIncludes("**/*.jar, classes");
+ }
+ DirectoryScanner directoryScanner = fileSet.getDirectoryScanner(getProject());
+ String files[] = directoryScanner.getIncludedFiles();
+ String dirs[] = directoryScanner.getIncludedDirectories();
+ String resources[] = (String[]) TaskUtils.addAll(files, dirs);
+
+ deployResources(resources);
+ }
+
+ // -------------------------------------------------------- Private Methods
+
+ /**
+ * Deploy the resources specified by the given filenames.
+ *
+ * @param filenames the filenames for the resources to deploy.
+ */
+ private void deployResources(String filenames[]) {
+ Writer reportWriter = null;
+ try {
+
+ InputStream is = TaskUtils.getResourceAsStream("/report-template.html", DeployTask.class);
+ String template = null;
+
+ if (is == null) {
+ System.out.println("The report template 'report-template.html' could not be found on the classpath. No report will be generated.");
+ } else {
+ template = TaskUtils.toString(is);
+ }
+
+ DeployReport report = new DeployReport();
+
+ StringWriter writer = new StringWriter();
+ for (int i = 0; i < filenames.length; i++) {
+ String filename = filenames[i];
+ String path = getCurrentPath();
+ File file = new File(dir, filename);
+
+ Deploy deploy = new Deploy();
+
+ boolean deployed = false;
+
+ if (filename.indexOf(".jar") >= 0) {
+ deployed = deploy.deployResourcesInJar(file, toDir);
+ } else {
+ deployed = deploy.deployResourcesInDir(file, toDir);
+ }
+
+ if (deployed) {
+ report.writeReport(path + filename, toDir.getCanonicalPath(),
+ deploy.getDeployed(), deploy.getOutdated(), reportWriter);
+ }
+ }
+
+ if (template != null) {
+ String reportContent = template;
+ reportContent = reportContent.replace("{0}", dir.getCanonicalPath());
+ reportContent = reportContent.replace("{1}", toDir.getCanonicalPath());
+ reportContent = reportContent.replace("{2}", toHtml(filenames));
+
+ String reportEntries = writer.toString();
+
+ // If no report entries were made, print a success message
+ if (TaskUtils.isBlank(reportEntries)) {
+ reportContent = reportContent.replace("{3}", "<h3 class='success'>All resources are successfully deployed</h3>");
+ } else {
+ reportContent = reportContent.replace("{3}", writer.toString());
+ }
+
+ File reportFile = new File("report.html");
+ reportWriter = new FileWriter(reportFile);
+ reportWriter.append(reportContent);
+ System.out.println("See report: " + reportFile.getCanonicalPath());
+ }
+
+ } catch(IOException ioe) {
+ throw new BuildException(ioe.getClass().getName() + ":" + ioe.getMessage(), ioe);
+
+ } finally {
+ TaskUtils.close(reportWriter);
+ }
+ }
+
+ /**
+ * Returns the current path.
+ *
+ * @return the current path
+ * @throws IOException if the path cannot be looked up
+ */
+ private String getCurrentPath() throws IOException {
+ String path = dir.getCanonicalPath();
+ return path.endsWith(File.separator) ? path : path + File.separator;
+ }
+
+ /**
+ * Return the HTML representation of the given filenames.
+ *
+ * @param filenames the filenames to represent as HTML
+ * @return return HTML representation of the given filenames
+ * @throws IOException if an IO exception occurs
+ */
+ private String toHtml(String[] filenames) throws IOException {
+ StringBuilder buffer = new StringBuilder();
+
+ if (filenames != null && filenames.length > 0) {
+ String path = getCurrentPath();
+
+ for (String filename : filenames) {
+ if (filename.endsWith(".jar")) {
+ JarFile jarFile = new JarFile(new File(path, filename));
+ if (jarFile.getEntry("META-INF/web") != null) {
+ render(buffer, filename);
+ }
+ } else {
+ File file = new File(path, filename);
+ file = new File(file, "META-INF/web");
+ if (file.exists()) {
+ render(buffer, filename);
+ }
+ }
+ }
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * Render the HTML represenation of the given filename.
+ *
+ * @param buffer the buffer to render the HTML representation to
+ * @param filename the filename to render
+ */
+ private void render(StringBuilder buffer, String filename) {
+ buffer.append("<li><a href='#");
+ buffer.append(TaskUtils.getFilename(filename));
+ buffer.append("'>");
+ buffer.append(filename);
+ buffer.append("</a></li>");
+ }
+}
Added: incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/TaskUtils.java
URL: http://svn.apache.org/viewvc/incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/TaskUtils.java?rev=795360&view=auto
==============================================================================
--- incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/TaskUtils.java (added)
+++ incubator/click/trunk/tools/standalone/dev-tasks/src/org/apache/click/tools/deploy/TaskUtils.java Sat Jul 18 13:11:42 2009
@@ -0,0 +1,448 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.click.tools.deploy;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.jar.JarFile;
+
+/**
+ * Provides common String and Stream utility methods.
+ */
+class TaskUtils {
+
+ // -------------------------------------------------------------- Constants
+
+ /** Default buffer size for writing files. */
+ private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
+
+ // --------------------------------------------------------- Public Methods
+
+ /**
+ * Return the input stream for the given name and class.
+ *
+ * @param name the name of the resource to return
+ * @param aClass the class which class loader to use
+ * @return the input stream for the given name and class
+ */
+ public static InputStream getResourceAsStream(String name, Class aClass) {
+ if (isBlank(name)) {
+ throw new IllegalArgumentException("Parameter name cannot be blank");
+ };
+
+ if (aClass == null) {
+ throw new IllegalArgumentException("Parameter aClass is null");
+ }
+
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+
+ InputStream inputStream = classLoader.getResourceAsStream(name);
+ if (inputStream == null) {
+ inputStream = aClass.getResourceAsStream(name);
+ }
+
+ return inputStream;
+ }
+
+ /**
+ * Extract and return the filename from the path.
+ *
+ * @param path the path to extract the filename from
+ * @return the path filename
+ */
+ public static String getFilename(String path) {
+ if (isBlank(path)) {
+ return "";
+ }
+ path = path.replace('\\', '/');
+ int index = path.lastIndexOf("/");
+ if (index >= 0) {
+ return path.substring(index + 1);
+ }
+ return path;
+ }
+
+ /**
+ * Return all the files in the specified directory and sub-directories. The
+ * given filter can be used to accept or reject files.
+ *
+ * @param directory the directory which files to return
+ * @param filter a filter to accept or reject files
+ * @return the list of files in the directory and sub-directories
+ */
+ public static List<File> listFiles(File directory, FilenameFilter filter) {
+ List<File> files = new ArrayList<File>();
+
+ File[] entries = directory.listFiles();
+
+ for (File entry : entries) {
+ if (filter == null || filter.accept(entry, entry.getName())) {
+ files.add(entry);
+ }
+
+ if (entry.isDirectory()) {
+ files.addAll(listFiles(entry, filter));
+ }
+ }
+
+ return files;
+ }
+
+ // --------------------------------------------- Copied from Apache Commons
+
+ /**
+ * Get the contents of an <code>InputStream</code> as a <code>byte[]</code>.
+ * <p>
+ * This method buffers the input internally, so there is no need to use a
+ * <code>BufferedInputStream</code>.
+ *
+ * @param input the <code>InputStream</code> to read from
+ * @return the requested byte array
+ * @throws NullPointerException if the input is null
+ * @throws IOException if an I/O error occurs
+ */
+ public static byte[] toByteArray(InputStream input) throws IOException {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ copy(input, output);
+ return output.toByteArray();
+ }
+
+ /**
+ * Get the contents of an <code>InputStream</code> as a String
+ * using the default character encoding of the platform.
+ * <p/>
+ * This method buffers the input internally, so there is no need to use a
+ * <code>BufferedInputStream</code>.
+ *
+ * @param input the <code>InputStream</code> to read from
+ * @return the requested String
+ * @throws NullPointerException if the input is null
+ * @throws IOException if an I/O error occurs
+ */
+ public static String toString(InputStream input) throws IOException {
+ StringWriter sw = new StringWriter();
+ copy(input, sw);
+ return sw.toString();
+ }
+
+ /**
+ * Copy bytes from an <code>InputStream</code> to an
+ * <code>OutputStream</code>.
+ * <p>
+ * This method buffers the input internally, so there is no need to use a
+ * <code>BufferedInputStream</code>.
+ * <p>
+ * Large streams (over 2GB) will return a bytes copied value of
+ * <code>-1</code> after the copy has completed since the correct
+ * number of bytes cannot be returned as an int. For large streams
+ * use the <code>copyLarge(InputStream, OutputStream)</code> method.
+ *
+ * @param input the <code>InputStream</code> to read from
+ * @param output the <code>OutputStream</code> to write to
+ * @return the number of bytes copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ * @throws ArithmeticException if the byte count is too large
+ * @since Commons IO 1.1
+ */
+ public static int copy(InputStream input, OutputStream output) throws IOException {
+ long count = copyLarge(input, output);
+ if (count > Integer.MAX_VALUE) {
+ return -1;
+ }
+ return (int) count;
+ }
+
+ /**
+ * Copy bytes from an <code>InputStream</code> to chars on a
+ * <code>Writer</code> using the default character encoding of the platform.
+ * <p>
+ * This method buffers the input internally, so there is no need to use a
+ * <code>BufferedInputStream</code>.
+ * <p>
+ * This method uses {@link InputStreamReader}.
+ *
+ * @param input the <code>InputStream</code> to read from
+ * @param output the <code>Writer</code> to write to
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ * @since Commons IO 1.1
+ */
+ public static void copy(InputStream input, Writer output)
+ throws IOException {
+ InputStreamReader in = new InputStreamReader(input);
+ copy(in, output);
+ }
+
+ /**
+ * Copy chars from a <code>Reader</code> to a <code>Writer</code>.
+ * <p>
+ * This method buffers the input internally, so there is no need to use a
+ * <code>BufferedReader</code>.
+ * <p>
+ * Large streams (over 2GB) will return a chars copied value of
+ * <code>-1</code> after the copy has completed since the correct
+ * number of chars cannot be returned as an int. For large streams
+ * use the <code>copyLarge(Reader, Writer)</code> method.
+ *
+ * @param input the <code>Reader</code> to read from
+ * @param output the <code>Writer</code> to write to
+ * @return the number of characters copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ * @throws ArithmeticException if the character count is too large
+ * @since Commons IO 1.1
+ */
+ public static int copy(Reader input, Writer output) throws IOException {
+ long count = copyLarge(input, output);
+ if (count > Integer.MAX_VALUE) {
+ return -1;
+ }
+ return (int) count;
+ }
+
+ /**
+ * Copy bytes from a large (over 2GB) <code>InputStream</code> to an
+ * <code>OutputStream</code>.
+ * <p>
+ * This method buffers the input internally, so there is no need to use a
+ * <code>BufferedInputStream</code>.
+ *
+ * @param input the <code>InputStream</code> to read from
+ * @param output the <code>OutputStream</code> to write to
+ * @return the number of bytes copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ * @since Commons IO 1.3
+ */
+ public static long copyLarge(InputStream input, OutputStream output)
+ throws IOException {
+ byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
+ long count = 0;
+ int n = 0;
+ while (-1 != (n = input.read(buffer))) {
+ output.write(buffer, 0, n);
+ count += n;
+ }
+ return count;
+ }
+
+ /**
+ * Copy chars from a large (over 2GB) <code>Reader</code> to a <code>Writer</code>.
+ * <p>
+ * This method buffers the input internally, so there is no need to use a
+ * <code>BufferedReader</code>.
+ *
+ * @param input the <code>Reader</code> to read from
+ * @param output the <code>Writer</code> to write to
+ * @return the number of characters copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ * @since Commons IO 1.3
+ */
+ public static long copyLarge(Reader input, Writer output) throws IOException {
+ char[] buffer = new char[DEFAULT_BUFFER_SIZE];
+ long count = 0;
+ int n = 0;
+ while (-1 != (n = input.read(buffer))) {
+ output.write(buffer, 0, n);
+ count += n;
+ }
+ return count;
+ }
+
+ /**
+ * Compares two byte arrays for equality.
+ *
+ * @param a A byte[].
+ * @param b A byte[].
+ * @return True if the arrays have identical contents.
+ */
+ public static boolean areEqual(byte[] a, byte[] b) {
+ int aLength = a.length;
+ if (aLength != b.length) {
+ return false;
+ }
+
+ for (int i = 0; i < aLength; i++) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if a String is whitespace, empty ("") or null.
+ * <p/>
+ *
+ * @param str the String to check, may be null
+ * @return <code>true</code> if the String is null, empty or whitespace
+ */
+ public static boolean isBlank(String str) {
+ int strLen;
+ if (str == null || (strLen = str.length()) == 0) {
+ return true;
+ }
+ for (int i = 0; i < strLen; i++) {
+ if ((Character.isWhitespace(str.charAt(i)) == false)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if a String is not empty (""), not null and not whitespace only.
+ * <p/>
+ *
+ * @param str the String to check, may be null
+ * @return <code>true</code> if the String is not empty and not null and not
+ * whitespace
+ */
+ public static boolean isNotBlank(String str) {
+ return !isBlank(str);
+ }
+
+ /**
+ * <p>Adds all the elements of the given arrays into a new array.</p>
+ * <p>The new array contains all of the element of <code>array1</code> followed
+ * by all of the elements <code>array2</code>. When an array is returned, it is always
+ * a new array.</p>
+ *
+ * <pre>
+ * ArrayUtils.addAll(null, null) = null
+ * ArrayUtils.addAll(array1, null) = cloned copy of array1
+ * ArrayUtils.addAll(null, array2) = cloned copy of array2
+ * ArrayUtils.addAll([], []) = []
+ * ArrayUtils.addAll([null], [null]) = [null, null]
+ * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
+ * </pre>
+ *
+ * @param array1 the first array whose elements are added to the new array, may be <code>null</code>
+ * @param array2 the second array whose elements are added to the new array, may be <code>null</code>
+ * @return The new array, <code>null</code> if <code>null</code> array inputs.
+ * The type of the new array is the type of the first array.
+ * @since 2.1
+ */
+ public static Object[] addAll(Object[] array1, Object[] array2) {
+ if (array1 == null) {
+ return clone(array2);
+ } else if (array2 == null) {
+ return clone(array1);
+ }
+ Object[] joinedArray = (Object[]) Array.newInstance(array1.getClass().getComponentType(),
+ array1.length + array2.length);
+
+ System.arraycopy(array1, 0, joinedArray, 0, array1.length);
+ System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
+ return joinedArray;
+ }
+
+ /**
+ * <p>Shallow clones an array returning a typecast result and handling
+ * <code>null</code>.</p>
+ *
+ * <p>The objects in the array are not cloned, thus there is no special
+ * handling for multi-dimensional arrays.</p>
+ *
+ * <p>This method returns <code>null</code> for a <code>null</code> input array.</p>
+ *
+ * @param array the array to shallow clone, may be <code>null</code>
+ * @return the cloned array, <code>null</code> if <code>null</code> input
+ */
+ public static Object[] clone(Object[] array) {
+ if (array == null) {
+ return null;
+ }
+ return (Object[]) array.clone();
+ }
+
+
+ /**
+ * Close the given input stream and ignore any exceptions thrown.
+ *
+ * @param stream the input stream to close.
+ */
+ public static void close(InputStream stream) {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException ex) {
+ // Ignore.
+ }
+ }
+ }
+
+ /**
+ * Close the given writer and ignore any exceptions thrown.
+ *
+ * @param stream the writer to close.
+ */
+ public static void close(Writer writer) {
+ if (writer != null) {
+ try {
+ writer.close();
+ } catch (IOException ex) {
+ // Ignore.
+ }
+ }
+ }
+
+ /**
+ * Close the given output stream and ignore any exceptions thrown.
+ *
+ * @param stream the output stream to close.
+ */
+ public static void close(OutputStream stream) {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException ex) {
+ // Ignore.
+ }
+ }
+ }
+
+ /**
+ * Close the given jar file and ignore any exceptions thrown.
+ *
+ * @param file the jar file to close.
+ */
+ public static void close(JarFile file) {
+ if (file != null) {
+ try {
+ file.close();
+ } catch (IOException ex) {
+ // Ignore.
+ }
+ }
+ }
+}
Added: incubator/click/trunk/tools/standalone/dev-tasks/src/report-template.html
URL: http://svn.apache.org/viewvc/incubator/click/trunk/tools/standalone/dev-tasks/src/report-template.html?rev=795360&view=auto
==============================================================================
--- incubator/click/trunk/tools/standalone/dev-tasks/src/report-template.html (added)
+++ incubator/click/trunk/tools/standalone/dev-tasks/src/report-template.html Sat Jul 18 13:11:42 2009
@@ -0,0 +1,101 @@
+<!doctype html>
+
+<html>
+ <head>
+ <style rel="stylesheet" type="text/css">
+ body, table, td, p {
+ font-family: verdana, arial, helvetica, lucida-sans, sans-serif;
+ font-size: 10pt;
+ }
+ .success {
+ padding: 3px;
+ float: left;
+ }
+ .success, .deployed {
+ background-color: #0F8800;
+ color: white;
+ font-weight: bold;
+ }
+ .outdated {
+ background-color: #FF1400;
+ color: white;
+ font-weight: bold;
+ }
+
+ .deployedHeader, .outdatedHeader {
+ text-align: left;
+ color: white;
+ font-weight: bold;
+ margin: 1px;
+ padding: 2px;
+ border: 1px solid #CCC;
+ }
+ .deployedHeader {
+ background-color: #0F8800;
+ }
+ .outdatedHeader {
+ background-color: #FF1400;
+ }
+ .container {
+ margin-top: 1em;
+ padding: 0px 0px 10px;
+ border: 1px solid gray;
+ background-color: #EEE;
+ }
+ .container h4 {
+ background-color: #CCC;
+ padding: 3px;
+ margin: 0;
+ border-bottom: 1px solid gray;
+ }
+ .container table {
+ width: 100%;
+ }
+ .container th {
+ text-align: left;
+ width: 50%;
+ }
+ </style>
+ </head>
+
+ <body>
+
+ <h3>Apache Click - Resource Deployment Report</h3>
+
+ This report shows the JavaScript, CSS, images and other resources found
+ under the folder "<tt>{0}</tt>" that was deployed to the target folder
+ "<tt>{1}</tt>".
+
+ <p/>
+
+ The following JARs and folders contains deployable resources
+ (deployable resources are found in JARs and folders under <tt>WEB-INF/web</tt>):
+
+ <ul>
+ {2}
+ </ul>
+
+ Resources can have one of three states:
+
+ <ul>
+ <li>Deployed - the resource was deployed from the JAR to the target folder</li>
+ <li>Outdated <span style="color:red">*</span> - the resource was already
+ deployed, but a newer version of the resource is available</li>
+ <li>Current - the resource was already deployed, no redeploy was necessary.
+ Please note, this state is not shown in the detailed report as it is redundent information</li>
+ </ul>
+
+ <span style="color:red">*</span> Outdated resources must be
+ manually redeployed by either deleting the existing resource and executing
+ the deploy task again, or if the existing resource was customized, it must
+ be merged by your IDE diff utility.
+
+ <p/>
+
+ Below is the detailed report for the resources that was <tt>Deployed Successfully
+ </tt> or <tt>Outdated</tt>.
+
+ {3}
+
+ </body>
+</html>
Propchange: incubator/click/trunk/tools/standalone/dev-tasks/src/report-template.html
------------------------------------------------------------------------------
svn:mime-type = text/html