You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ma...@apache.org on 2009/06/27 17:53:26 UTC
svn commit: r788992 [8/25] - in /incubator/ace/trunk: gateway/ gateway/src/
gateway/src/net/ gateway/src/net/luminis/ gateway/src/net/luminis/liq/
gateway/src/net/luminis/liq/bootstrap/
gateway/src/net/luminis/liq/bootstrap/multigateway/ gateway/src/ne...
Added: incubator/ace/trunk/liq/target-dev-server-upnp.xml
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/liq/target-dev-server-upnp.xml?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/liq/target-dev-server-upnp.xml (added)
+++ incubator/ace/trunk/liq/target-dev-server-upnp.xml Sat Jun 27 15:53:04 2009
@@ -0,0 +1,137 @@
+<project name="dev-server-upnp" default="warning">
+ <property name="deploy-dir" value="deploy/target/${ant.project.name}" />
+ <property name="app-name" value="L-iQ PS server with UPnP support" />
+
+ <target name="warning">
+ <echo message="Please run top level build." />
+ </target>
+
+ <target name="deploy">
+ <mkdir dir="${deploy-dir}" />
+ <mkdir dir="${deploy-dir}/store" />
+ <copy todir="${deploy-dir}">
+ <fileset dir="lib/felix/1.4.1">
+ <include name="**" />
+ </fileset>
+ </copy>
+ <copy todir="${deploy-dir}/bundle">
+ <fileset dir="deploy/bundle">
+ <include name="net.luminis.liq.consolelogger-1.0.0.jar" />
+ <include name="net.luminis.liq.configurator-1.0.0.jar" />
+ <include name="net.luminis.liq.configurator.useradmin.task-1.0.0.jar" />
+ <include name="net.luminis.liq.resourceprocessor.useradmin-1.0.0.jar" />
+ <include name="net.luminis.liq.http.listener-1.0.0.jar" />
+ <include name="net.luminis.liq.deployment.servlet-1.0.0.jar" />
+ <include name="net.luminis.liq.deployment.provider.repositorybased-1.0.0.jar" />
+ <include name="net.luminis.liq.deployment.streamgenerator-1.0.0.jar" />
+ <include name="net.luminis.liq.discovery.upnp-1.0.0.jar" />
+ <include name="net.luminis.liq.location.upnp-1.0.0.jar" />
+ <include name="net.luminis.liq.server.log.store-1.0.0.jar" />
+ <include name="net.luminis.liq.server.log-1.0.0.jar" />
+ <include name="net.luminis.liq.scheduler-1.0.0.jar" />
+ <include name="net.luminis.liq.repository-1.0.0.jar" />
+ <include name="net.luminis.liq.repository.servlet-1.0.0.jar" />
+ <include name="net.luminis.liq.client.repository.stateful-1.0.0.jar" />
+ <include name="net.luminis.liq.client.repository-1.0.0.jar" />
+ <include name="net.luminis.liq.client.repository.helper.base-1.0.0.jar" />
+ <include name="net.luminis.liq.client.repository.helper.bundle-1.0.0.jar" />
+ <include name="net.luminis.liq.activationinfo.factory.server-1.0.0.jar" />
+ <include name="net.luminis.liq.license.factory.server-1.0.0.jar" />
+ <include name="net.luminis.liq.server.activation-1.0.0.jar" />
+ <include name="net.luminis.liq.server.activation.store-1.0.0.jar" />
+ <include name="net.luminis.liq.server.activation.matcher-1.0.0.jar" />
+ <include name="net.luminis.liq.server.activation.servlet-1.0.0.jar" />
+ </fileset>
+ <fileset dir="ext">
+ <include name="org.osgi.compendium.jar" />
+ <include name="osgi.mobile.jar" />
+ <include name="javax.servlet.jar" />
+ <include name="org.apache.felix.dependencymanager.jar" />
+ </fileset>
+ <fileset dir="lib">
+ <include name="net.luminis.liq.xstream-1.3.jar" />
+ <include name="org.apache.felix.configadmin.jar" />
+ <include name="org.apache.felix.eventadmin.jar" />
+ <include name="log_all-2.0.0.jar" />
+ <include name="http.jetty.jar" />
+ <include name="useradmin_all-2.0.0.jar" />
+ <include name="org.apache.felix.prefs-0.1.0-SNAPSHOT.jar" />
+ <include name="org.apache.felix.upnp.basedriver-0.8.0.jar" />
+ </fileset>
+ </copy>
+ <copy todir="${deploy-dir}/conf">
+ <fileset dir="conf/${ant.project.name}">
+ <include name="**/*.cfg" />
+ </fileset>
+ </copy>
+ <copy file="${deploy-dir}/conf/dev-config.properties" overwrite="true" tofile="${deploy-dir}/conf/config.properties" />
+ <delete file="${deploy-dir}/conf/test-config.properties" />
+ <property name="bundles-noshell" value="
+ file:bundle/net.luminis.liq.consolelogger-1.0.0.jar
+ file:bundle/log_all-2.0.0.jar
+ file:bundle/osgi.mobile.jar
+ file:bundle/org.osgi.compendium.jar
+ file:bundle/http.jetty.jar
+ file:bundle/javax.servlet.jar
+ file:bundle/useradmin_all-2.0.0.jar
+ file:bundle/net.luminis.liq.xstream-1.3.jar
+ file:bundle/org.apache.felix.eventadmin.jar
+ file:bundle/org.apache.felix.shell-1.0.1.jar
+ file:bundle/org.apache.felix.shell.tui-1.0.1.jar
+ file:bundle/org.apache.felix.configadmin.jar
+ file:bundle/org.apache.felix.dependencymanager.jar
+ file:bundle/org.apache.felix.prefs-0.1.0-SNAPSHOT.jar
+ file:bundle/org.apache.felix.upnp.basedriver-0.8.0.jar
+ file:bundle/net.luminis.liq.configurator-1.0.0.jar
+ file:bundle/net.luminis.liq.http.listener-1.0.0.jar
+ file:bundle/net.luminis.liq.location.upnp-1.0.0.jar
+ file:bundle/net.luminis.liq.deployment.servlet-1.0.0.jar
+ file:bundle/net.luminis.liq.deployment.provider.repositorybased-1.0.0.jar
+ file:bundle/net.luminis.liq.deployment.streamgenerator-1.0.0.jar
+ file:bundle/net.luminis.liq.discovery.upnp-1.0.0.jar
+ file:bundle/net.luminis.liq.server.log.store-1.0.0.jar
+ file:bundle/net.luminis.liq.server.log-1.0.0.jar
+ file:bundle/net.luminis.liq.scheduler-1.0.0.jar
+ file:bundle/net.luminis.liq.repository-1.0.0.jar
+ file:bundle/net.luminis.liq.repository.servlet-1.0.0.jar
+ file:bundle/net.luminis.liq.client.repository.stateful-1.0.0.jar
+ file:bundle/net.luminis.liq.client.repository-1.0.0.jar
+ file:bundle/net.luminis.liq.client.repository.helper.base-1.0.0.jar
+ file:bundle/net.luminis.liq.client.repository.helper.bundle-1.0.0.jar
+ file:bundle/net.luminis.liq.configurator.useradmin.task-1.0.0.jar
+ file:bundle/net.luminis.liq.resourceprocessor.useradmin-1.0.0.jar
+ file:bundle/net.luminis.liq.license.factory.server-1.0.0.jar
+ file:bundle/net.luminis.liq.activationinfo.factory.server-1.0.0.jar
+ file:bundle/net.luminis.liq.server.activation-1.0.0.jar
+ file:bundle/net.luminis.liq.server.activation.store-1.0.0.jar
+ file:bundle/net.luminis.liq.server.activation.matcher-1.0.0.jar
+ file:bundle/net.luminis.liq.server.activation.servlet-1.0.0.jar" />
+ <property name="bundles-shell" value="${bundles-noshell}
+ file:bundle/org.apache.felix.shell-1.0.0.jar
+ file:bundle/org.apache.felix.shell.tui-1.0.0.jar" />
+ <replace file="${deploy-dir}/conf/config.properties" token="@bundles@" value="${bundles-shell}" />
+ <move file="${deploy-dir}/conf/dev-config.properties" tofile="${deploy-dir}/conf/config-noshell.properties" />
+ <replace file="${deploy-dir}/conf/config-noshell.properties" token="@bundles@" value="${bundles-noshell}" />
+ <replace file="${deploy-dir}/conf/config.properties" token="@properties@" value="org.osgi.service.http.port=8080" />
+ <replace file="${deploy-dir}/conf/config-noshell.properties" token="@properties@" value="org.osgi.service.http.port=8080" />
+
+ <property name="runCommand" value="java -Xms256m -Xmx256m -jar bin/felix.jar"/>
+ <property name="runNoshellCommand" value="java -Xms256m -Xmx256m -Dfelix.config.properties=file:conf/config-noshell.properties -jar bin/felix.jar > output-felix.txt 2>&1"/>
+ <property name="debugCommand" value="java -Xms256m -Xmx256m -jar -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y -Dcom.sun.management.jmxremote.port=6666 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false bin/felix.jar"/>
+ <echo file="${deploy-dir}/run.sh">#!/bin/sh
+${runCommand}
+ </echo>
+ <echo file="${deploy-dir}/run.bat">${runCommand}
+ </echo>
+ <echo file="${deploy-dir}/run-noshell.sh">#!/bin/sh
+${runNoshellCommand}
+ </echo>
+ <echo file="${deploy-dir}/run-noshell.bat">${runNoshellCommand}
+ </echo>
+ <echo file="${deploy-dir}/debug.sh">#!/bin/sh
+${debugCommand}
+ </echo>
+ <echo file="${deploy-dir}/debug.bat">${debugCommand}
+ </echo>
+ </target>
+</project>
Added: incubator/ace/trunk/liq/target-dev-server.xml
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/liq/target-dev-server.xml?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/liq/target-dev-server.xml (added)
+++ incubator/ace/trunk/liq/target-dev-server.xml Sat Jun 27 15:53:04 2009
@@ -0,0 +1,172 @@
+<project name="dev-server" default="warning">
+ <property name="deploy-dir" value="deploy/target/${ant.project.name}" />
+ <property name="app-name" value="L-iQ PS server" />
+
+ <target name="warning">
+ <echo message="Please run top level build." />
+ </target>
+
+ <target name="deploy">
+ <mkdir dir="${deploy-dir}" />
+ <mkdir dir="${deploy-dir}/store" />
+ <copy todir="${deploy-dir}">
+ <fileset dir="lib/felix/1.4.1">
+ <include name="**" />
+ </fileset>
+ </copy>
+ <copy todir="${deploy-dir}/bundle">
+ <fileset dir="deploy/bundle">
+ <include name="net.luminis.liq.consolelogger-1.0.0.jar" />
+ <include name="net.luminis.liq.configurator-1.0.0.jar" />
+ <include name="net.luminis.liq.configurator.useradmin.task-1.0.0.jar" />
+ <include name="net.luminis.liq.resourceprocessor.useradmin-1.0.0.jar" />
+ <include name="net.luminis.liq.http.listener-1.0.0.jar" />
+ <include name="net.luminis.liq.deployment.servlet-1.0.0.jar" />
+ <include name="net.luminis.liq.deployment.provider.repositorybased-1.0.0.jar" />
+ <include name="net.luminis.liq.deployment.streamgenerator-1.0.0.jar" />
+ <include name="net.luminis.liq.discovery.property-1.0.0.jar" />
+ <include name="net.luminis.liq.server.log.store-1.0.0.jar" />
+ <include name="net.luminis.liq.server.log-1.0.0.jar" />
+ <include name="net.luminis.liq.scheduler-1.0.0.jar" />
+ <include name="net.luminis.liq.repository-1.0.0.jar" />
+ <include name="net.luminis.liq.repository.servlet-1.0.0.jar" />
+ <include name="net.luminis.liq.client.repository.stateful-1.0.0.jar" />
+ <include name="net.luminis.liq.client.repository-1.0.0.jar" />
+ <include name="net.luminis.liq.client.repository.helper.base-1.0.0.jar" />
+ <include name="net.luminis.liq.client.repository.helper.bundle-1.0.0.jar" />
+ <include name="net.luminis.liq.activation.store-1.0.0.jar" />
+ <include name="net.luminis.liq.activationinfo.store-1.0.0.jar" />
+ <include name="net.luminis.liq.activation.matcher-1.0.0.jar" />
+ <include name="net.luminis.liq.activation.servlet-1.0.0.jar" />
+ <include name="net.luminis.liq.activation.service-1.0.0.jar" />
+ <include name="net.luminis.liq.client.repository.helper.license-1.0.0.jar" />
+ <!-- for testing -->
+ <!--
+ <include name="net.luminis.liq.http.echo.servlet-1.0.0.jar" />
+ -->
+ </fileset>
+ <fileset dir="ext">
+ <include name="org.osgi.compendium.jar" />
+ <include name="osgi.mobile.jar" />
+ <include name="javax.servlet.jar" />
+ <include name="org.apache.felix.dependencymanager.jar" />
+ <include name="org.apache.felix.dependencymanager.shell.jar" />
+ </fileset>
+ <fileset dir="lib">
+ <include name="net.luminis.liq.xstream-1.3.jar" />
+ <include name="org.apache.felix.configadmin.jar" />
+ <include name="org.apache.felix.eventadmin.jar" />
+ <include name="log_all-2.0.0.jar" />
+ <include name="http.jetty.jar" />
+ <include name="useradmin_all-2.0.0.jar" />
+ <include name="org.apache.felix.prefs.jar" />
+ </fileset>
+ </copy>
+ <copy todir="${deploy-dir}/conf">
+ <fileset dir="conf/${ant.project.name}">
+ <include name="**/*.cfg" />
+ </fileset>
+ </copy>
+ <copy file="${deploy-dir}/conf/dev-config.properties" overwrite="true" tofile="${deploy-dir}/conf/config.properties" />
+ <delete file="${deploy-dir}/conf/test-config.properties" />
+ <property name="bundles-noshell" value="
+ file:bundle/net.luminis.liq.consolelogger-1.0.0.jar
+ file:bundle/log_all-2.0.0.jar
+ file:bundle/osgi.mobile.jar
+ file:bundle/org.osgi.compendium.jar
+ file:bundle/http.jetty.jar
+ file:bundle/javax.servlet.jar
+ file:bundle/useradmin_all-2.0.0.jar
+ file:bundle/net.luminis.liq.xstream-1.3.jar
+ file:bundle/org.apache.felix.eventadmin.jar
+ file:bundle/org.apache.felix.configadmin.jar
+ file:bundle/org.apache.felix.dependencymanager.jar
+ file:bundle/org.apache.felix.prefs.jar
+ file:bundle/net.luminis.liq.configurator-1.0.0.jar
+ file:bundle/net.luminis.liq.http.listener-1.0.0.jar
+ file:bundle/net.luminis.liq.deployment.servlet-1.0.0.jar
+ file:bundle/net.luminis.liq.deployment.provider.repositorybased-1.0.0.jar
+ file:bundle/net.luminis.liq.deployment.streamgenerator-1.0.0.jar
+ file:bundle/net.luminis.liq.discovery.property-1.0.0.jar
+ file:bundle/net.luminis.liq.server.log.store-1.0.0.jar
+ file:bundle/net.luminis.liq.server.log-1.0.0.jar
+ file:bundle/net.luminis.liq.scheduler-1.0.0.jar
+ file:bundle/net.luminis.liq.repository-1.0.0.jar
+ file:bundle/net.luminis.liq.repository.servlet-1.0.0.jar
+ file:bundle/net.luminis.liq.client.repository.stateful-1.0.0.jar
+ file:bundle/net.luminis.liq.client.repository-1.0.0.jar
+ file:bundle/net.luminis.liq.client.repository.helper.base-1.0.0.jar
+ file:bundle/net.luminis.liq.client.repository.helper.bundle-1.0.0.jar
+ file:bundle/net.luminis.liq.configurator.useradmin.task-1.0.0.jar
+ file:bundle/net.luminis.liq.resourceprocessor.useradmin-1.0.0.jar
+ file:bundle/net.luminis.liq.activation.store-1.0.0.jar
+ file:bundle/net.luminis.liq.activationinfo.store-1.0.0.jar
+ file:bundle/net.luminis.liq.activation.matcher-1.0.0.jar
+ file:bundle/net.luminis.liq.activation.servlet-1.0.0.jar
+ file:bundle/net.luminis.liq.activation.service-1.0.0.jar
+ file:bundle/net.luminis.liq.client.repository.helper.license-1.0.0.jar
+ " />
+ <property name="bundles-shell" value="${bundles-noshell}
+ file:bundle/org.apache.felix.shell-1.0.2.jar
+ file:bundle/org.apache.felix.shell.tui-1.0.2.jar
+ file:bundle/org.apache.felix.dependencymanager.shell.jar
+ " />
+ <replace file="${deploy-dir}/conf/config.properties" token="@bundles@" value="${bundles-shell}" />
+ <move file="${deploy-dir}/conf/dev-config.properties" tofile="${deploy-dir}/conf/config-noshell.properties" />
+ <replace file="${deploy-dir}/conf/config-noshell.properties" token="@bundles@" value="${bundles-noshell}" />
+ <replace file="${deploy-dir}/conf/config.properties" token="@properties@">
+ <replacevalue><![CDATA[
+org.apache.felix.http.nio=true
+org.apache.felix.http.enable=true
+org.osgi.service.http.port=8080
+org.apache.felix.https.enable=false
+org.osgi.service.http.port.secure=8443
+org.apache.felix.http.debug=false
+org.apache.felix.https.keystore=/tmp/node1Keystore
+org.apache.felix.https.keystore.password=secret
+org.apache.felix.https.keystore.key.password=secret
+org.apache.felix.https.truststore=/tmp/truststore
+org.apache.felix.https.truststore.password=secret
+org.apache.felix.https.clientcertificate=needs
+ ]]></replacevalue>
+ </replace>
+ <replace file="${deploy-dir}/conf/config-noshell.properties" token="@properties@">
+ <replacevalue><![CDATA[
+org.apache.felix.http.nio=true
+org.apache.felix.http.enable=true
+org.osgi.service.http.port=8080
+org.apache.felix.https.enable=false
+org.osgi.service.http.port.secure=8443
+org.apache.felix.http.debug=false
+org.apache.felix.https.keystore=/tmp/node1Keystore
+org.apache.felix.https.keystore.password=secret
+org.apache.felix.https.keystore.key.password=secret
+org.apache.felix.https.truststore=/tmp/truststore
+org.apache.felix.https.truststore.password=secret
+org.apache.felix.https.clientcertificate=needs
+ ]]></replacevalue>
+ </replace>
+
+ <property name="runCommand" value="java -Xms256m -Xmx256m -jar bin/felix.jar"/>
+ <property name="runNoshellCommand" value="java -Xms256m -Xmx256m -Dfelix.config.properties=file:conf/config-noshell.properties -jar bin/felix.jar > output-felix.txt 2>&1"/>
+ <property name="debugCommand" value="java -Xms256m -Xmx256m -jar -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y -Dcom.sun.management.jmxremote.port=6666 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false bin/felix.jar"/>
+ <echo file="${deploy-dir}/run.sh">#!/bin/sh
+${runCommand}
+ </echo>
+ <echo file="${deploy-dir}/run.bat">${runCommand}
+ </echo>
+ <echo file="${deploy-dir}/run-noshell.sh">#!/bin/sh
+${runNoshellCommand}
+ </echo>
+ <echo file="${deploy-dir}/run-noshell.bat">${runNoshellCommand}
+ </echo>
+ <echo file="${deploy-dir}/debug.sh">#!/bin/sh
+${debugCommand}
+ </echo>
+ <echo file="${deploy-dir}/debug.bat">${debugCommand}
+ </echo>
+ <echo file="${deploy-dir}/run_secure.sh">#!/bin/sh
+${runSecureCommand}
+ </echo>
+ </target>
+</project>
Added: incubator/ace/trunk/liq/target-dev-tools.xml
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/liq/target-dev-tools.xml?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/liq/target-dev-tools.xml (added)
+++ incubator/ace/trunk/liq/target-dev-tools.xml Sat Jun 27 15:53:04 2009
@@ -0,0 +1,19 @@
+<project name="dev-tools" default="warning">
+ <property name="deploy-dir" value="deploy/target/${ant.project.name}" />
+
+ <target name="warning">
+ <echo message="Please run top level build." />
+ </target>
+
+ <target name="deploy">
+ <mkdir dir="${deploy-dir}" />
+ <copy todir="${deploy-dir}">
+ <fileset dir="deploy/tools">
+ <include name="**" />
+ </fileset>
+ <fileset dir="../test/ext/commons">
+ <include name="*.jar" />
+ </fileset>
+ </copy>
+ </target>
+</project>
\ No newline at end of file
Added: incubator/ace/trunk/liq/target-test.xml
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/liq/target-test.xml?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/liq/target-test.xml (added)
+++ incubator/ace/trunk/liq/target-test.xml Sat Jun 27 15:53:04 2009
@@ -0,0 +1,53 @@
+<project name="test" default="warning">
+ <property name="deploy-dir" value="deploy/target/${ant.project.name}" />
+
+ <target name="warning">
+ <echo message="Please run top level build." />
+ </target>
+
+ <target name="deploy">
+ <mkdir dir="${deploy-dir}" />
+ <copy todir="${deploy-dir}">
+ <fileset dir="lib/felix/1.4.1">
+ <include name="**" />
+ </fileset>
+ </copy>
+ <copy todir="${deploy-dir}/bundle">
+ <fileset dir="deploy/test">
+ <include name="*.jar" />
+ </fileset>
+ <fileset dir="deploy/bundle">
+ <include name="*.jar" />
+ </fileset>
+ <fileset dir="ext">
+ <include name="*.jar" />
+ </fileset>
+ <fileset dir="lib">
+ <include name="http.jetty.jar" />
+ <include name="log_all-2.0.0.jar" />
+ <include name="org.apache.felix.eventadmin.jar" />
+ <include name="org.apache.felix.configadmin.jar" />
+ <include name="org.apache.felix.prefs.jar" />
+ <include name="useradmin_all-2.0.0.jar" />
+ <include name="org.apache.felix.deploymentadmin-0.9.0-SNAPSHOT.jar" />
+ <!-- Temporarily added until we can use xstream in some other way -->
+ <include name="net.luminis.liq.xstream-1.3.jar" />
+ </fileset>
+ </copy>
+ <copy todir="${deploy-dir}/conf">
+ <fileset dir="conf/${ant.project.name}">
+ <include name="**/*.cfg" />
+ </fileset>
+ </copy>
+ <move file="${deploy-dir}/conf/test-config.properties" tofile="${deploy-dir}/conf/config.properties" />
+
+ <!-- instrument the classes for code coverage -->
+ <mkdir dir="${deploy-dir}/instrumented" />
+ <echo file="${deploy-dir}/run.sh">#!/bin/sh
+java -jar bin/felix.jar
+ </echo>
+ <echo file="${deploy-dir}/debug.sh">#!/bin/sh
+java -jar -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y -Dcom.sun.management.jmxremote.port=6666 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false bin/felix.jar
+ </echo>
+ </target>
+</project>
\ No newline at end of file
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/automation/Activator.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/automation/Activator.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/automation/Activator.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/automation/Activator.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,41 @@
+package net.luminis.liq.client.automation;
+
+
+import net.luminis.liq.client.repository.RepositoryAdmin;
+import net.luminis.liq.client.repository.repository.DeploymentVersionRepository;
+import net.luminis.liq.client.repository.repository.GatewayRepository;
+import net.luminis.liq.client.repository.stateful.StatefulGatewayRepository;
+
+import org.apache.felix.dependencymanager.DependencyActivatorBase;
+import org.apache.felix.dependencymanager.DependencyManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.log.LogService;
+import org.osgi.service.useradmin.UserAdmin;
+
+
+/**
+ * Bundle activator for the gateway operator automation.
+ */
+public class Activator extends DependencyActivatorBase {
+
+ /**
+ * Initialize and set dependencies
+ */
+ @Override
+ public void init(BundleContext context, DependencyManager manager) throws Exception {
+ manager.add(createService()
+ .setImplementation(AutoGatewayOperator.class)
+ .add(createConfigurationDependency().setPid(AutoGatewayOperator.PID))
+ .add(createServiceDependency().setRequired(true).setService(UserAdmin.class))
+ .add(createServiceDependency().setRequired(true).setService(GatewayRepository.class))
+ .add(createServiceDependency().setRequired(true).setService(StatefulGatewayRepository.class))
+ .add(createServiceDependency().setRequired(true).setService(DeploymentVersionRepository.class))
+ .add(createServiceDependency().setRequired(true).setService(RepositoryAdmin.class))
+ .add(createServiceDependency().setRequired(false).setService(LogService.class))
+ );
+ }
+
+ @Override
+ public void destroy(BundleContext context, DependencyManager manager) throws Exception {
+ }
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/automation/AutoGatewayOperator.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/automation/AutoGatewayOperator.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/automation/AutoGatewayOperator.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/automation/AutoGatewayOperator.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,242 @@
+package net.luminis.liq.client.automation;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Properties;
+
+import net.luminis.liq.client.repository.RepositoryAdmin;
+import net.luminis.liq.client.repository.RepositoryAdminLoginContext;
+import net.luminis.liq.client.repository.object.GatewayObject;
+import net.luminis.liq.client.repository.stateful.StatefulGatewayObject;
+import net.luminis.liq.client.repository.stateful.StatefulGatewayRepository;
+import net.luminis.liq.scheduler.constants.SchedulerConstants;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.log.LogService;
+import org.osgi.service.useradmin.User;
+import org.osgi.service.useradmin.UserAdmin;
+
+/**
+ * Automatic gateway operator, when configured will automatically register, approve, auto-approve
+ * and commit gateways to the repository. An LDAP filter can be used to filter for the correct gateways
+ *
+ */
+public class AutoGatewayOperator implements ManagedService {
+
+ public static final String PID = "net.luminis.liq.client.automation";
+ public static final String SCHEDULER_NAME = "net.luminis.liq.client.processauditlog";
+
+ private volatile StatefulGatewayRepository m_statefulGatewayRepos;
+ private volatile RepositoryAdmin m_reposAdmin;
+ private volatile UserAdmin m_userAdmin;
+ private volatile BundleContext m_bundleContext;
+ private volatile LogService m_log;
+ @SuppressWarnings("unchecked")
+ private volatile Dictionary m_settings;
+
+ private static String username = "serverUser";
+
+ // used for processing the auditlog (tell the repository about that)
+ private final AuditLogProcessTask m_task = new AuditLogProcessTask();
+ private Object m_serviceReg = null;
+
+ public void start() {
+ // get user
+ User user = m_userAdmin.getUser("username",username);
+
+ // login at Repository admin
+ try {
+ URL url = new URL(getConfigValue(ConfigItem.HOSTNAME) + getConfigValue(ConfigItem.ENDPOINT));
+ String customerName = getConfigValue(ConfigItem.CUSTOMER_NAME);
+
+ RepositoryAdminLoginContext loginContext = m_reposAdmin.createLoginContext(user);
+ loginContext.addShopRepository(url, customerName, getConfigValue(ConfigItem.STORE_REPOSITORY), false)
+ .addGatewayRepository(url, customerName, getConfigValue(ConfigItem.GATEWAY_REPOSITORY), true)
+ .addDeploymentRepository(url, customerName, getConfigValue(ConfigItem.DEPLOYMENT_REPOSITORY), true);
+ m_reposAdmin.login(loginContext);
+
+ // start refresh task
+ Properties props = new Properties();
+ props.put(SchedulerConstants.SCHEDULER_NAME_KEY, SCHEDULER_NAME);
+ m_serviceReg = m_bundleContext.registerService(Runnable.class.getName(), m_task, props);
+ }
+ catch (IOException ioe) {
+ m_log.log(LogService.LOG_ERROR, "Unable to login at repository admin.", ioe);
+ }
+ }
+
+ public void stop() {
+ // service present, pull it
+ if (m_serviceReg != null) {
+ ((ServiceRegistration) m_serviceReg).unregister();
+ }
+
+ m_serviceReg = null;
+
+ //logout
+ try {
+ m_reposAdmin.logout(true);
+ }
+ catch (IOException ioe) {
+ // not a lot we can
+ System.err.println(ioe.getMessage());
+ }
+ }
+
+ /**
+ * Runnable that will synchronize audit log data with the server and tell the repository about the changes if applicable.
+ */
+ private final class AuditLogProcessTask implements Runnable {
+
+ private final Object m_lock = new Object();
+
+ public void process() {
+ // perform synchronous model actions
+ synchronized(m_lock) {
+ m_statefulGatewayRepos.refresh();
+ boolean changed = false;
+ try {
+ checkoutModel();
+ changed |=registerGateways();
+ changed |=approveGateways();
+ changed |=setAutoApprove();
+ }
+ catch (IOException ioe) {
+ m_log.log(LogService.LOG_WARNING, "Checkout of model failed.", ioe);
+ }
+ catch (InvalidSyntaxException ise) {
+ m_log.log(LogService.LOG_WARNING, "Illegal register gateway filter.", ise);
+ }
+
+ // Commit any changes
+ try {
+ if (changed) {
+ m_reposAdmin.commit();
+ }
+ }
+ catch (IOException ioe) {
+ m_log.log(LogService.LOG_WARNING, "Commit of model failed", ioe);
+ }
+ }
+ }
+
+ public void run() {
+ process();
+ }
+ }
+
+ private void checkoutModel() throws IOException {
+ // Do a checkout
+ if (!m_reposAdmin.isCurrent()) {
+ m_reposAdmin.checkout();
+ }
+ }
+
+ private boolean registerGateways() throws InvalidSyntaxException {
+ boolean changed = false;
+ String filter = "(&" + getConfigValue(ConfigItem.REGISTER_GW_FILTER) +
+ "(" + StatefulGatewayObject.KEY_REGISTRATION_STATE + "=" + StatefulGatewayObject.RegistrationState.Unregistered + "))";
+ List<StatefulGatewayObject> sgos = m_statefulGatewayRepos.get(m_bundleContext.createFilter(filter));
+ for (StatefulGatewayObject sgo : sgos) {
+ sgo.register();
+ changed = true;
+ }
+ return changed;
+ }
+
+ private boolean setAutoApprove() throws InvalidSyntaxException {
+ boolean changed = false;
+ String filter = "(&" + getConfigValue(ConfigItem.AUTO_APPROVE_GW_FILTER) +
+ "(" + StatefulGatewayObject.KEY_REGISTRATION_STATE + "=" + StatefulGatewayObject.RegistrationState.Registered + ")" +
+ "(!(" + GatewayObject.KEY_AUTO_APPROVE + "=true)))";
+
+ List<StatefulGatewayObject> sgos = m_statefulGatewayRepos.get(m_bundleContext.createFilter(filter));
+ for (StatefulGatewayObject sgo : sgos) {
+ sgo.setAutoApprove(true);
+ changed = true;
+ }
+ return changed;
+ }
+
+ private boolean approveGateways() throws InvalidSyntaxException {
+ boolean changed = false;
+ String filter = "(&" + getConfigValue(ConfigItem.APPROVE_GW_FILTER) +
+ "(" + StatefulGatewayObject.KEY_STORE_STATE + "=" + StatefulGatewayObject.StoreState.Unapproved + "))";
+
+ List<StatefulGatewayObject> sgos = m_statefulGatewayRepos.get(m_bundleContext.createFilter(filter));
+ for (StatefulGatewayObject sgo : sgos) {
+ sgo.approve();
+ changed = true;
+ }
+ return changed;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void updated(Dictionary settings) throws ConfigurationException {
+ if (settings != null) {
+ for (ConfigItem item : ConfigItem.values()) {
+ String value = (String) settings.get(item.toString());
+ if ((value == null) || value.equals("")) {
+ throw new ConfigurationException(item.toString(), item.getErrorText());
+ }
+ }
+ // store configuration
+ m_settings = settings;
+ }
+ }
+
+ /**
+ * @param item The configuration item (enum)
+ * @return The value stored in the configuration dictionary.
+ */
+ private String getConfigValue(ConfigItem item) {
+ return (String) m_settings.get(item.toString());
+ }
+
+ /**
+ * Helper class used for gateway automation client configuration.
+ * ENUM (itemname, errormessage, filter true/false)
+ *
+ */
+ private enum ConfigItem {
+ REGISTER_GW_FILTER ("registerGatewayFilter","Register gateway filter missing", true),
+ APPROVE_GW_FILTER ("approveGatewayFilter","Approve gateway filter missing", true),
+ AUTO_APPROVE_GW_FILTER ("autoApproveGatewayFilter", "Auto approve config value missing", true),
+ COMMIT_REPO ("commitRepositories","Commit value missing.", false),
+ GATEWAY_REPOSITORY ("gatewayRepository","GatewayRepository id missing.", false),
+ DEPLOYMENT_REPOSITORY ("deploymentRepository","DeploymentRepository id missing.", false),
+ STORE_REPOSITORY ("storeRepository","Store Repository id missing.", false),
+ CUSTOMER_NAME ("customerName", "Customer name missing", false),
+ HOSTNAME ("hostName", "Hostname missing.", false),
+ ENDPOINT ("endpoint", "Endpoint missing in config.", false);
+
+ private final String m_name;
+ private final String m_errorText;
+ private final boolean m_isFilter;
+
+ private ConfigItem(String name, String errorText, boolean isFilter) {
+ m_name = name;
+ m_errorText = errorText;
+ m_isFilter = isFilter;
+ }
+
+ @Override
+ public String toString() {
+ return m_name;
+ }
+
+ public String getErrorText() {
+ return m_errorText;
+ }
+
+ public boolean isFilter() {
+ return m_isFilter;
+ }
+ }
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/Associatable.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/Associatable.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/Associatable.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/Associatable.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,41 @@
+package net.luminis.liq.client.repository;
+
+import java.util.List;
+
+/**
+ * The Associatable interface is to be implemented by any object that wants to be
+ * used in an Association.
+ */
+public interface Associatable {
+ /**
+ * Adds the association to this object, which has the given class. The 'other side' of
+ * the association will now show up when filtering for <code>clazz</code>, which is the
+ * class of the other end of the association.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends Associatable> void add(Association association, Class<T> clazz);
+ /**
+ * Removes the association from this object, with the given class. The 'other side' of
+ * the association will no longer show up when filtering for <code>clazz</code>.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends Associatable> void remove(Association association, Class<T> clazz);
+ /**
+ * Gets all Associatable objects of the <code>clazz</code> with which this object
+ * is associated. If <code>clazz</code> is not in use, this function will return
+ * an empty list.
+ */
+ public <T extends Associatable> List<T> getAssociations(Class<T> clazz);
+ /**
+ * Checks whether this object is related with <code>obj</code>, which is to be of class
+ * <code>clazz</code>. Will also return <code>false</code> when the class does not match.
+ */
+ public <T extends Associatable> boolean isAssociated(Object obj, Class<T> clazz);
+ /**
+ * Returns the associations that exist between this object and the other, of the
+ * given <code>clazz</code>, in a typed list of associations <code>associationType</code>.
+ * Will return an empty list if no associations exist.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends Associatable, A extends Association> List<A> getAssociationsWith(Associatable other, Class<T> clazz, Class<A> associationType);
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/Association.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/Association.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/Association.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/Association.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,61 @@
+package net.luminis.liq.client.repository;
+
+import java.util.List;
+
+/**
+ * Represents a basic association between two Associatable objects, whose types
+ * are given by the generic parameters.
+ */
+public interface Association<L extends Associatable, R extends Associatable> extends RepositoryObject {
+ /**
+ * A filter string indicating the left endpoint.
+ */
+ public final static String LEFT_ENDPOINT = "leftEndpoint";
+ /**
+ * A filter string indicating the right endpoint.
+ */
+ public final static String RIGHT_ENDPOINT = "rightEndpoint";
+ /**
+ * A string indicating the cardinality for the left endpoint.
+ */
+ public final static String LEFT_CARDINALITY = "leftCardinality";
+ /**
+ * A string indicating the cardinality for the right endpoint.
+ */
+ public final static String RIGHT_CARDINALITY = "rightCardinality";
+
+ /**
+ * Used for <code>Event</code> properties: A <code>List<Associatable></code> indicating the
+ * objects making up this endpoint before the event happened.
+ */
+ public final static String EVENT_OLD = "old";
+ /**
+ * Used for <code>Event</code> properties: A <code>List<Associatable></code> indicating the
+ * objects making up this endpoint before the event happened.
+ */
+ public final static String EVENT_NEW = "new";
+
+ /**
+ * Gets the Associatable object on the 'other side' of <code>from</code>. If
+ * <code>from</code> does not point to either end of this association, this
+ * function will return <code>null</code>.
+ */
+ public List<Associatable> getTo(Associatable from);
+ /**
+ * Returns the 'left' side of this association.
+ */
+ public List<L> getLeft();
+ /**
+ * Returns the 'left' side of this association.
+ */
+ public List<R> getRight();
+ /**
+ * Removes this association from both endpoints.
+ */
+ public void remove();
+ /**
+ * Indicates whether both sides of this association are available. In an m-to-n assocation,
+ * this function will indicate whether at least one object is available on either side.
+ */
+ public boolean isSatisfied();
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/AssociationRepository.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/AssociationRepository.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/AssociationRepository.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/AssociationRepository.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,37 @@
+package net.luminis.liq.client.repository;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Represents a basic repository of associations. The associations are to be of type
+ * <code>T</code>, associating types <code>L</code> and <code>R</code>.
+ */
+public interface AssociationRepository<L extends Associatable, R extends Associatable, T extends Association<L, R>> extends ObjectRepository<T>{
+ /**
+ * Creates a static association between two filters for objects, stores it,
+ * and returns the association object. This association will link all objects
+ * that apply to the filters in an m-to-n fashion.
+ */
+ public T create(String left, String right);
+ /**
+ * Creates a static association between two objects, stores it,
+ * and returns the association object.
+ */
+ public T create(L left, R right);
+ /**
+ * Creates an association between the given objects, with the <code>Props</code> containing
+ * additional directives for the endpoints, stores it, and returns the association.
+ */
+ public T create(L left, Map<String, String> leftProps, R right, Map<String, String> rightProps);
+ /**
+ * Creates a static association between two lists of objects, stores it,
+ * and returns the association object.
+ */
+ public T create(List<L> left, List<R> right);
+ /**
+ * Removes the given association, and deletes the association from the left- and right
+ * side of the association.
+ */
+ public void remove(T entity);
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/ObjectRepository.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/ObjectRepository.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/ObjectRepository.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/ObjectRepository.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,34 @@
+package net.luminis.liq.client.repository;
+
+import java.util.List;
+import java.util.Map;
+
+import org.osgi.framework.Filter;
+
+/**
+ * A basic object repository, storing implementers of RepositoryObject.
+ */
+public interface ObjectRepository<T extends RepositoryObject> {
+ /**
+ * Removes the given entity from this repository. Will silently fail
+ * when the entity does not exist in this repository.
+ */
+ public void remove(T entity);
+ /**
+ * Gets a list of all entities in this repository.
+ */
+ public List<T> get();
+ /**
+ * Returns a list of all entities in this repository that satisfy
+ * the conditions set in <code>filter</code>. If none match, an
+ * empty list will be returned.
+ */
+ public List<T> get(Filter filter);
+
+ /**
+ * Creates a new inhabitant based on the given attributes. The object
+ * will be stored in this repository's store, and will be returned.
+ * @throws IllegalArgumentException Will be thrown when the attributes cannot be accepted.
+ */
+ public T create(Map<String, String> attributes, Map<String, String> tags) throws IllegalArgumentException;
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/RepositoryAdmin.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/RepositoryAdmin.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/RepositoryAdmin.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/RepositoryAdmin.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,143 @@
+package net.luminis.liq.client.repository;
+
+import java.io.IOException;
+import java.net.URL;
+
+import net.luminis.liq.client.repository.RepositoryObject.WorkingState;
+
+import org.osgi.service.useradmin.User;
+
+public interface RepositoryAdmin {
+
+ public static final String PUBLIC_TOPIC_ROOT = RepositoryAdmin.class.getPackage().getName().replace('.', '/') + "/public/";
+ public static final String PRIVATE_TOPIC_ROOT = RepositoryAdmin.class.getPackage().getName().replace('.', '/') + "/private/";
+
+ public static final String TOPIC_ENTITY_ROOT = RepositoryAdmin.class.getSimpleName() + "/";
+
+ public static final String TOPIC_REFRESH_SUFFIX = "REFRESH";
+ public static final String TOPIC_LOGIN_SUFFIX = "LOGIN";
+ public static final String TOPIC_LOGOUT_SUFFIX = "LOGOUT";
+ public static final String TOPIC_STATUSCHANGED_SUFFIX = "STATUSCHANGED";
+ public static final String TOPIC_FLUSHED_SUFFIX = "FLUSHED";
+ public static final String TOPIC_ALL_SUFFIX = "*";
+
+ /**
+ * Indicates a serious change to the structure of the repository, which is too complicated to use
+ * the Object's own Changed topic.
+ */
+ public static final String TOPIC_REFRESH = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_REFRESH_SUFFIX;
+ /**
+ * Indicates a successful login; the model will now be filled, as signaled by the earlier TOPIC_REFRESH.
+ */
+ public static final String TOPIC_LOGIN = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_LOGIN_SUFFIX;
+ /**
+ * Indicates a successful logout; the model will now be empty, as signaled by the earlier TOPIC_REFRESH.
+ */
+ public static final String TOPIC_LOGOUT = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_LOGOUT_SUFFIX;
+ /**
+ * Signals that isCurrent or isModified have (potentially) changed.
+ */
+ public static final String TOPIC_STATUSCHANGED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_STATUSCHANGED_SUFFIX;
+ /**
+ * Signals that a flush() has been done.
+ */
+ public static final String TOPIC_FLUSHED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_FLUSHED_SUFFIX;
+
+ public static final String TOPIC_ALL = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_ALL_SUFFIX;
+
+ /**
+ * Checks out the most recent version of the repositories from <code>login</code>.
+ * @throws IOException Thrown when we are not logged in, or when there is a problem
+ * communicating with either the local repository or the remote one.
+ */
+ public void checkout() throws IOException;
+
+ /**
+ * Commits the most what we have in memory to the repositories from <code>login</code>.
+ * @throws IOException Thrown when we are not logged in, or when there is a problem
+ * communicating with either the local repository or the remote one.
+ */
+ public void commit() throws IOException;
+
+ /**
+ * Reverts what we have in memory to the most recent one that was checked our or
+ * committed.
+ * @throws IOException Thrown when we are not logged in, or when there is a problem
+ * communicating with either the local repository or the remote one.
+ */
+ public void revert() throws IOException;
+
+ /**
+ * Indicates that the version on which the changes are made is the most recent on the server.
+ * This indication only applies to repositories for which write access has been received.
+ * @throws IOException Thrown when there is a problem communicating with the backup repository,
+ * which keeps track of the local copies of the repository.
+ */
+ public boolean isCurrent() throws IOException;
+
+ /**
+ * Indicates whether the data we have (in memory and persisted) has changed in respect to
+ * what is on the server.
+ * @throws IOException Thrown when there is a problem communicating with the backup repository,
+ * which keeps track of the local copies of the repository.
+ */
+ public boolean isModified() throws IOException;
+
+ /**
+ * Writes what we have in memory to a backup repository, so it can be persisted between runs
+ * of the client, without committing it to the remote repository.
+ * @throws IOException Thrown when there is a problem communicating with the backup repository,
+ * which keeps track of the local copies of the repository.
+ */
+ public void flush() throws IOException;
+
+ /**
+ * Writes what we have in memory to a backup repository, and prepares the repository for use by
+ * a new user.
+ * @param force Indicates that, even when an exception is thrown, we still want to log the
+ * user out.
+ * @throws IOException Thrown when there is a problem communicating with the backup repository,
+ * which keeps track of the local copies of the repository. If this exception is thrown,
+ * the user is still logged in, unless <code>force = true</code>.
+ * @throws IllegalStateException Thrown if no user is logged in.
+ */
+ public void logout(boolean force) throws IOException, IllegalStateException;
+
+ /**
+ * Creates a new login context.
+ * @param user The user to use for this context.
+ * @return A new RepositoryAdminLoginContext,
+ */
+ public RepositoryAdminLoginContext createLoginContext(User user);
+
+ /**
+ * Logs in using the given RepositoryAdminLoginContext; use createLoginContext for an initial
+ * RepositoryAdminLoginContext.
+ * @param context The context to use for this login.
+ * @throws IOException Thrown when there is a problem communicating with the backup repository,
+ * which keeps track of the local copies of the repository.
+ * @throws IllegalArgumentException If <code>context</code> was not one that was
+ * created by <code>createLoginContext</code<.
+ * @throws IllegalStateException If there already is a user logged in.
+ */
+ public void login(RepositoryAdminLoginContext context) throws IOException;
+
+ /**
+ * Return the working state of the given object. If the object is not part of any
+ * repository managed by this admin, <code>New</code> will be returned.
+ * @param object A repository object.
+ * @return The current working state of this object.
+ */
+ public WorkingState getWorkingState(RepositoryObject object);
+
+ /**
+ * Gets the number of objects of a given class with a given state. Note that
+ * this class applies to all objects of that class, and all its descendents.
+ * @param clazz The class of objects to be counted.
+ * @param state A working state.
+ * @return The number of objects which are (or descend from) the given class,
+ * and have the given working state.
+ */
+ public int getNumberWithWorkingState(Class<? extends RepositoryObject> clazz, WorkingState state);
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/RepositoryAdminLoginContext.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/RepositoryAdminLoginContext.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/RepositoryAdminLoginContext.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/RepositoryAdminLoginContext.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,63 @@
+package net.luminis.liq.client.repository;
+
+import java.net.URL;
+
+/**
+ * RepositoryAdminLoginContext represents a context for logins to the repository admin. It is used to specify
+ * which repositories are to be used in a given session with the RepositoryAdmin.
+ */
+public interface RepositoryAdminLoginContext {
+
+ /**
+ * Adds a set of repositories and their location to this login context.
+ * @param repositoryLocation The location of the repository where this set's data resides.
+ * @param repositoryCustomer The customer name for the location of the repository where this set's data resides.
+ * @param repositoryName The repository name for the location of the repository where this set's data resides.
+ * @param writeAccess Whether or not we need write access to this location. If <code>false</code>, readonly access
+ * will be used.
+ * @param objectRepositories The interfaces classes of the repositories to be used for this set.
+ * @return this object, to allow chaining.
+ */
+ @SuppressWarnings("unchecked")
+ public RepositoryAdminLoginContext addRepositories(URL repositoryLocation, String repositoryCustomer, String repositoryName, boolean writeAccess, Class<? extends ObjectRepository>... objectRepositories);
+
+ /**
+ * Adds a shop repository to this login context.
+ * @param repositoryLocation The location of the repository where this set's data resides.
+ * @param repositoryCustomer The customer name for the location of the repository where this set's data resides.
+ * @param repositoryName The repository name for the location of the repository where this set's data resides.
+ * @param writeAccess Whether or not we need write access to this location. If <code>false</code>, readonly access
+ * will be used.
+ * @return this object, to allow chaining.
+ */
+ public RepositoryAdminLoginContext addShopRepository(URL repositoryLocation, String repositoryCustomer, String repositoryName, boolean writeAccess);
+
+ /**
+ * When uploads are needed, this is the base OBR that will be used.
+ * @param base The URL of the OBR to be used.
+ * @return this object, to allow chaining.
+ */
+ public RepositoryAdminLoginContext setObrBase(URL base);
+
+ /**
+ * Adds a gateway repository to this login context.
+ * @param repositoryLocation The location of the repository where this set's data resides.
+ * @param repositoryCustomer The customer name for the location of the repository where this set's data resides.
+ * @param repositoryName The repository name for the location of the repository where this set's data resides.
+ * @param writeAccess Whether or not we need write access to this location. If <code>false</code>, readonly access
+ * will be used.
+ * @return this object, to allow chaining.
+ */
+ public RepositoryAdminLoginContext addGatewayRepository(URL repositoryLocation, String repositoryCustomer, String repositoryName, boolean writeAccess);
+
+ /**
+ * Adds a deployment repository to this login context.
+ * @param repositoryLocation The location of the repository where this set's data resides.
+ * @param repositoryCustomer The customer name for the location of the repository where this set's data resides.
+ * @param repositoryName The repository name for the location of the repository where this set's data resides.
+ * @param writeAccess Whether or not we need write access to this location. If <code>false</code>, readonly access
+ * will be used.
+ * @return this object, to allow chaining.
+ */
+ public RepositoryAdminLoginContext addDeploymentRepository(URL repositoryLocation, String repositoryCustomer, String repositoryName, boolean writeAccess);
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/RepositoryObject.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/RepositoryObject.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/RepositoryObject.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/RepositoryObject.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,103 @@
+package net.luminis.liq.client.repository;
+
+import java.util.Comparator;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Map;
+
+/**
+ * A basic repository object, intended to be stored in a ObjectRepository of its given type.
+ * A RepositoryObject is associatable.
+ */
+public interface RepositoryObject extends Associatable {
+ /**
+ * This key is used to store the RepositoryObject an event comes from, in the Event object.
+ */
+ public final static String EVENT_ENTITY = "entity";
+
+ public static final String PUBLIC_TOPIC_ROOT = RepositoryObject.class.getPackage().getName().replace('.', '/') + "/public/";
+ public static final String PRIVATE_TOPIC_ROOT = RepositoryObject.class.getPackage().getName().replace('.', '/') + "/private/";
+
+ public static final String TOPIC_ADDED_SUFFIX = "ADDED";
+ public static final String TOPIC_REMOVED_SUFFIX = "REMOVED";
+ public static final String TOPIC_CHANGED_SUFFIX = "CHANGED";
+ public static final String TOPIC_ALL_SUFFIX = "*";
+
+ /**
+ * Adds a named attribute to this object's attributes. If the name already exists,
+ * it will be overwritten, and the old value is returned; will return <code>null</code>
+ * when the value is new.
+ */
+ public String addAttribute(String key, String value);
+ /**
+ * Gets a named attribute. Returns <code>null<code> when the attribute named by
+ * <code>key</code> does not exist.
+ */
+ public String getAttribute(String key);
+ /**
+ * Returns an enumeration of all attribute keys.
+ */
+ public Enumeration<String> getAttributeKeys();
+ /**
+ * Adds a named tag to this object's attributes. If the name already exists,
+ * it will be overwritten, and the old value is returned; will return <code>null</code>
+ * when the value is new.
+ */
+ public String addTag(String key, String value);
+ /**
+ * Gets a named tag. Returns <code>null<code> when the attribute named by
+ * <code>key</code> does not exist.
+ */
+ public String getTag(String key);
+ /**
+ * Returns an enumeration of all tags in this object, coming from both the
+ * tags and the attributes.
+ */
+ public Enumeration<String> getTagKeys();
+ /**
+ * Returns a <code>Dictionary</code> representing this object. It will contain all keys,
+ * from <code>getTagKeys</code>, and all values that correspond to them. If a key is present
+ * in both the attributes and the tags, the corresponding value will be an array of two
+ * <code>String</code> objects; otherwise a single <code>String</code> is returned.
+ */
+ public Dictionary<String, Object> getDictionary();
+ /**
+ * Indicates that this object should no longer be used.
+ */
+ public boolean isDeleted();
+ /**
+ * Creates a filter string for use in associations, optionally with some
+ * additional properties. The basic implementation will use all <code>getDefiningKeys</code>.
+ * @param properties Properties indicating specifics of the filter to be created.
+ * @return A string representation of a filter, for use in <code>Association</code>s.
+ */
+ public String getAssociationFilter(Map<String, String> properties);
+
+ /**
+ * Determines the cardinality of this endpoint of an association, given
+ * the passed properties.
+ * @param properties Properties indicating specifics of this endpoint.
+ * @return The necessary cardinality.
+ */
+ public int getCardinality(Map<String, String> properties);
+
+ /**
+ * Returns a <code>Comparator</code> for this type of object. Descendent
+ * classes are expected to return a comparator if they can be meaningfully compared,
+ * and otherwise (if no order is natural), return <code>null</code>.
+ * @return A <code>Comparator</code> for this type of object
+ */
+ @SuppressWarnings("unchecked")
+ public Comparator getComparator();
+
+ /**
+ * Returns a string which uniquely defines this object. The content is
+ * not intended to 'mean' anything.
+ * @return A uniquely defining string.
+ */
+ public String getDefinition();
+
+ public enum WorkingState {
+ New, Changed, Unchanged, Removed;
+ }
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/RepositoryUtil.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/RepositoryUtil.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/RepositoryUtil.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/RepositoryUtil.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,15 @@
+package net.luminis.liq.client.repository;
+
+public class RepositoryUtil {
+ /**
+ * Before passing user input into an LDAP filter, some precautions need to be taken
+ * (see section 3.2.6 of the OSGi core specification). This function escapes
+ * illegal characters, and returns the resulting string.
+ */
+ public static String escapeFilterValue(String value) {
+ return value.replaceAll("\\\\", "\\\\\\\\")
+ .replaceAll("\\(", "\\\\(")
+ .replaceAll("\\)", "\\\\)")
+ .replaceAll("\\*", "\\\\*");
+ }
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/ArtifactHelper.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/ArtifactHelper.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/ArtifactHelper.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/ArtifactHelper.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,75 @@
+package net.luminis.liq.client.repository.helper;
+
+import java.util.Comparator;
+import java.util.Map;
+
+import net.luminis.liq.client.repository.object.ArtifactObject;
+
+/**
+ * Interface to an artifact helper. For each type of artifact, there should be a helper
+ * service implementing this interface. The service should be registered with the mimetype
+ * in the service's properties, so it can be identified. The <code>KEY_MIMETYPE</code> in
+ * this class can be used for this purpose.
+ */
+public interface ArtifactHelper {
+ public static final String KEY_MIMETYPE = "mimetype";
+
+ /**
+ * Checks whether this helper can 'do anything' with this artifact object.
+ * @param object An artifact object.
+ * @return <code>true</code> when this helper can use the object, <code>false</code> otherwise.
+ */
+ public boolean canUse(ArtifactObject object);
+
+ /**
+ * Returns the artifact preprocessor that is associated with the type of artifact this
+ * helper helps. Return null when no useful processor is available.
+ * @return An artifact preprocessor, or <code>null</code> if no useful preprocessor can be created.
+ */
+ public ArtifactPreprocessor getPreprocessor();
+
+ /**
+ * Creates a filter string for use in associations, optionally with some
+ * additional properties. The basic implementation will use all <code>getDefiningKeys</code>.
+ * @param properties Properties indicating specifics of the filter to be created.
+ * @return A string representation of a filter, for use in <code>Association</code>s.
+ */
+ public <TYPE extends ArtifactObject> String getAssociationFilter(TYPE obj, Map<String, String> properties);
+
+ /**
+ * Determines the cardinality of this endpoint of an association, given
+ * the passed properties.
+ * @param properties Properties indicating specifics of this endpoint.
+ * @return The necessary cardinality.
+ */
+ public <TYPE extends ArtifactObject> int getCardinality(TYPE obj, Map<String, String> properties);
+
+ /**
+ * Returns a <code>Comparator</code> for this type of object. Descendent
+ * classes are expected to return a comparator if they can be meaningfully compared,
+ * and otherwise (if no order is natural), return <code>null</code>.
+ * @return A <code>Comparator</code> for this type of object
+ */
+ public Comparator<ArtifactObject> getComparator();
+
+ /**
+ * Checks the correctness of the given attributes for this type of object. If they
+ * are correct, the map will be returned, potentially with some changes, and if not,
+ * an {@link IllegalArgumentException} will be raised. Optionally, this
+ * function can do some validation of input parameters, such as normalizing numbers.
+ */
+ public Map<String, String> checkAttributes(Map<String, String> attributes);
+
+ /**
+ * Gets an array of keys in the attributes that are considered defining for this type
+ * of object; the combination of values of these keys should result in a unique
+ * identification of the object.
+ */
+ public String[] getDefiningKeys();
+
+ /**
+ * Gets an array of all attributes that have to be present when creating an object
+ * of this type.
+ */
+ public String[] getMandatoryAttributes();
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/ArtifactPreprocessor.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/ArtifactPreprocessor.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/ArtifactPreprocessor.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/ArtifactPreprocessor.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,37 @@
+package net.luminis.liq.client.repository.helper;
+
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * An ArtifactPreprocessor processes an artifact before it is deployed.
+ */
+public interface ArtifactPreprocessor {
+
+ /**
+ * Preprocesses a single artifact, uploads it to the obr, and returns the new URL as a string.
+ * @param url A string representing a URL to the original artifact.
+ * @param props A PropertyResolver which can be used to fill in 'holes' in the template.
+ * @param gatewayID The gatewayID of the gateway for which this artifact is being processed.
+ * @param version The deployment version for which this artifact is being processed.
+ * @param obrBase A base OBR to upload the new artifact to.
+ * @return A URL to the new object (or the old one, if no replacing was necessary), as a string.
+ * @throws IOException Thrown if reading the original artifact goes wrong, or storing the processed one.
+ */
+ public String preprocess(String url, PropertyResolver props, String gatewayID, String version, URL obrBase) throws IOException;
+
+ /**
+ * Indicates whether the template should be processed again, given the properties, and the version to which it
+ * should be compared.
+ * @param url A string representing a URL to the original artifact.
+ * @param props A PropertyResolver which can be used to fill in 'holes' in the template.
+ * @param gatewayID The gatewayID of the gateway for which this artifact is being processed.
+ * @param version The deployment version for which this artifact is being processed.
+ * @param fromVersion The deployment version to which the current one should be compared.
+ * @return <code>false</code> if the version of the processed artifact identified by <code>fromVersion</code>
+ * is identical to what would be created using the new <code>props</code>; <code>true</code> otherwise.
+ * @throws IOException
+ */
+ public boolean needsNewVersion(String url, PropertyResolver props, String gatewayID, String fromVersion);
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/ArtifactRecognizer.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/ArtifactRecognizer.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/ArtifactRecognizer.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/ArtifactRecognizer.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,40 @@
+package net.luminis.liq.client.repository.helper;
+
+import java.net.URL;
+import java.util.Map;
+
+/**
+ * Service interface for services that can recognize the type of an artifact, given a URL
+ * to that artifact.
+ */
+public interface ArtifactRecognizer {
+ /**
+ * Tries to determine the type of the artifact. If this recognizer cannot determine the type, it
+ * should return <code>null</code>.
+ * @param artifact A URL to a 'physical' artifact.
+ * @return The mimetype of the artifact, or <code>null</code> if the artifact is not recognized.
+ */
+ public String recognize(URL artifact);
+
+ /**
+ * Gets the relevant metadata for this artifact.
+ * @param artifact A URL to a 'physical' artifact.
+ * @return A map of strings, representing the relevant metadata specific for this artifact. The
+ * keys are best defined in the corresponding <code>ArtifactHelper</code> interface for this type of artifact.
+ * This function should also set the <code>ArtifactObject.KEY_PROCESSOR_PID</code> attribute.<br>
+ * Optionally, <code>ArtifactObject.KEY_ARTIFACT_NAME</code> and <code>ArtifactObject.KEY_ARTIFACT_DESCRIPTION</code>
+ * can be set.
+ * @throws IllegalArgumentException when the metadata cannot be retrieved from the <code>artifact</code>.
+ */
+ public Map<String, String> extractMetaData(URL artifact) throws IllegalArgumentException;
+
+ /**
+ * Indicates whether this recognizer can handle (i.e., extract metadata) from an artifact of
+ * a given mime type.
+ * @param mimetype The mimetype of an artifact.
+ * @return <code>true</code> when this type should be able to be handled by this recognizer;
+ * <code>false</code> otherwise.
+ */
+ public boolean canHandle(String mimetype);
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/PropertyResolver.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/PropertyResolver.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/PropertyResolver.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/PropertyResolver.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,15 @@
+package net.luminis.liq.client.repository.helper;
+
+/**
+ * Interface for resolving properties about the template's
+ * environment which are to be used by an ArtifactPreprocessor.
+ */
+public interface PropertyResolver {
+ /**
+ * Gets a property, based on the given key. If the key cannot be found, <code>null</code>
+ * can be used.
+ * @param key A key to some property. Cannot be null.
+ * @return The property identified by <code>key</code> if it can be found, <code>null</code> otherwise.
+ */
+ public String get(String key);
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/base/ArtifactPreprocessorBase.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/base/ArtifactPreprocessorBase.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/base/ArtifactPreprocessorBase.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/base/ArtifactPreprocessorBase.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,162 @@
+package net.luminis.liq.client.repository.helper.base;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+
+import net.luminis.liq.client.repository.helper.ArtifactPreprocessor;
+import net.luminis.liq.client.repository.helper.PropertyResolver;
+
+/**
+ * This class can be used as a base class for artifact preprocessors. It comes with its
+ * own upload() method, which will be used by all artifact preprocessors anyway.
+ */
+public abstract class ArtifactPreprocessorBase implements ArtifactPreprocessor {
+
+ private static final int BUFFER_SIZE = 4 * 1024;
+
+ /**
+ * Uploads an artifact to an OBR.
+ * @param input A inputstream from which the artifact can be read.
+ * @param name The name of the artifact. If the name is not unique, an IOException will be thrown.
+ * @param obrBase The base URL of the obr to which this artifact should be written.
+ * @return A URL to the uploaded artifact; this is identical to calling <code>determineNewUrl(name, obrBase)</code>
+ * @throws IOException If there was an error reading from <code>input</code>, or if there was a problem communicating
+ * with the OBR.
+ */
+ protected URL upload(InputStream input, String name, URL obrBase) throws IOException {
+ if (obrBase == null) {
+ throw new IOException("There is no storage available for this artifact.");
+ }
+ if ((name == null) || (input == null)) {
+ throw new IllegalArgumentException("None of the parameters can be null.");
+ }
+
+ OutputStream output = null;
+ URL url = null;
+ try {
+ url = determineNewUrl(name, obrBase);
+ URLConnection connection = url.openConnection();
+ connection.setDoOutput(true);
+ connection.setDoInput(true);
+ output = connection.getOutputStream();
+ byte[] buffer = new byte[BUFFER_SIZE];
+ for (int count = input.read(buffer); count != -1; count = input.read(buffer)) {
+ output.write(buffer, 0, count);
+ }
+ output.close();
+ if (connection instanceof HttpURLConnection) {
+ int responseCode = ((HttpURLConnection) connection).getResponseCode();
+ switch (responseCode) {
+ case HttpURLConnection.HTTP_OK :
+ break;
+ case HttpURLConnection.HTTP_CONFLICT:
+ throw new IOException("Artifact already exists in storage.");
+ case HttpURLConnection.HTTP_INTERNAL_ERROR:
+ throw new IOException("The storage server returned an internal server error.");
+ default:
+ throw new IOException("The storage server returned code " + responseCode + " writing to " + url.toString());
+ }
+ }
+ }
+ catch (IOException ioe) {
+ throw new IOException("Error uploading " + name + ": " + ioe.getMessage());
+ }
+ finally {
+ if (input != null) {
+ try {
+ input.close();
+ }
+ catch (Exception ex) {
+ // Not much we can do
+ }
+ }
+ if (output != null) {
+ try {
+ output.close();
+ }
+ catch (Exception ex) {
+ // Not much we can do
+ }
+ }
+ }
+
+ return url;
+ }
+
+ /**
+ * Gets a stream to write an artifact to, which will be uploaded to the OBR.
+ * @param name The name of the artifact.
+ * @param obrBase The base URL of the obr to which this artifact should be written.
+ * @return An outputstream, to which the artifact can be written.
+ * @throws IOException If there is a problem setting up the outputstream.
+ */
+ protected OutputStream upload(final String name, final URL obrBase) throws IOException {
+ /*
+ * This function works by starting a thread which reads from the outputstream which is passed out,
+ * and writing it to another stream, which is read by a thread that does the Upload.
+ */
+ PipedOutputStream externalOutput = new PipedOutputStream();
+ final PipedInputStream externalInput = new PipedInputStream(externalOutput);
+
+ final PipedOutputStream internalOutput = new PipedOutputStream();
+ final PipedInputStream internalInput = new PipedInputStream(internalOutput);
+
+ new Thread(new Runnable() {
+ public void run() {
+ try {
+ byte[] buffer = new byte[BUFFER_SIZE];
+ for (int count = externalInput.read(buffer); count != -1; count = externalInput.read(buffer)) {
+ internalOutput.write(buffer, 0, count);
+ }
+ }
+ catch (IOException e) {
+ // We cannot signal this to the user, but he will notice (in the original thread)
+ // that the pipe has been broken.
+ }
+ finally {
+ try {
+ internalOutput.close();
+ }
+ catch (IOException e) {
+ // Not much to be done.
+ }
+ try {
+ externalInput.close();
+ }
+ catch (IOException e) {
+ // Not much to be done.
+ }
+ }
+ }
+ }, "upload-Outputstream(" + name + ")").start();
+
+ new Thread(new Runnable() {
+ public void run() {
+ try {
+ upload(internalInput, name, obrBase);
+ }
+ catch (IOException e) {
+ // We cannot signal this to the user, but he will notice (in the original thread)
+ // that the pipe has been broken.
+ }
+ }
+ }, "upload-Inputstream(" + name + ")").start();
+
+ return externalOutput;
+ }
+
+ protected URL determineNewUrl(String name, URL obrBase) throws MalformedURLException {
+ return new URL(obrBase, name);
+ }
+
+ public abstract String preprocess(String url, PropertyResolver props, String gatewayID, String version, URL obrBase) throws IOException;
+
+ public abstract boolean needsNewVersion(String url, PropertyResolver props, String gatewayID, String fromVersion);
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/base/VelocityArtifactPreprocessor.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/base/VelocityArtifactPreprocessor.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/base/VelocityArtifactPreprocessor.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/base/VelocityArtifactPreprocessor.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,230 @@
+package net.luminis.liq.client.repository.helper.base;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.luminis.liq.client.repository.helper.PropertyResolver;
+
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+
+/**
+ * This class can be used as a 'default' artifact preprocessor, using the Velocity template engine to preprocess
+ * the artifact.
+ */
+public class VelocityArtifactPreprocessor extends ArtifactPreprocessorBase {
+
+ private static final int BUFFER_SIZE = 1024;
+ private Map<String, byte[]> m_cachedArtifacts = new HashMap<String, byte[]>();
+ private Map<String, String> m_cachedHashes = new HashMap<String, String>();
+
+ private static Object m_initLock = new Object();
+ private static boolean m_velocityInitialized = false;
+
+ private void init() throws IOException {
+ if (m_velocityInitialized) {
+ return;
+ }
+ else {
+ synchronized (m_initLock) {
+ if (!m_velocityInitialized) {
+ try {
+ Velocity.init();
+ m_velocityInitialized = true;
+ }
+ catch (Exception e) {
+ // Something went seriously bad initializing velocity.
+ throw new IOException("Error initializing Velocity: " + e.getMessage());
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public String preprocess(String url, PropertyResolver props, String gatewayID, String version, URL obrBase) throws IOException {
+ init();
+ // first, get the original data.
+ byte[] input = null;
+ try {
+ input = getArtifactAsBytes(url);
+ }
+ catch (IOException ioe) {
+ throw new IOException("Error retrieving the original artifact for preprocessing: " + ioe.getMessage());
+ }
+
+ // process the template
+ byte[] result = process(input, props);
+
+ if (Arrays.equals(result, input)) {
+ return url;
+ }
+ else {
+ try {
+ String name = getFilename(url, gatewayID, version);
+ OutputStream output = upload(name, obrBase);
+ output.write(result);
+ output.close();
+ setHashForVersion(url, gatewayID, version, hash(result));
+ return determineNewUrl(name, obrBase).toString();
+ }
+ catch (IOException ioe) {
+ throw new IOException("Error storing the processed: " + ioe.getMessage());
+ }
+ }
+ }
+
+ private String getFilename(String url, String gatewayID, String version) throws MalformedURLException {
+ return new File(new URL(url).getFile()).getName() + "-" + gatewayID + "-" + version;
+ }
+
+ private String getFullUrl(String url, String gatewayID, String version) throws MalformedURLException {
+ return url + "-" + gatewayID + "-" + version;
+ }
+
+ private String getHashForVersion(String url, String gateway, String version) {
+ String key = new StringBuilder().append('[')
+ .append(url)
+ .append("][")
+ .append(gateway)
+ .append("][")
+ .append(version)
+ .append(']').toString();
+
+ if (m_cachedHashes.containsKey(key)) {
+ return m_cachedHashes.get(key);
+ }
+ else {
+ byte[] processedTemplate;
+ try {
+ processedTemplate = getBytesFromUrl(getFullUrl(url, gateway, version));
+ }
+ catch (IOException e) {
+ // we cannot retrieve the artifact, so we cannot say anything about it.
+ return null;
+ }
+ String result = hash(processedTemplate);
+
+ m_cachedHashes.put(key, result);
+ return result;
+ }
+ }
+
+ private void setHashForVersion(String url, String gateway, String version, String hash) {
+ String key = new StringBuilder().append('[')
+ .append(url)
+ .append("][")
+ .append(gateway)
+ .append("][")
+ .append(version)
+ .append(']').toString();
+
+ m_cachedHashes.put(key, hash);
+ }
+
+ private byte[] process(byte[] input, PropertyResolver props) throws IOException {
+ try {
+ VelocityContext context = new VelocityContext();
+ context.put("context", props);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ Writer writer = new OutputStreamWriter(baos);
+ Velocity.evaluate(context, writer, "", new InputStreamReader(new ByteArrayInputStream(input)));
+ writer.flush();
+ return baos.toByteArray();
+ }
+ catch (IOException ioe) {
+ throw new IOException("Error processing the artifact: " + ioe.getMessage());
+ }
+ }
+
+ /**
+ * Helper method, which reads all information from a stream, and returns that as a
+ * byte array. The byte array is not to be changed.
+ */
+ private byte[] getArtifactAsBytes(String url) throws IOException {
+ if (m_cachedArtifacts.containsKey(url)) {
+ return m_cachedArtifacts.get(url);
+ }
+ else {
+ return getBytesFromUrl(url);
+ }
+ }
+
+ private byte[] getBytesFromUrl(String url) throws IOException, MalformedURLException {
+ ByteArrayOutputStream found = new ByteArrayOutputStream();
+ InputStream in = new URL(url).openStream();
+
+ byte[] buf = new byte[BUFFER_SIZE];
+ for (int count = in.read(buf); count != -1; count = in.read(buf)) {
+ found.write(buf, 0, count);
+ }
+ in.close();
+ byte[] result = found.toByteArray();
+ m_cachedArtifacts.put(url, result);
+ return result;
+ }
+
+ @Override
+ public boolean needsNewVersion(String url, PropertyResolver props, String gatewayID, String fromVersion) {
+ try {
+ init();
+ }
+ catch (IOException e) {
+ // problem initializing velocity... we cannot say anything.
+ return true;
+ }
+ // get the tempate
+ byte[] input = null;
+ byte[] result = null;
+ try {
+ input = getArtifactAsBytes(url);
+ result = process(input, props);
+ }
+ catch (IOException ioe) {
+ // we cannot retrieve the original artifact, or process it; we can't say anyting now.
+ return true;
+ }
+
+ // process the template
+
+ // first check: did we need any processing at all?
+ if (Arrays.equals(result, input)) {
+ return false;
+ }
+
+ // hash the processed template
+ String newHash = hash(result);
+
+ // find the hash for the previous version
+ String oldHash = getHashForVersion(url, gatewayID, fromVersion);
+
+ // Note: we do not cache any previously created processed templates, since the call that asks us to approve a new version
+ // may cross a pending needsNewVersion call.
+ return !newHash.equals(oldHash);
+ }
+
+ private String hash(byte[] input) {
+ try {
+ return new String(MessageDigest.getInstance("MD5").digest(input));
+ }
+ catch (NoSuchAlgorithmException e) {
+ // Will not happen: MD5 is a standard algorithm.
+ }
+ return null;
+ }
+
+}