--- /dev/null
+Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2014 ByteLife Solutions OÜ
+
+ Licensed 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.
+
--- /dev/null
+vFLOWer Toolkit
+============================
+*Created by ByteLife Solutions*
+
+
+<h4>1. OVERVIEW</h4>
+
+vFLOWer Toolkit enables exchanging VMware vCenter Orchestrator content (workflows, actions, etc) as a versionable
+source code in XML format. Along with its pre-requisite components vFLOWer allows vCO administrators and/or developers
+to perform the following actions:
+
+* Retrieve vCO content source code in XML format from remote version control repositories and
+build a binary vCO package to be imported into vCO.
+* Publish vCO content source code in XML format to remote version control repositories by
+unpacking/converting exported binary vCO packages.
+
+**NOTE**
+Current version of this integration tool handles only vCO packages. For publishing, vCO packages
+must be created first including all needed content.
+
+
+<h4>2. PRE-REQUISITES</h4>
+
+To work properly vFLOWer Toolkit needs multiple additional publicly available software components:
+
+* Apache Ant. Tested with version 1.9.3. http://ant.apache.org/bindownload.cgi.
+* Oracle Java SE Development Kit. Tested with JDK 1.7.0.45 for Windows.
+http://www.oracle.com/technetwork/java/javase/downloads/index.html.
+* OpenSSL. Needed for vCO packages retrieval only. Tested with OpenSSL 1.0.1e for Windows. http://www.openssl.org.
+* Git command-line client. Tested with Git 1.8.5.2 for Windows. http://git-scm.com/downloads.
+* VMware vCenter Orchestrator client.
+* VMware vCenter Orchestrator. Tested with versions 5.1 and 5.5.
+
+**NOTES**
+* This product includes software developed by the Ant-Contrib project
+(http://sourceforge.net/projects/ant-contrib).
+* When using Windows as a client platform, Git client must be set up with UNIX-style file formats.
+vCO is expecting that.
+* On a client machine ANT_HOME and JAVA_HOME environment variables must be set. In addition,
+PATH environment variable must be updated to include ANT, Java, Git client and OpenSSL binary directories.
+
+
+<h4>3. PUBLISHING vCO CONTENT TO THE GitHub</h4>
+
+Multiple manual steps must be performed in order to publish vCO content to GitHub repository.
+All steps can be performed from a client machine having all needed pre-requisite components installed.
+
+* User account created in GitHub (if not existing).
+* New repository created in GitHub for publishable content.
+* New GitHub repository cloned to the client machine (git clone).
+* A vCO package created using vCO client to include all needed content.
+* The package exported to the client machine into specified input/output directory (part of repository
+folder structure) using vCO client.
+* ByteLife’s ANT precommit script launched from the repository root directory to unpack/convert
+the vCO package into XML-based source code.
+* New content commited and pushed to the remote GitHub repository (git commit, git push).
+
+
+<h4>4. RETRIEVING vCO CONTENT FROM THE GitHub</h4>
+
+Multiple manual steps must be performed in order to retrieve vCO content from public GitHub repository.
+All steps can be performed from a client machine having all needed pre-requisite components installed.
+
+* vCO content source code downloaded from a public GitHub repository. Content can be downloaded
+by cloning remote repository (git clone) to the client machine which includes all needed ANT scripts
+and folder structure.
+* ByteLife’s ANT build script launched from the repository root directory to build a vCO package from
+downloaded XML-based source code.
+* The package imported from specified input/output directory to the vCO using vCO client.
+
+
+==============================================
+For more information review **vFLOWer_User_Guide.pdf**
+
+For pre-requisites installation hints review **vFLOWer_Prereq_Install_Guide.pdf**
+
+See also http://www.bytelife.com/vFLOWer
+
--- /dev/null
+<project name="vFLOWer">
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml">
+ <classpath>
+ <pathelement location="ant.lib/ant-contrib/ant-contrib-1.0.jar"/>
+ </classpath>
+ </taskdef>
+
+ <!-- Folder for unpacked files -->
+ <property name="content.folder" value="content"/>
+
+ <!-- Folder for vCO transfer zone -->
+ <property name="pkg.folder" value="inout"/>
+
+ <!-- Information for self-signed certificate -->
+ <property name="cert.name" value="www.bytelife.com"/>
+ <property name="cert.country" value="EE"/>
+ <property name="cert.org" value="ByteLife"/>
+ <property name="cert.orgUnit" value="Automation Team"/>
+
+ <macrodef name="reverseCertInfoString">
+ <attribute name="reverse.prop.suffix" default="0"/>
+ <attribute name="reverse.buffer" default=""/>
+ <attribute name="property"/>
+ <attribute name="src"/>
+ <sequential>
+ <math result="@{property}.reverse.nextCnt@{reverse.prop.suffix}" operand1="@{reverse.prop.suffix}"
+ operation="+" operand2="1" datatype="int"/>
+ <if>
+ <equals arg1="@{src}" arg2=""/>
+ <then>
+ <property name="@{property}" value="@{reverse.buffer}"/>
+ </then>
+ <else>
+ <propertyregex property="@{property}.reverse.token@{reverse.prop.suffix}"
+ input="@{src}" regexp="^\s*([^/\s]*(\s+[^/\s]*)*)" select="\1"/>
+ <propertyregex property="@{property}.reverse.rest@{reverse.prop.suffix}"
+ input="@{src}" regexp="^[^/]*/*(.*)$" select="\1"/>
+ <if>
+ <or>
+ <equals arg1="@{reverse.buffer}" arg2=""/>
+ <equals arg1="@{reverse.prop.suffix}" arg2="0"/>
+ </or>
+ <then>
+ <property name="@{property}.reverse.delimiter@{reverse.prop.suffix}" value=""/>
+ </then>
+ <else>
+ <property name="@{property}.reverse.delimiter@{reverse.prop.suffix}" value=","/>
+ </else>
+ </if>
+ <reverseCertInfoString reverse.prop.suffix="${@{property}.reverse.nextCnt@{reverse.prop.suffix}}"
+ reverse.buffer="${@{property}.reverse.token@{reverse.prop.suffix}}${@{property}.reverse.delimiter@{reverse.prop.suffix}}@{reverse.buffer}"
+ property="@{property}"
+ src="${@{property}.reverse.rest@{reverse.prop.suffix}}"/>
+ </else>
+ </if>
+ </sequential>
+ </macrodef>
+
+ <target name="precommit">
+ <foreach param="pkg.file" target="unpack.package">
+ <path>
+ <sort>
+ <fileset dir="${pkg.folder}" includes="*.package"/>
+ <reverse xmlns="antlib:org.apache.tools.ant.types.resources.comparators">
+ <date/>
+ </reverse>
+ </sort>
+ </path>
+ </foreach>
+ </target>
+
+ <target name="build">
+ <foreach param="pkg.file" target="build.package">
+ <path>
+ <sort>
+ <fileset dir="${content.folder}/Packages" includes="*.package.xml"/>
+ <reverse xmlns="antlib:org.apache.tools.ant.types.resources.comparators">
+ <date/>
+ </reverse>
+ </sort>
+ </path>
+ </foreach>
+ </target>
+
+ <target name="build.package">
+ <basename property="pack.pkg.destfile" file="${pkg.file}" suffix=".xml"/>
+ <if>
+ <and>
+ <available file="${pkg.folder}/${pack.pkg.destfile}"/>
+ <uptodate srcfile="${pkg.file}" targetfile="${pkg.folder}/${pack.pkg.destfile}"/>
+ </and>
+ <then>
+ <echo message=""${pkg.folder}/${pack.pkg.destfile}" already exists and is up-to-date. Skip processing "${pkg.file}"."/>
+ </then>
+ <else>
+ <tempfile property="pack.pkg.tempdir" destdir="${pkg.folder}"/>
+ <tempfile property="pack.pkg.packdir" destDir="${pack.pkg.tempdir}"/>
+
+ <!-- Creating self-signed certificate -->
+ <property name="pack.pkg.certsubject" value="/C=${cert.country}/O=${cert.org}/OU=${cert.orgUnit}/CN=${cert.name}"/>
+ <reverseCertInfoString property="pack.pkg.owner" src="${pack.pkg.certsubject}"/>
+ <property name="pack.pkg.signer" value="${pack.pkg.owner}"/>
+
+ <mkdir dir="${pack.pkg.packdir}/certificates"/>
+ <exec executable="openssl" failonerror="true">
+ <arg value="req"/>
+ <arg value="-x509"/>
+ <arg value="-sha512"/>
+ <arg value="-nodes"/>
+ <arg value="-days"/>
+ <arg value="3652"/>
+ <arg value="-subj"/>
+ <arg value="${pack.pkg.certsubject}"/>
+ <arg value="-newkey"/>
+ <arg value="rsa:2048"/>
+ <arg value="-outform"/>
+ <arg value="DER"/>
+ <arg value="-keyout"/>
+ <arg value="${pack.pkg.tempdir}/private.key"/>
+ <arg value="-out"/>
+ <arg value="${pack.pkg.packdir}/certificates/${pack.pkg.owner}.cer"/>
+ </exec>
+
+ <xmlproperty file="${pkg.file}" collapseAttributes="true"/>
+<echo file="${pack.pkg.packdir}/dunes-meta-inf"><?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+</echo>
+ <echoxml file="${pack.pkg.packdir}/dunes-meta-inf" append="true">
+ <properties>
+ <comment>UTF-16</comment>
+ <entry key="pkg-description">${package.description}</entry>
+ <entry key="pkg-name">${package.name}</entry>
+ <entry key="pkg-signer">${pack.pkg.signer}</entry>
+ <entry key="pkg-owner">${pack.pkg.owner}</entry>
+ <entry key="pkg-id">${package.id}</entry>
+ </properties>
+ </echoxml>
+
+ <propertyselector property="pack.pkg.elements"
+ match="^package\.([^.]+\.id-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\..+$"
+ distinct="true" select="\1"/>
+ <foreach param="pack.pkg.element" list="${pack.pkg.elements}"
+ target="pack.package.element" inheritall="true"/>
+
+ <!-- Copying package directory structure for signatures -->
+ <copy todir="${pack.pkg.packdir}/signatures">
+ <dirset dir="${pack.pkg.packdir}"/>
+ </copy>
+
+ <!-- Signing all package files -->
+ <apply executable="openssl" failonerror="true">
+ <arg value="dgst"/>
+ <arg value="-md5"/>
+ <arg value="-sign"/>
+ <arg value="${pack.pkg.tempdir}/private.key"/>
+ <arg value="-out"/>
+ <targetfile/>
+ <fileset dir="${pack.pkg.packdir}"/>
+ <mapper type="glob" from="*" to="${pack.pkg.packdir}/signatures/*"/>
+ </apply>
+
+ <zip destfile="${pkg.folder}/${pack.pkg.destfile}" basedir="${pack.pkg.packdir}" level="9"/>
+ <delete dir="${pack.pkg.tempdir}"/>
+ <touch file="${pkg.file}"/>
+ </else>
+ </if>
+ </target>
+
+ <target name="pack.package.element">
+ <propertyregex property="pack.pkg.el.type" input="${pack.pkg.element}" regexp="^([^.]+)s" select="\1"/>
+ <propertyregex property="pack.pkg.el.id" input="${pack.pkg.element}" regexp="^[^.]+s\.id-(.*)$" select="\1"/>
+ <propertycopy property="pack.pkg.el.src" from="package.${pack.pkg.element}.path"/>
+ <property name="pack.pkg.el.packdir" value="${pack.pkg.packdir}/elements/${pack.pkg.el.id}"/>
+ <basename property="pack.pkg.el.srcfile" file="${pack.pkg.el.src}"/>
+ <propertyregex property="pack.pkg.el.category" input="${pack.pkg.el.src}" regexp="^(.*)/${pack.pkg.el.srcfile}$" select="\1"/>
+
+ <if>
+ <equals arg1="${pack.pkg.el.type}" arg2="resource"/>
+ <then>
+ <tempfile property="pack.pkg.res.tempdir" destdir="${pack.pkg.tempdir}"/>
+ <tempfile property="pack.pkg.res.packdir" destdir="${pack.pkg.res.tempdir}"/>
+ <copy file="${content.folder}/Resources/${pack.pkg.el.src}" tofile="${pack.pkg.res.packdir}/VSO-RESOURCE-INF/data"/>
+ <echo file="${pack.pkg.res.packdir}/VSO-RESOURCE-INF/attribute_id">${pack.pkg.el.id}</echo>
+ <propertycopy property="pack.pkg.el.resname" from="package.${pack.pkg.element}.name"/>
+ <echo file="${pack.pkg.res.packdir}/VSO-RESOURCE-INF/attribute_name">${pack.pkg.el.resname}</echo>
+ <propertycopy property="pack.pkg.el.resdescr" from="package.${pack.pkg.element}.description"/>
+ <echo file="${pack.pkg.res.packdir}/VSO-RESOURCE-INF/attribute_description">${pack.pkg.el.resdescr}</echo>
+ <propertycopy property="pack.pkg.el.resmimetype" from="package.${pack.pkg.element}.mimetype"/>
+ <echo file="${pack.pkg.res.packdir}/VSO-RESOURCE-INF/attribute_mimetype">${pack.pkg.el.resmimetype}</echo>
+ <propertycopy property="pack.pkg.el.respermissions" from="package.${pack.pkg.element}.permissions"/>
+ <echo file="${pack.pkg.res.packdir}/VSO-RESOURCE-INF/attribute_allowedOperations">${pack.pkg.el.respermissions}</echo>
+ <propertycopy property="pack.pkg.el.resver" from="package.${pack.pkg.element}.version"/>
+ <echo file="${pack.pkg.res.packdir}/VSO-RESOURCE-INF/attribute_version">${pack.pkg.el.resver}</echo>
+
+ <zip destfile="${pack.pkg.res.tempdir}/data" basedir="${pack.pkg.res.packdir}" level="9"/>
+ <copy file="${pack.pkg.res.tempdir}/data" tofile="${pack.pkg.el.packdir}/data"/>
+ <property name="pack.pkg.el.typeinfo" value="ResourceElement"/>
+ </then>
+ <else>
+ <switch value="${pack.pkg.el.type}">
+ <case value="configuration">
+ <property name="pack.pkg.el.datafile" value="${content.folder}/Configurations/${pack.pkg.el.src}"/>
+ <property name="pack.pkg.el.typeinfo" value="ConfigurationElement"/>
+ </case>
+ <case value="action">
+ <property name="pack.pkg.el.datafile" value="${content.folder}/Actions/${pack.pkg.el.src}"/>
+ <property name="pack.pkg.el.typeinfo" value="ScriptModule"/>
+ </case>
+ <case value="workflow">
+ <property name="pack.pkg.el.datafile" value="${content.folder}/Workflows/${pack.pkg.el.src}"/>
+ <property name="pack.pkg.el.typeinfo" value="Workflow"/>
+ </case>
+ <default>
+ <fail message="Unknown element type "${pack.pkg.el.type}" found in package "${package.name}"."/>
+ </default>
+ </switch>
+ <copy file="${pack.pkg.el.datafile}" tofile="${pack.pkg.el.packdir}/data" outputencoding="UTF-16"/>
+ <replaceregexp file="${pack.pkg.el.packdir}/data" encoding="UTF-16"
+ match="(encoding\s*=\s*)"[^"]*"" flags="i" replace="\1"UTF-16""/>
+ </else>
+ </if>
+
+<echo file="${pack.pkg.el.packdir}/info"><?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+</echo>
+ <echoxml file="${pack.pkg.el.packdir}/info" append="true">
+ <properties>
+ <comment>UTF-16</comment>
+ <entry key="type">${pack.pkg.el.typeinfo}</entry>
+ <entry key="id">${pack.pkg.el.id}</entry>
+ </properties>
+ </echoxml>
+
+ <echo file="${pack.pkg.el.packdir}/categories" encoding="UTF-16"><categories></echo>
+ <for param="cat.name" list="${pack.pkg.el.category}" delimiter="/" trim="true">
+ <sequential>
+ <echo file="${pack.pkg.el.packdir}/categories" encoding="UTF-16" append="true"><category name="@{cat.name}"></category></echo>
+ </sequential>
+ </for>
+ <echo file="${pack.pkg.el.packdir}/categories" encoding="UTF-16" append="true"></categories></echo>
+ </target>
+
+ <target name="unpack.package">
+ <property name="unpack.pkg.destdir" value="${content.folder}/Packages"/>
+
+ <basename property="unpack.pkg.pkgname" file="${pkg.file}" suffix="package"/>
+
+ <tempfile property="unpack.pkg.tempdir" destDir="${unpack.pkg.destdir}"/>
+ <tempfile property="unpack.pkg.listdir" destDir="${unpack.pkg.tempdir}"/>
+ <mkdir dir="${unpack.pkg.listdir}"/>
+ <unzip src="${pkg.file}" dest="${unpack.pkg.tempdir}"/>
+ <foreach param="unpack.pkg.el.srcdir" target="unpack.package.element">
+ <path>
+ <dirset dir="${unpack.pkg.tempdir}/elements" includes="*" erroronmissingdir="false"/>
+ </path>
+ <param name="unpack.pkg.listdir" value="${unpack.pkg.listdir}"/>
+ <param name="pkg.srcfile" value="${pkg.file}"/>
+ </foreach>
+
+ <tempfile property="unpack.pkg.pkgprops" destDir="${unpack.pkg.tempdir}"/>
+ <replaceregexp file="${unpack.pkg.tempdir}/dunes-meta-inf" match="<!DOCTYPE\s[^>]+>" flags="sgi" replace=""/>
+ <xslt style="getProperties.xsl" in="${unpack.pkg.tempdir}/dunes-meta-inf" out="${unpack.pkg.pkgprops}"/>
+ <loadproperties srcfile="${unpack.pkg.pkgprops}"/>
+ <if>
+ <not>
+ <isset property="entry.pkg-description"/>
+ </not>
+ <then>
+ <property name="entry.pkg-description" value=""/>
+ </then>
+ </if>
+
+ <tempfile property="unpack.pkg.tempdestfile" destDir="${unpack.pkg.tempdir}"/>
+ <if>
+ <available file="${unpack.pkg.listdir}/WorkflowList.xml"/>
+ <then>
+ <loadfile property="unpack.pkg.wflist" srcfile="${unpack.pkg.listdir}/WorkflowList.xml"/>
+ </then>
+ <else>
+ <property name="unpack.pkg.wflist" value=""/>
+ </else>
+ </if>
+ <if>
+ <available file="${unpack.pkg.listdir}/ScriptModuleList.xml"/>
+ <then>
+ <loadfile property="unpack.pkg.actionlist" srcfile="${unpack.pkg.listdir}/ScriptModuleList.xml"/>
+ </then>
+ <else>
+ <property name="unpack.pkg.actionlist" value=""/>
+ </else>
+ </if>
+ <if>
+ <available file="${unpack.pkg.listdir}/ConfigurationElementList.xml"/>
+ <then>
+ <loadfile property="unpack.pkg.cfglist" srcfile="${unpack.pkg.listdir}/ConfigurationElementList.xml"/>
+ </then>
+ <else>
+ <property name="unpack.pkg.cfglist" value=""/>
+ </else>
+ </if>
+ <if>
+ <available file="${unpack.pkg.listdir}/ResourceElementList.xml"/>
+ <then>
+ <loadfile property="unpack.pkg.reslist" srcfile="${unpack.pkg.listdir}/ResourceElementList.xml"/>
+ </then>
+ <else>
+ <property name="unpack.pkg.reslist" value=""/>
+ </else>
+ </if>
+ <echo file="${unpack.pkg.tempdestfile}">
+ <package id="${entry.pkg-id}">
+ <name>${unpack.pkg.pkgname}</name>
+ <description>${entry.pkg-description}</description>
+ <workflows>
+ ${unpack.pkg.wflist}
+ </workflows>
+ <actions>
+ ${unpack.pkg.actionlist}
+ </actions>
+ <configurations>
+ ${unpack.pkg.cfglist}
+ </configurations>
+ <resources>
+ ${unpack.pkg.reslist}
+ </resources>
+ </package>
+ </echo>
+ <xslt style="format.xsl" in="${unpack.pkg.tempdestfile}" out="${unpack.pkg.destdir}/${unpack.pkg.pkgname}.package.xml"/>
+
+ <delete file="${pkg.file}"/>
+ <delete dir="${unpack.pkg.tempdir}"/>
+ <fixcrlf srcDir="${content.folder}" excludes="Resources/**/*" eol="lf"/>
+ </target>
+
+ <target name="unpack.package.element">
+ <tempfile property="unpack.pkg.el.infoprops" destDir="${unpack.pkg.el.srcdir}"/>
+ <replaceregexp file="${unpack.pkg.el.srcdir}/info" match="<!DOCTYPE\s[^>]+>" flags="sgi" replace=""/>
+ <xslt style="getProperties.xsl" in="${unpack.pkg.el.srcdir}/info" out="${unpack.pkg.el.infoprops}"/>
+ <loadproperties srcfile="${unpack.pkg.el.infoprops}"/>
+
+ <tempfile property="unpack.pkg.el.catprops" destDir="${unpack.pkg.el.srcdir}"/>
+ <xslt style="getProperties.xsl" in="${unpack.pkg.el.srcdir}/categories" out="${unpack.pkg.el.catprops}"/>
+ <loadproperties srcfile="${unpack.pkg.el.catprops}"/>
+
+ <if>
+ <equals arg1="${entry.type}" arg2="ResourceElement"/>
+ <then>
+ <tempfile property="unpack.pkg.el.ressrcdir" destDir="${unpack.pkg.el.srcdir}"/>
+ <unzip src="${unpack.pkg.el.srcdir}/data" dest="${unpack.pkg.el.ressrcdir}"/>
+
+ <property name="unpack.pkg.el.srcfile" value="${unpack.pkg.el.ressrcdir}/VSO-RESOURCE-INF/data"/>
+
+ <loadfile property="unpack.pkg.el.elname"
+ srcfile="${unpack.pkg.el.ressrcdir}/VSO-RESOURCE-INF/attribute_name"/>
+ <loadfile property="unpack.pkg.el.resdescr"
+ srcfile="${unpack.pkg.el.ressrcdir}/VSO-RESOURCE-INF/attribute_description"/>
+ <loadfile property="unpack.pkg.el.respermissions"
+ srcfile="${unpack.pkg.el.ressrcdir}/VSO-RESOURCE-INF/attribute_allowedOperations"/>
+ <loadfile property="unpack.pkg.el.resmimetype"
+ srcfile="${unpack.pkg.el.ressrcdir}/VSO-RESOURCE-INF/attribute_mimetype"/>
+ <if>
+ <available file="${unpack.pkg.el.ressrcdir}/VSO-RESOURCE-INF/attribute_version"/>
+ <then>
+ <loadfile property="unpack.pkg.el.resver"
+ srcfile="${unpack.pkg.el.ressrcdir}/VSO-RESOURCE-INF/attribute_version"/>
+ </then>
+ <else>
+ <property name="unpack.pkg.el.resver" value="0.0.0"/>
+ </else>
+ </if>
+
+ <property name="unpack.pkg.el.relpath"
+ value="${element.category}${unpack.pkg.el.elname}"/>
+ <property name="unpack.pkg.el.destfile"
+ value="${content.folder}/Resources/${unpack.pkg.el.relpath}"/>
+
+ <echo file="${unpack.pkg.listdir}/${entry.type}List.xml" append="true">
+ <id-${entry.id} path="${unpack.pkg.el.relpath}">
+ <name>${unpack.pkg.el.elname}</name>
+ <description>${unpack.pkg.el.resdescr}</description>
+ <mimetype>${unpack.pkg.el.resmimetype}</mimetype>
+ <permissions>${unpack.pkg.el.respermissions}</permissions>
+ <version>${unpack.pkg.el.resver}</version>
+ </id-${entry.id}>
+ </echo>
+ </then>
+ <else>
+ <property name="unpack.pkg.el.srcfile" value="${unpack.pkg.el.srcdir}/data"/>
+ <replaceregexp file="${unpack.pkg.el.srcfile}"
+ encoding="UTF-16" match="(encoding\s*=\s*)"[^"]*"" flags="i" replace="\1"UTF-16""/>
+ <xmlproperty file="${unpack.pkg.el.srcfile}" collapseAttributes="true"/>
+ <switch value="${entry.type}">
+ <case value="Workflow">
+ <property name="unpack.pkg.el.elname" value="${workflow.display-name}"/>
+ <property name="unpack.pkg.el.desttypedir" value="${content.folder}/Workflows"/>
+ <property name="unpack.pkg.el.typesuffix" value="workflow"/>
+ </case>
+ <case value="ConfigurationElement">
+ <property name="unpack.pkg.el.elname" value="${config-element.display-name}"/>
+ <property name="unpack.pkg.el.desttypedir" value="${content.folder}/Configurations"/>
+ <property name="unpack.pkg.el.typesuffix" value="vsoconf"/>
+ </case>
+ <case value="ScriptModule">
+ <property name="unpack.pkg.el.elname" value="${dunes-script-module.name}"/>
+ <property name="unpack.pkg.el.desttypedir" value="${content.folder}/Actions"/>
+ <property name="unpack.pkg.el.typesuffix" value="action"/>
+ </case>
+ <default>
+ <fail message="Unknown element type "${entry.type}" found in package "${unpack.pkg.pkgname}"."/>
+ </default>
+ </switch>
+
+ <property name="unpack.pkg.el.relpath"
+ value="${element.category}${unpack.pkg.el.elname}.${unpack.pkg.el.typesuffix}"/>
+ <echo file="${unpack.pkg.listdir}/${entry.type}List.xml" append="true">
+ <id-${entry.id} path="${unpack.pkg.el.relpath}.xml"/>
+ </echo>
+
+ <!-- Checking if same element is exported separately and is newer -->
+ <if>
+ <available file="${unpack.pkg.el.desttypedir}/${unpack.pkg.el.relpath}"/>
+ <then>
+ <echo message="Found alternative source for "${unpack.pkg.el.elname}" ${entry.type}."/>
+ <uptodate property="unpack.pkg.el.isalternewer" srcfile="${pkg.srcfile}"
+ targetfile="${unpack.pkg.el.desttypedir}/${unpack.pkg.el.relpath}"/>
+ <if>
+ <not>
+ <isset property="unpack.pkg.el.isalternewer"/>
+ </not>
+ <then>
+ <echo message="Alternative source for "${unpack.pkg.el.elname}" ${entry.type} is older. Deleting alternative source."/>
+ <delete file="${unpack.pkg.el.desttypedir}/${unpack.pkg.el.relpath}"/>
+ </then>
+ </if>
+ </then>
+ </if>
+ <property name="unpack.pkg.el.destfile"
+ value="${unpack.pkg.el.desttypedir}/${unpack.pkg.el.relpath}.xml"/>
+ </else>
+ </if>
+
+ <!-- Extracting element from package if its content is newer -->
+ <if>
+ <isset property="unpack.pkg.el.isalternewer"/>
+ <then>
+ <echo message="Alternative source for "${unpack.pkg.el.elname}" ${entry.type} is newer. This element extraction is skipped."/>
+ </then>
+ <else>
+ <if>
+ <and>
+ <available file="${unpack.pkg.el.destfile}"/>
+ <uptodate srcfile="${pkg.srcfile}" targetfile="${unpack.pkg.el.destfile}"/>
+ </and>
+ <then>
+ <echo message="${entry.type} "${unpack.pkg.el.elname}" has already been extracted and is up-to-date. Skipping element."/>
+ </then>
+ <else>
+ <if>
+ <equals arg1="${entry.type}" arg2="ResourceElement"/>
+ <then>
+ <copy file="${unpack.pkg.el.srcfile}" tofile="${unpack.pkg.el.destfile}"/>
+ </then>
+ <else>
+ <xslt style="format.xsl" in="${unpack.pkg.el.srcfile}" out="${unpack.pkg.el.destfile}"/>
+ </else>
+ </if>
+ </else>
+ </if>
+ </else>
+ </if>
+ </target>
+
+</project>
--- /dev/null
+<xsl:stylesheet
+ version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:vco="http://vmware.com/vco/workflow"
+ xmlns:trax="http://xml.apache.org/xslt"
+>
+
+ <xsl:output method="xml" version="1.0" indent="yes" trax:indent-amount="4"/>
+ <xsl:strip-space elements="*"/>
+
+ <xsl:template name="ltrim">
+ <xsl:param name="text"/>
+ <xsl:value-of select="substring($text, string-length(substring-before($text, substring(normalize-space($text), 1, 1))) + 1)"/>
+ </xsl:template>
+
+ <xsl:template name="getNumOfTrailingSpaces">
+ <xsl:param name="text"/>
+ <xsl:variable name="normalizedText">
+ <xsl:value-of select="normalize-space($text)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($normalizedText) > 0">
+ <xsl:call-template name="getNumOfTrailingSpaces">
+ <xsl:with-param name="text" select="substring-after(substring($text, string-length($normalizedText)), substring($normalizedText, string-length($normalizedText)))"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="string-length($text)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="rtrim">
+ <xsl:param name="text"/>
+ <xsl:variable name="numOfTrailingSpaces">
+ <xsl:call-template name="getNumOfTrailingSpaces">
+ <xsl:with-param name="text">
+ <xsl:call-template name="ltrim">
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="substring($text, 1, string-length($text) - $numOfTrailingSpaces)"/>
+ </xsl:template>
+
+ <xsl:template name="trim">
+ <xsl:param name="text"/>
+ <xsl:call-template name="rtrim">
+ <xsl:with-param name="text">
+ <xsl:call-template name="ltrim">
+ <xsl:with-param name="text" select="$text"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template match="@*|node()">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:copy>
+ </xsl:template>
+
+ <xsl:template match="text()">
+ <xsl:variable name="trimmed">
+ <xsl:call-template name="trim">
+ <xsl:with-param name="text" select="."/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="parent::vco:script or parent::script or contains(., '
')">
+ <xsl:text>
</xsl:text>
+ </xsl:if>
+ <xsl:value-of select="$trimmed"/>
+ <xsl:if test="parent::vco:script or parent::script or contains(., '
')">
+ <xsl:text>
</xsl:text>
+ <!-- generate indent for closing tag -->
+ <!-- get ancestor nodes except root element (which has no parent) -->
+ <xsl:for-each select="ancestor::*[parent::*]">
+ <xsl:text> </xsl:text>
+ </xsl:for-each>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="vco:workflow | dunes-script-module | package | config-element">
+ <xsl:text>
</xsl:text>
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:copy>
+ </xsl:template>
+
+ <xsl:template match="vco:workflow[not(allowed-operations)]/@api-version">
+ <xsl:copy>
+ <xsl:attribute name="allowed-operations">vfe</xsl:attribute>
+ </xsl:copy>
+ </xsl:template>
+
+ <xsl:template match="dunes-script-module[not(allowed-operations)]/@version">
+ <xsl:copy>
+ <xsl:attribute name="allowed-operations">vfe</xsl:attribute>
+ </xsl:copy>
+ </xsl:template>
+
+ <xsl:template match="vco:input | vco:output | vco:attrib[position() = 1] | vco:workflow-item
+ | vco:position | vco:description[local-name(parent::*) != 'attrib'] | vco:in-binding
+ | vco:out-binding | vco:script | vco:presentation
+ | script | param">
+ <xsl:if test="preceding-sibling::*">
+ <xsl:text>

</xsl:text>
+ <!-- generate indent for opening tag -->
+ <xsl:for-each select="ancestor::*">
+ <xsl:text> </xsl:text>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:copy>
+ </xsl:template>
+
+</xsl:stylesheet>
--- /dev/null
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+ <xsl:output method="text"/>
+ <xsl:strip-space elements="*"/>
+
+ <xsl:template match="/properties">
+ <!-- Package meta info -->
+ <xsl:apply-templates select="entry[@key = 'pkg-id']"/>
+ <xsl:apply-templates select="entry[@key = 'pkg-description']"/>
+
+ <!-- Element meta info -->
+ <xsl:apply-templates select="entry[@key = 'id']"/>
+ <xsl:apply-templates select="entry[@key = 'type']"/>
+ </xsl:template>
+
+ <xsl:template match="entry">
+ <xsl:text>entry.</xsl:text>
+ <xsl:value-of select="@key"/>
+ <xsl:text> = </xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text>
</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="/categories">
+ <xsl:text>element.category = </xsl:text>
+ <xsl:variable name="path">
+ <xsl:for-each select="category">
+ <xsl:value-of select="name"/>
+ <xsl:text>/</xsl:text>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:value-of select="$path"/>
+ <xsl:text>
</xsl:text>
+ </xsl:template>
+
+</xsl:stylesheet>