From e6c942a30df9aefadb5e25e49ece634b80db4926 Mon Sep 17 00:00:00 2001 From: Roman Roelofsen Date: Thu, 4 Mar 2010 22:53:05 +0100 Subject: [PATCH 001/188] Added OSGi proof of concept Very basic example Starting point to kick of discussions --- akka-core/pom.xml | 16 ++ akka-osgi/akka-dependencies-bundle/pom.xml | 56 +++++ akka-osgi/akka-sample-osgi/pom.xml | 49 +++++ .../src/main/scala/Activator.scala | 36 +++ .../src/main/scala/Actors.scala | 18 ++ akka-osgi/deployer/pom.xml | 54 +++++ .../akka/osgi/deployer/Activator.java | 43 ++++ .../akka/osgi/deployer/DirWatcher.java | 207 ++++++++++++++++++ akka-osgi/karaf/pom.xml | 127 +++++++++++ akka-osgi/karaf/src/main/assembly/runtime.xml | 37 ++++ akka-osgi/pom.xml | 45 ++++ 11 files changed, 688 insertions(+) create mode 100644 akka-osgi/akka-dependencies-bundle/pom.xml create mode 100644 akka-osgi/akka-sample-osgi/pom.xml create mode 100644 akka-osgi/akka-sample-osgi/src/main/scala/Activator.scala create mode 100644 akka-osgi/akka-sample-osgi/src/main/scala/Actors.scala create mode 100644 akka-osgi/deployer/pom.xml create mode 100644 akka-osgi/deployer/src/main/java/se/scalablesolutions/akka/osgi/deployer/Activator.java create mode 100644 akka-osgi/deployer/src/main/java/se/scalablesolutions/akka/osgi/deployer/DirWatcher.java create mode 100644 akka-osgi/karaf/pom.xml create mode 100644 akka-osgi/karaf/src/main/assembly/runtime.xml create mode 100644 akka-osgi/pom.xml diff --git a/akka-core/pom.xml b/akka-core/pom.xml index d6ca57ebfe..b9753200c8 100644 --- a/akka-core/pom.xml +++ b/akka-core/pom.xml @@ -108,4 +108,20 @@ test + + + + + org.apache.felix + maven-bundle-plugin + + + + se.scalablesolutions.akka.*;version=${project.version};-split-package:=merge-first + + + + + + diff --git a/akka-osgi/akka-dependencies-bundle/pom.xml b/akka-osgi/akka-dependencies-bundle/pom.xml new file mode 100644 index 0000000000..74d1792be4 --- /dev/null +++ b/akka-osgi/akka-dependencies-bundle/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + + + se.scalablesolutions.akka + akka-osgi-parent + 0.7-SNAPSHOT + + + akka-dependencies-bundle + Akka Dependencies Bundle + + + + akka-kernel + se.scalablesolutions.akka + ${project.version} + + + + + + + org.apache.felix + maven-bundle-plugin + + + + *;resolution:=optional + + + + !test.*, + + + !scala.*, + !org.apache.commons.io.*, + !org.codehaus.jackson.*, + !org.codehaus.jettison.*, + !org.jboss.netty.*, + + + !se.scalablesolutions.akka.*, + + + *;-split-package:=merge-first + + + + + + + + diff --git a/akka-osgi/akka-sample-osgi/pom.xml b/akka-osgi/akka-sample-osgi/pom.xml new file mode 100644 index 0000000000..bd48ca2392 --- /dev/null +++ b/akka-osgi/akka-sample-osgi/pom.xml @@ -0,0 +1,49 @@ + + 4.0.0 + + akka-sample-osgi + Akka OSGi Sample Module + + jar + + + akka-osgi-parent + se.scalablesolutions.akka + 0.7-SNAPSHOT + + + + + akka-core + se.scalablesolutions.akka + ${project.version} + + + org.osgi + org.osgi.core + + + org.osgi + org.osgi.compendium + + + + + + + org.apache.felix + maven-bundle-plugin + + + se.scalablesolutions.akka.osgi.sample.Activator + + se.scalablesolutions.akka.osgi.sample + + + + + + + + diff --git a/akka-osgi/akka-sample-osgi/src/main/scala/Activator.scala b/akka-osgi/akka-sample-osgi/src/main/scala/Activator.scala new file mode 100644 index 0000000000..7925a2705f --- /dev/null +++ b/akka-osgi/akka-sample-osgi/src/main/scala/Activator.scala @@ -0,0 +1,36 @@ + +package se.scalablesolutions.akka.osgi.sample + +import org.osgi.framework.{BundleContext, BundleActivator} +import se.scalablesolutions.akka.config.ScalaConfig._ +import se.scalablesolutions.akka.actor.{Supervisor, SupervisorFactory} + +class Activator extends BundleActivator { + + var supervisor: Supervisor = _ + + val ping = new Ping + + def start(context: BundleContext) { + println("Starting Akka OSGi sample") + + supervisor = SupervisorFactory( + SupervisorConfig( + RestartStrategy(OneForOne, 3, 100, List(classOf[Exception])), + Supervise(ping, LifeCycle(Permanent)) :: Nil)).newInstance + + supervisor.start + println("Supervisor: " + supervisor) + + println("Sending ping") + ping send CounterMessage(0) + + } + + def stop(context: BundleContext) { + println("Stopping Akka OSGi sample") + + supervisor.stop + } + +} \ No newline at end of file diff --git a/akka-osgi/akka-sample-osgi/src/main/scala/Actors.scala b/akka-osgi/akka-sample-osgi/src/main/scala/Actors.scala new file mode 100644 index 0000000000..008ea98ef1 --- /dev/null +++ b/akka-osgi/akka-sample-osgi/src/main/scala/Actors.scala @@ -0,0 +1,18 @@ + +package se.scalablesolutions.akka.osgi.sample + +import se.scalablesolutions.akka.actor.Actor + +case class CounterMessage(counter: Int) + +class Ping extends Actor { + def receive = { + case CounterMessage(i) => println("Got message " + i) + } +} + +class Pong extends Actor { + def receive = { + case _ => + } +} diff --git a/akka-osgi/deployer/pom.xml b/akka-osgi/deployer/pom.xml new file mode 100644 index 0000000000..e94aa441f3 --- /dev/null +++ b/akka-osgi/deployer/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + + + se.scalablesolutions.akka + akka-osgi-parent + 0.7-SNAPSHOT + + + akka-deployer + Akka Deployer + + + + org.osgi + org.osgi.core + + + org.osgi + org.osgi.compendium + + + + + src/main/java + src/test/java + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + **/* + + + + + org.apache.felix + maven-bundle-plugin + + + se.scalablesolutions.akka.osgi.deployer.Activator + se.scalablesolutions.akka.osgi.deployer.* + + + + + + + diff --git a/akka-osgi/deployer/src/main/java/se/scalablesolutions/akka/osgi/deployer/Activator.java b/akka-osgi/deployer/src/main/java/se/scalablesolutions/akka/osgi/deployer/Activator.java new file mode 100644 index 0000000000..8cc1dca792 --- /dev/null +++ b/akka-osgi/deployer/src/main/java/se/scalablesolutions/akka/osgi/deployer/Activator.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2010 Roman Roelofsen + * + * 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. + */ +package se.scalablesolutions.akka.osgi.deployer; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class Activator implements BundleActivator { + + private static final String DIRINSTALLER_POLL = "dirinstaller.poll"; + private static final String DIRINSTALLER_DIR = "dirinstaller.dir"; + + private DirWatcher watcher; + + public void start(BundleContext context) throws Exception { + String bundlesDir = context.getProperty(DIRINSTALLER_DIR); + bundlesDir = bundlesDir == null ? "akka" : bundlesDir; + + String intervalStr = context.getProperty(DIRINSTALLER_POLL); + Integer interval = intervalStr == null ? 2000 : Integer.valueOf(intervalStr); + + watcher = new DirWatcher(context, bundlesDir, interval); + watcher.startWatching(); + } + + public void stop(BundleContext context) throws Exception { + watcher.stopWatching(); + } + +} diff --git a/akka-osgi/deployer/src/main/java/se/scalablesolutions/akka/osgi/deployer/DirWatcher.java b/akka-osgi/deployer/src/main/java/se/scalablesolutions/akka/osgi/deployer/DirWatcher.java new file mode 100644 index 0000000000..37d65e4c53 --- /dev/null +++ b/akka-osgi/deployer/src/main/java/se/scalablesolutions/akka/osgi/deployer/DirWatcher.java @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2010 Roman Roelofsen + * + * 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. + */ +package se.scalablesolutions.akka.osgi.deployer; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; +import org.osgi.service.packageadmin.PackageAdmin; +import org.osgi.util.tracker.ServiceTracker; + +public class DirWatcher { + + private Thread thread; + + private ServiceTracker packageAdminTracker; + + private final BundleContext context; + private final String bundlesDir; + private final int interval; + + private final Map timestamps = new HashMap(); + private boolean modifiedSinceLastRun = false; + + private boolean warningMissingLoadDirPresented = false; + + public DirWatcher(BundleContext context, String bundlesDir, int interval) { + this.packageAdminTracker = new ServiceTracker(context, PackageAdmin.class.getName(), null); + this.packageAdminTracker.open(); + + this.context = context; + this.bundlesDir = bundlesDir; + this.interval = interval; + } + + public void startWatching() { + thread = new Thread() { + @Override + public void run() { + try { + while (!Thread.interrupted()) { + modifiedSinceLastRun = false; + List found = new ArrayList(); + getAllFiles(found, bundlesDir); + analyseNewState(found); + Thread.sleep(interval); + } + } catch (InterruptedException e) { + } + } + }; + thread.start(); + } + + public void stopWatching() { + thread.interrupt(); + } + + private void getAllFiles(List found, String dirName) { + File dir = new File(dirName); + File[] files = dir.listFiles(); + if (files == null) { + if (!warningMissingLoadDirPresented) { + System.out.println("DirInstaller WARNING: Directory '" + dirName + "' does not exist!"); + warningMissingLoadDirPresented = true; + } + return; + } + + for (File f : files) { + try { + if (f.isFile()) + if (f.getName().endsWith(".cfg")) { + found.add(0, f); + } else { + found.add(f); + } + else + getAllFiles(found, f.getCanonicalPath()); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + private void analyseNewState(List found) { + // check for new or updated bundles + for (File file : found) { + try { + String string = file.getCanonicalPath(); + Long time = timestamps.get(string); + + // time == null: system startup + // time < lastModified: updated file + if (time == null || time < file.lastModified()) { + timestamps.put(string, file.lastModified()); + modifiedSinceLastRun = true; + + if (string.endsWith(".jar")) + installOrUpdateBundle(string, time == null); + } + } catch (IOException e) { + System.out.println("DirInstaller: Problems accessing file " + file.getName()); + e.printStackTrace(); + } catch (BundleException e) { + System.out.println("DirInstaller: Problems installing or updating bundle. File: " + + file.getName()); + e.printStackTrace(); + } + } + + // check removed bundles + Iterator it = timestamps.keySet().iterator(); + while (it.hasNext()) { + String s = it.next(); + try { + if (!containsFilename(s, found)) { + for (Bundle b : context.getBundles()) { + if (b.getLocation().equals("file:" + s)) { + System.out.println("Removing bundle '" + b.getSymbolicName() + "'"); + b.uninstall(); + modifiedSinceLastRun = true; + } + } + it.remove(); + timestamps.remove(s); + } + } catch (BundleException e) { + System.out.println("DirInstaller: Problems uninstalling bundle: " + s); + } catch (IOException e) { + System.out.println("DirInstaller: Problems processing file: " + e); + } + } + + if (modifiedSinceLastRun) + startAllAndRefresh(); + } + + private boolean containsFilename(String string, List fileList) throws IOException { + for (File f : fileList) { + if (f.getCanonicalPath().equals(string)) + return true; + } + return false; + } + + private void startAllAndRefresh() { + for (Bundle b : context.getBundles()) { + try { + if (b.getState() != Bundle.ACTIVE && !isFragment(b)) { + b.start(); + } + } catch (BundleException e) { + System.out.println("Problems starting bundle: " + b); + e.printStackTrace(); + } + } + PackageAdmin admin = (PackageAdmin) this.packageAdminTracker.getService(); + System.out.println("DirInstaller: Refreshing packages"); + admin.refreshPackages(null); + } + + private boolean isFragment(Bundle b) { + PackageAdmin admin = (PackageAdmin) this.packageAdminTracker.getService(); + return admin.getBundleType(b) == PackageAdmin.BUNDLE_TYPE_FRAGMENT; + } + + private void installOrUpdateBundle(String s, boolean startup) throws BundleException { + // Check if bundle is already installed + // Perform bundle update in this case + for (Bundle b : context.getBundles()) { + if (b.getLocation().endsWith(s)) { + if (startup) // Don't update bundles on startup + return; + + System.out.println("DirInstaller: Updating bundle [" + b.getSymbolicName() + "]"); + b.stop(); + b.update(); + return; + } + } + // If the bundle is not installed, perform bundle install + System.out.println("DirInstaller: Installing bundle [" + s + "]"); + context.installBundle("file:" + s); + } + +} diff --git a/akka-osgi/karaf/pom.xml b/akka-osgi/karaf/pom.xml new file mode 100644 index 0000000000..ffc9dc8697 --- /dev/null +++ b/akka-osgi/karaf/pom.xml @@ -0,0 +1,127 @@ + + + + 4.0.0 + + + akka-osgi-parent + se.scalablesolutions.akka + 0.7-SNAPSHOT + + + akka-karaf + Akka OSGi Karaf Distribution + pom + + + http://www.apache.org/dist/felix/apache-felix-karaf-1.2.0.tar.gz + apache-felix-karaf-1.2.0 + + + + + + akka-dependencies-bundle + se.scalablesolutions.akka + ${project.version} + + + + + scala-library + org.scala-lang-osgi + 2.7.7 + + + commons-io + commons-io + 1.4 + + + org.codehaus.jackson + jackson-core-asl + 1.2.1 + + + org.codehaus.jackson + jackson-mapper-asl + 1.2.1 + + + org.jboss.netty + netty + 3.2.0.ALPHA3 + + + + + akka-core + se.scalablesolutions.akka + ${project.version} + + + akka-deployer + se.scalablesolutions.akka + ${project.version} + + + akka-sample-osgi + se.scalablesolutions.akka + ${project.version} + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + + generate-resources + generate-resources + + + + + + + + + run + + + + + + maven-assembly-plugin + + + src/main/assembly/runtime.xml + + + + + make-distribution-dir + package + + directory-single + + + + make-distribution-zip + package + + single + + + + + + + + diff --git a/akka-osgi/karaf/src/main/assembly/runtime.xml b/akka-osgi/karaf/src/main/assembly/runtime.xml new file mode 100644 index 0000000000..2fe4ef12cd --- /dev/null +++ b/akka-osgi/karaf/src/main/assembly/runtime.xml @@ -0,0 +1,37 @@ + + runtime + + zip + + false + + + src/main/resources/runtime + + + + target/generated/runtime + + + + + + + se.scalablesolutions.akka:akka-deployer + + ${karaf.root.dir}/akka + false + false + false + + + + se.scalablesolutions.akka:akka-deployer + + ${karaf.root.dir}/deploy + false + false + false + + + diff --git a/akka-osgi/pom.xml b/akka-osgi/pom.xml new file mode 100644 index 0000000000..9748335c9b --- /dev/null +++ b/akka-osgi/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + + + se.scalablesolutions.akka + akka + 0.7-SNAPSHOT + + + akka-osgi-parent + Akka OSGi Parent + + pom + + + 4.2.0 + + + + deployer + akka-dependencies-bundle + akka-sample-osgi + karaf + + + + + + org.osgi + org.osgi.core + ${osgi.version} + provided + + + org.osgi + org.osgi.compendium + ${osgi.version} + provided + + + + + From c09d64abf9869686324b2d3ff2d041d159e0dfb3 Mon Sep 17 00:00:00 2001 From: Roman Roelofsen Date: Fri, 5 Mar 2010 11:51:23 +0100 Subject: [PATCH 002/188] added akka-osgi module to parent pom --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 3cfc2839a8..ea7edf729e 100644 --- a/pom.xml +++ b/pom.xml @@ -59,6 +59,7 @@ akka-security akka-patterns akka-kernel + akka-osgi akka-fun-test-java akka-samples From f12484b1b40e007e0243354e638c4c82a1bf27f1 Mon Sep 17 00:00:00 2001 From: Roman Roelofsen Date: Fri, 12 Mar 2010 12:28:53 +0100 Subject: [PATCH 003/188] rewriting deployer in scala ... work in progress! --- akka-osgi/deployer/pom.xml | 18 +- .../akka/osgi/deployer/Activator.java | 43 ---- .../akka/osgi/deployer/DirWatcher.java | 207 ------------------ .../deployer/src/main/scala/Activator.scala | 36 +++ .../deployer/src/main/scala/DirWatcher.scala | 112 ++++++++++ 5 files changed, 153 insertions(+), 263 deletions(-) delete mode 100644 akka-osgi/deployer/src/main/java/se/scalablesolutions/akka/osgi/deployer/Activator.java delete mode 100644 akka-osgi/deployer/src/main/java/se/scalablesolutions/akka/osgi/deployer/DirWatcher.java create mode 100644 akka-osgi/deployer/src/main/scala/Activator.scala create mode 100644 akka-osgi/deployer/src/main/scala/DirWatcher.scala diff --git a/akka-osgi/deployer/pom.xml b/akka-osgi/deployer/pom.xml index e94aa441f3..db35d10dc1 100644 --- a/akka-osgi/deployer/pom.xml +++ b/akka-osgi/deployer/pom.xml @@ -13,6 +13,11 @@ Akka Deployer + + org.scala-lang + scala-library + ${scala.version} + org.osgi org.osgi.core @@ -24,20 +29,7 @@ - src/main/java - src/test/java - - org.apache.maven.plugins - maven-compiler-plugin - - 1.5 - 1.5 - - **/* - - - org.apache.felix maven-bundle-plugin diff --git a/akka-osgi/deployer/src/main/java/se/scalablesolutions/akka/osgi/deployer/Activator.java b/akka-osgi/deployer/src/main/java/se/scalablesolutions/akka/osgi/deployer/Activator.java deleted file mode 100644 index 8cc1dca792..0000000000 --- a/akka-osgi/deployer/src/main/java/se/scalablesolutions/akka/osgi/deployer/Activator.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2010 Roman Roelofsen - * - * 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. - */ -package se.scalablesolutions.akka.osgi.deployer; - -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; - -public class Activator implements BundleActivator { - - private static final String DIRINSTALLER_POLL = "dirinstaller.poll"; - private static final String DIRINSTALLER_DIR = "dirinstaller.dir"; - - private DirWatcher watcher; - - public void start(BundleContext context) throws Exception { - String bundlesDir = context.getProperty(DIRINSTALLER_DIR); - bundlesDir = bundlesDir == null ? "akka" : bundlesDir; - - String intervalStr = context.getProperty(DIRINSTALLER_POLL); - Integer interval = intervalStr == null ? 2000 : Integer.valueOf(intervalStr); - - watcher = new DirWatcher(context, bundlesDir, interval); - watcher.startWatching(); - } - - public void stop(BundleContext context) throws Exception { - watcher.stopWatching(); - } - -} diff --git a/akka-osgi/deployer/src/main/java/se/scalablesolutions/akka/osgi/deployer/DirWatcher.java b/akka-osgi/deployer/src/main/java/se/scalablesolutions/akka/osgi/deployer/DirWatcher.java deleted file mode 100644 index 37d65e4c53..0000000000 --- a/akka-osgi/deployer/src/main/java/se/scalablesolutions/akka/osgi/deployer/DirWatcher.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 2010 Roman Roelofsen - * - * 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. - */ -package se.scalablesolutions.akka.osgi.deployer; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.BundleException; -import org.osgi.service.packageadmin.PackageAdmin; -import org.osgi.util.tracker.ServiceTracker; - -public class DirWatcher { - - private Thread thread; - - private ServiceTracker packageAdminTracker; - - private final BundleContext context; - private final String bundlesDir; - private final int interval; - - private final Map timestamps = new HashMap(); - private boolean modifiedSinceLastRun = false; - - private boolean warningMissingLoadDirPresented = false; - - public DirWatcher(BundleContext context, String bundlesDir, int interval) { - this.packageAdminTracker = new ServiceTracker(context, PackageAdmin.class.getName(), null); - this.packageAdminTracker.open(); - - this.context = context; - this.bundlesDir = bundlesDir; - this.interval = interval; - } - - public void startWatching() { - thread = new Thread() { - @Override - public void run() { - try { - while (!Thread.interrupted()) { - modifiedSinceLastRun = false; - List found = new ArrayList(); - getAllFiles(found, bundlesDir); - analyseNewState(found); - Thread.sleep(interval); - } - } catch (InterruptedException e) { - } - } - }; - thread.start(); - } - - public void stopWatching() { - thread.interrupt(); - } - - private void getAllFiles(List found, String dirName) { - File dir = new File(dirName); - File[] files = dir.listFiles(); - if (files == null) { - if (!warningMissingLoadDirPresented) { - System.out.println("DirInstaller WARNING: Directory '" + dirName + "' does not exist!"); - warningMissingLoadDirPresented = true; - } - return; - } - - for (File f : files) { - try { - if (f.isFile()) - if (f.getName().endsWith(".cfg")) { - found.add(0, f); - } else { - found.add(f); - } - else - getAllFiles(found, f.getCanonicalPath()); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - private void analyseNewState(List found) { - // check for new or updated bundles - for (File file : found) { - try { - String string = file.getCanonicalPath(); - Long time = timestamps.get(string); - - // time == null: system startup - // time < lastModified: updated file - if (time == null || time < file.lastModified()) { - timestamps.put(string, file.lastModified()); - modifiedSinceLastRun = true; - - if (string.endsWith(".jar")) - installOrUpdateBundle(string, time == null); - } - } catch (IOException e) { - System.out.println("DirInstaller: Problems accessing file " + file.getName()); - e.printStackTrace(); - } catch (BundleException e) { - System.out.println("DirInstaller: Problems installing or updating bundle. File: " - + file.getName()); - e.printStackTrace(); - } - } - - // check removed bundles - Iterator it = timestamps.keySet().iterator(); - while (it.hasNext()) { - String s = it.next(); - try { - if (!containsFilename(s, found)) { - for (Bundle b : context.getBundles()) { - if (b.getLocation().equals("file:" + s)) { - System.out.println("Removing bundle '" + b.getSymbolicName() + "'"); - b.uninstall(); - modifiedSinceLastRun = true; - } - } - it.remove(); - timestamps.remove(s); - } - } catch (BundleException e) { - System.out.println("DirInstaller: Problems uninstalling bundle: " + s); - } catch (IOException e) { - System.out.println("DirInstaller: Problems processing file: " + e); - } - } - - if (modifiedSinceLastRun) - startAllAndRefresh(); - } - - private boolean containsFilename(String string, List fileList) throws IOException { - for (File f : fileList) { - if (f.getCanonicalPath().equals(string)) - return true; - } - return false; - } - - private void startAllAndRefresh() { - for (Bundle b : context.getBundles()) { - try { - if (b.getState() != Bundle.ACTIVE && !isFragment(b)) { - b.start(); - } - } catch (BundleException e) { - System.out.println("Problems starting bundle: " + b); - e.printStackTrace(); - } - } - PackageAdmin admin = (PackageAdmin) this.packageAdminTracker.getService(); - System.out.println("DirInstaller: Refreshing packages"); - admin.refreshPackages(null); - } - - private boolean isFragment(Bundle b) { - PackageAdmin admin = (PackageAdmin) this.packageAdminTracker.getService(); - return admin.getBundleType(b) == PackageAdmin.BUNDLE_TYPE_FRAGMENT; - } - - private void installOrUpdateBundle(String s, boolean startup) throws BundleException { - // Check if bundle is already installed - // Perform bundle update in this case - for (Bundle b : context.getBundles()) { - if (b.getLocation().endsWith(s)) { - if (startup) // Don't update bundles on startup - return; - - System.out.println("DirInstaller: Updating bundle [" + b.getSymbolicName() + "]"); - b.stop(); - b.update(); - return; - } - } - // If the bundle is not installed, perform bundle install - System.out.println("DirInstaller: Installing bundle [" + s + "]"); - context.installBundle("file:" + s); - } - -} diff --git a/akka-osgi/deployer/src/main/scala/Activator.scala b/akka-osgi/deployer/src/main/scala/Activator.scala new file mode 100644 index 0000000000..d12b63ba16 --- /dev/null +++ b/akka-osgi/deployer/src/main/scala/Activator.scala @@ -0,0 +1,36 @@ + +package se.scalablesolutions.akka.osgi.deployer + +import org.osgi.framework.{BundleContext, BundleActivator} +import java.io.File + +class Activator extends BundleActivator { + + private val AKKA_DEPLOYER_DIR = "akka.deployer.dir" + private val AKKA_DEPLOYER_POLL = "akka.deployer.poll" + + private var watcher: DirWatcher = _ + + def start(context: BundleContext) { + var bundlesDir = context.getProperty(AKKA_DEPLOYER_DIR) + bundlesDir = if (bundlesDir == null) "akka" else bundlesDir + + // check dir exists + if (new File(bundlesDir).listFiles == null) { + System.out.println("DirInstaller WARNING: Directory '" + bundlesDir + "' does not exist!") + return + } + + var interval = context.getProperty(AKKA_DEPLOYER_POLL) + interval = if (interval == null) "2000" else interval + + watcher = new DirWatcher(context, bundlesDir, interval.toInt) + watcher.startWatching + } + + def stop(context: BundleContext) { + if (watcher != null) + watcher.stopWatching + } + +} diff --git a/akka-osgi/deployer/src/main/scala/DirWatcher.scala b/akka-osgi/deployer/src/main/scala/DirWatcher.scala new file mode 100644 index 0000000000..4d4292604c --- /dev/null +++ b/akka-osgi/deployer/src/main/scala/DirWatcher.scala @@ -0,0 +1,112 @@ + +package se.scalablesolutions.akka.osgi.deployer + +import org.osgi.util.tracker.ServiceTracker +import java.io.File +import org.osgi.service.packageadmin.PackageAdmin +import org.osgi.framework.{Bundle, BundleContext} + +class DirWatcher(context: BundleContext, bundlesDir: String, interval: Int) { + + private var running = false + + private final var timestamps = Map[String, Long]() + + private val packageAdminTracker = new ServiceTracker(context, classOf[PackageAdmin].getName, null) + packageAdminTracker.open + + def startWatching { + if (running) return + running = true + new Thread { + override def run { + try { + while (running) { + val found = getAllFiles(bundlesDir) + analyseNewState(found) + Thread.sleep(interval) + } + } + catch { + case e: InterruptedException => + } + } + }.start() + } + + def stopWatching { + running = false + } + + private def getAllFiles(dirName: String): List[File] = { + val content = new File(dirName).listFiles + val files = content.filter(_.isFile).toList + val childs = content.filter(_.isDirectory).toList.flatMap(d => getAllFiles(d.getCanonicalPath)) + files ::: childs + } + + private def analyseNewState(found: List[File]) { + println("FOUND:" + found) + + // new or updated + val changed = found.filter(f => timestamps.getOrElse(f.getCanonicalPath, -1L) < f.lastModified) + changed.foreach {f => + val name = f.getCanonicalPath + timestamps += (name -> f.lastModified) + if (name.endsWith(".jar")) installOrUpdateBundle(name) + } + println("CHANGED:" + changed) + + // removed + val removed = timestamps.filter(f => !found.map(_.getCanonicalPath).contains(f._1)) + removed.foreach {f => + context.getBundles.filter(b => b.getLocation.equals("file:" + f._1)).foreach(_.uninstall) + timestamps -= f._1 + } + println("REMOVED:" + removed) + + if (changed.size + removed.size > 0) + startAllAndRefresh() + + println("") + } + + private def startAllAndRefresh() { + context.getBundles.filter(b => b.getState != Bundle.ACTIVE && !isFragment(b)).foreach {b => + try { + b.start + } catch { + case e: Exception => { + System.out.println("Problems starting bundle: " + b) + e.printStackTrace + } + } + } + + val admin = this.packageAdminTracker.getService.asInstanceOf[PackageAdmin] + System.out.println("DirInstaller: Refreshing packages") + admin.refreshPackages(null) + } + + + private def isFragment(b: Bundle): Boolean = { + var admin: PackageAdmin = this.packageAdminTracker.getService.asInstanceOf[PackageAdmin] + return admin.getBundleType(b) == PackageAdmin.BUNDLE_TYPE_FRAGMENT + } + + + private def installOrUpdateBundle(s: String) { + for (b <- context.getBundles) { + if (b.getLocation.endsWith(s)) { + System.out.println("DirInstaller: Updating bundle [" + b.getSymbolicName + "]") + b.stop + b.update + return + } + } + System.out.println("DirInstaller: Installing bundle [" + s + "]") + context.installBundle("file:" + s) + } + + +} \ No newline at end of file From c16c6ba7e103117638988d53e6a1d9bcbc92b56e Mon Sep 17 00:00:00 2001 From: Roman Roelofsen Date: Tue, 25 May 2010 15:19:06 +0200 Subject: [PATCH 004/188] changed karaf url --- akka-osgi/karaf/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/akka-osgi/karaf/pom.xml b/akka-osgi/karaf/pom.xml index ffc9dc8697..aaf297a82c 100644 --- a/akka-osgi/karaf/pom.xml +++ b/akka-osgi/karaf/pom.xml @@ -15,8 +15,8 @@ pom - http://www.apache.org/dist/felix/apache-felix-karaf-1.2.0.tar.gz - apache-felix-karaf-1.2.0 + http://www.apache.org/dist/felix/apache-felix-karaf-1.4.0.tar.gz + apache-felix-karaf-1.4.0 From 6911c7629c1757b23ea0fad9744c9b056bf47745 Mon Sep 17 00:00:00 2001 From: Andreas Kollegger Date: Sun, 6 Jun 2010 14:33:10 -0400 Subject: [PATCH 005/188] initial changes for OSGification: added bnd4sbt plugin, changed artifact naming to include _osgi --- project/build/AkkaProject.scala | 42 ++++++++++++++++++++------------ project/build/lib/bnd4sbt.jar | Bin 0 -> 8092 bytes project/plugins/Plugins.scala | 3 ++- 3 files changed, 29 insertions(+), 16 deletions(-) create mode 100644 project/build/lib/bnd4sbt.jar diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 4ad4858d09..3aa43b196d 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -10,6 +10,8 @@ import java.util.jar.Attributes import java.util.jar.Attributes.Name._ import java.io.File +import com.weiglewilczek.bnd4sbt._ + class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------ @@ -25,6 +27,8 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { lazy val deployPath = info.projectPath / "deploy" lazy val distPath = info.projectPath / "dist" + val artifactQualifier = buildScalaVersion + "_osgi" + override def compileOptions = super.compileOptions ++ Seq("-deprecation", "-Xmigration", @@ -36,7 +40,7 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { override def javaCompileOptions = JavaCompileOption("-Xlint:unchecked") :: super.javaCompileOptions.toList - def distName = "%s_%s-%s.zip".format(name, buildScalaVersion, version) + def distName = "%s_%s-%s.zip".format(name, artifactQualifier, version) lazy val dist = zipTask(allArtifacts, "dist", distName) dependsOn (`package`) describedAs("Zips up the distribution.") @@ -109,20 +113,20 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { override def manifestClassPath = Some(allArtifacts.getFiles .filter(_.getName.endsWith(".jar")) .filter(!_.getName.contains("scala-library")) - .map("lib_managed/scala_%s/compile/".format(buildScalaVersion) + _.getName) + .map("lib_managed/scala_%s/compile/".format(artifactQualifier) + _.getName) .mkString(" ") + " scala-library.jar" + - " dist/akka-core_%s-%s.jar".format(buildScalaVersion, version) + - " dist/akka-http_%s-%s.jar".format(buildScalaVersion, version) + - " dist/akka-camel_%s-%s.jar".format(buildScalaVersion, version) + - " dist/akka-amqp_%s-%s.jar".format(buildScalaVersion, version) + - " dist/akka-persistence-common_%s-%s.jar".format(buildScalaVersion, version) + - " dist/akka-persistence-redis_%s-%s.jar".format(buildScalaVersion, version) + - " dist/akka-persistence-mongo_%s-%s.jar".format(buildScalaVersion, version) + - " dist/akka-persistence-cassandra_%s-%s.jar".format(buildScalaVersion, version) + - " dist/akka-kernel_%s-%s.jar".format(buildScalaVersion, version) + - " dist/akka-spring_%s-%s.jar".format(buildScalaVersion, version) + - " dist/akka-jta_%s-%s.jar".format(buildScalaVersion, version) + " dist/akka-core_%s-%s.jar".format(artifactQualifier, version) + + " dist/akka-http_%s-%s.jar".format(artifactQualifier, version) + + " dist/akka-camel_%s-%s.jar".format(artifactQualifier, version) + + " dist/akka-amqp_%s-%s.jar".format(artifactQualifier, version) + + " dist/akka-persistence-common_%s-%s.jar".format(artifactQualifier, version) + + " dist/akka-persistence-redis_%s-%s.jar".format(artifactQualifier, version) + + " dist/akka-persistence-mongo_%s-%s.jar".format(artifactQualifier, version) + + " dist/akka-persistence-cassandra_%s-%s.jar".format(artifactQualifier, version) + + " dist/akka-kernel_%s-%s.jar".format(artifactQualifier, version) + + " dist/akka-spring_%s-%s.jar".format(artifactQualifier, version) + + " dist/akka-jta_%s-%s.jar".format(artifactQualifier, version) ) //Exclude slf4j1.5.11 from the classpath, it's conflicting... @@ -398,12 +402,14 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { } def akkaArtifacts = { - descendents(info.projectPath / "dist", "*" + buildScalaVersion + "-" + version + ".jar") + descendents(info.projectPath / "dist", "*" + artifactQualifier + "-" + version + ".jar") } // ------------------------------------------------------------ - class AkkaDefaultProject(info: ProjectInfo, val deployPath: Path) extends DefaultProject(info) with DeployProject + class AkkaDefaultProject(info: ProjectInfo, val deployPath: Path) extends DefaultProject(info) with DeployProject with OSGiProject + + trait DeployProject extends DefaultProject { // defines where the deployTask copies jars to @@ -424,4 +430,10 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { FileUtilities.copyFile(jar, toDir / jar.name, log) } else None } + + trait OSGiProject extends DefaultProject with BNDPlugin { + override def bndExportPackage = Set("*") + } + + } diff --git a/project/build/lib/bnd4sbt.jar b/project/build/lib/bnd4sbt.jar new file mode 100644 index 0000000000000000000000000000000000000000..5906b493003a67283602179ffdf24d15acdeb0b4 GIT binary patch literal 8092 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 Date: Sun, 6 Jun 2010 20:05:26 -0400 Subject: [PATCH 006/188] initial implementation of OSGiWrapperProject, applied to jgroups dependency to make it OSGi-friendly --- .../src/main/resources/features.xml | 7 +++ project/build/AkkaProject.scala | 51 +++++++++++++++++- project/plugins/.Plugins.scala.swp | Bin 12288 -> 0 bytes 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 akka-karaf/akka-features/src/main/resources/features.xml delete mode 100644 project/plugins/.Plugins.scala.swp diff --git a/akka-karaf/akka-features/src/main/resources/features.xml b/akka-karaf/akka-features/src/main/resources/features.xml new file mode 100644 index 0000000000..9176437f46 --- /dev/null +++ b/akka-karaf/akka-features/src/main/resources/features.xml @@ -0,0 +1,7 @@ + + + + mvn:se.scalablesolutions.akka.akka-wrap/jgroups-wrapper_2.8.0.RC3_osgi/2.9.0.GA + mvn:se.scalablesolutions.akka/akka-core_2.8.0.RC3_osgi/0.9 + + diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 47559ad865..2b96abb597 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -86,6 +86,9 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { // examples lazy val akka_samples = project("akka-samples", "akka-samples", new AkkaSamplesParentProject(_)) + // OSGi wrappers + lazy val akka_wrappers = project("akka-wrap", "akka-wrap", new AkkaWrappersParentProject(_)) + // ------------------------------------------------------------ // Run Akka microkernel using 'sbt run' + use for packaging executable JAR override def mainClass = Some("se.scalablesolutions.akka.kernel.Main") @@ -169,9 +172,28 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { " -Dpackaging=jar -DgeneratePom=true" command ! log } - None + None } dependsOn(dist) describedAs("Run mvn install for artifacts in dist.") + lazy val publishLocalMvnWrapped = runMvnInstallWrapped + def runMvnInstallWrapped = task { + for (absPath <- wrappedArtifacts.getPaths) { + val artifactRE = """.*/([^/]+)-([^-]+).jar""".r + val artifactRE(artifactId, artifactVersion) = absPath + val command = "mvn install:install-file" + + " -Dfile=" + absPath + + " -DgroupId=se.scalablesolutions.akka.akka-wrap" + + " -DartifactId=" + artifactId + + " -Dversion=" + artifactVersion + + " -Dpackaging=jar -DgeneratePom=true" + command ! log + } + None + } dependsOn(`package`) describedAs("Run mvn install for wrapped artifacts in akka-wrap.") + + + + // ------------------------------------------------------------ // subprojects class AkkaCoreProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { @@ -362,6 +384,23 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { new AkkaSampleRemoteProject(_), akka_kernel) } + + // ================= OSGi Wrappers ================== + class JgroupsWrapperProject(info: ProjectInfo) extends OSGiWrapperProject(info) { + override def wrappedVersion = "2.9.0.GA" + override def bndImportPackage = Set("org.testng.*;resolution:=optional", + "org.bouncycastle.jce.provider;resolution:=optional", + "bsh;resolution:=optional", + "*") + + val jgroups = "jgroups" % "jgroups" % wrappedVersion % "compile" + } + + class AkkaWrappersParentProject(info: ProjectInfo) extends ParentProject(info) { + lazy val jgroups_wrapper = project("jgroups-wrapper", "jgroups-wrapper", + new JgroupsWrapperProject(_)) + } + // ------------------------------------------------------------ // helper functions def removeDupEntries(paths: PathFinder) = @@ -390,6 +429,8 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { def akkaArtifacts = descendents(info.projectPath / "dist", "*" + buildScalaVersion + "_osgi-" + version + ".jar") + def wrappedArtifacts = descendents(info.projectPath / "akka-wrap", "*" + buildScalaVersion + "_osgi-" + "*.jar") + // ------------------------------------------------------------ class AkkaDefaultProject(info: ProjectInfo, val deployPath: Path) extends DefaultProject(info) with DeployProject with OSGiProject @@ -419,5 +460,13 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { } + abstract class OSGiWrapperProject(info: ProjectInfo) extends DefaultProject(info) with BNDPlugin { + def wrappedVersion:String + override def version = OpaqueVersion(wrappedVersion) + override def artifactID = moduleID + "_osgi" + override def bndEmbedDependencies = true + override def bndExportPackage = Set("*") + } + } diff --git a/project/plugins/.Plugins.scala.swp b/project/plugins/.Plugins.scala.swp deleted file mode 100644 index 39709506fa92639a4034a394fdcff22edf268002..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmYc?2=nw+FxN9;U|?VnU|?{5&Fv#s_Kdkeijg5PJ3l8UH9bAG2qcLcyCs&CRO3s$Q}1xG_*Gz5@CptK}S*MgV9*vQa8SxHerSSS=( zc9cCD0;3@?8UmvsFd71*Aut*OqaiRF0;3@?0z#mqfRW)p0|NsS0|Nsm0|Nsi6psL} zk9u)51V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qOb8^VFffSoF);Y^LFWHK zV*sD|85lnCGcau6XJAO=XJC-!XJEL-$H36d$G{K>RV&BGz#zuQz`)7Jz`z00J7Pj? z)T5&zFd71*Aut*OqaiRF0;3@?8UmvsFd71*Auz;4pq9Z70u+oal3*MdZ3hxGHAzV{ zPqR!iGq$uyOR-EeO*A$)u`n<*F*Zz0GO;u_H8nM>Wl&HkOUzM7%1bdRPAXBbRZvRK z&($kW%}mcpEzitJu1d{TQczV;f+_&B4fITu6ciZr^&xsQQ&JOQ8q+gNGD?&5atl&( zO7ink^T6thlS*_!igY3C!NFn%dWO2eevSdb9{wRpaHEP+3-UomxqIjqB&MepD}V%) z6cS4mlrl<63as??;U?=rtxC?%)z3{VOU=_)g8HSnASE>z;+N85y^_@AjJ(X`#GIT; zJ&+98b`V1s Date: Mon, 7 Jun 2010 15:59:47 +0200 Subject: [PATCH 007/188] Removed Maven projects and added bnd4sbt --- akka-osgi/akka-dependencies-bundle/pom.xml | 56 -------- akka-osgi/akka-sample-osgi/pom.xml | 49 ------- .../src/main/scala/Activator.scala | 36 ----- .../src/main/scala/Actors.scala | 18 --- akka-osgi/deployer/pom.xml | 46 ------- .../deployer/src/main/scala/Activator.scala | 36 ----- .../deployer/src/main/scala/DirWatcher.scala | 112 --------------- akka-osgi/karaf/pom.xml | 127 ------------------ akka-osgi/karaf/src/main/assembly/runtime.xml | 37 ----- akka-osgi/pom.xml | 45 ------- project/build/AkkaProject.scala | 26 ++++ project/plugins/Plugins.scala | 4 +- 12 files changed, 29 insertions(+), 563 deletions(-) delete mode 100644 akka-osgi/akka-dependencies-bundle/pom.xml delete mode 100644 akka-osgi/akka-sample-osgi/pom.xml delete mode 100644 akka-osgi/akka-sample-osgi/src/main/scala/Activator.scala delete mode 100644 akka-osgi/akka-sample-osgi/src/main/scala/Actors.scala delete mode 100644 akka-osgi/deployer/pom.xml delete mode 100644 akka-osgi/deployer/src/main/scala/Activator.scala delete mode 100644 akka-osgi/deployer/src/main/scala/DirWatcher.scala delete mode 100644 akka-osgi/karaf/pom.xml delete mode 100644 akka-osgi/karaf/src/main/assembly/runtime.xml delete mode 100644 akka-osgi/pom.xml diff --git a/akka-osgi/akka-dependencies-bundle/pom.xml b/akka-osgi/akka-dependencies-bundle/pom.xml deleted file mode 100644 index 74d1792be4..0000000000 --- a/akka-osgi/akka-dependencies-bundle/pom.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - 4.0.0 - - - se.scalablesolutions.akka - akka-osgi-parent - 0.7-SNAPSHOT - - - akka-dependencies-bundle - Akka Dependencies Bundle - - - - akka-kernel - se.scalablesolutions.akka - ${project.version} - - - - - - - org.apache.felix - maven-bundle-plugin - - - - *;resolution:=optional - - - - !test.*, - - - !scala.*, - !org.apache.commons.io.*, - !org.codehaus.jackson.*, - !org.codehaus.jettison.*, - !org.jboss.netty.*, - - - !se.scalablesolutions.akka.*, - - - *;-split-package:=merge-first - - - - - - - - diff --git a/akka-osgi/akka-sample-osgi/pom.xml b/akka-osgi/akka-sample-osgi/pom.xml deleted file mode 100644 index bd48ca2392..0000000000 --- a/akka-osgi/akka-sample-osgi/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - 4.0.0 - - akka-sample-osgi - Akka OSGi Sample Module - - jar - - - akka-osgi-parent - se.scalablesolutions.akka - 0.7-SNAPSHOT - - - - - akka-core - se.scalablesolutions.akka - ${project.version} - - - org.osgi - org.osgi.core - - - org.osgi - org.osgi.compendium - - - - - - - org.apache.felix - maven-bundle-plugin - - - se.scalablesolutions.akka.osgi.sample.Activator - - se.scalablesolutions.akka.osgi.sample - - - - - - - - diff --git a/akka-osgi/akka-sample-osgi/src/main/scala/Activator.scala b/akka-osgi/akka-sample-osgi/src/main/scala/Activator.scala deleted file mode 100644 index 7925a2705f..0000000000 --- a/akka-osgi/akka-sample-osgi/src/main/scala/Activator.scala +++ /dev/null @@ -1,36 +0,0 @@ - -package se.scalablesolutions.akka.osgi.sample - -import org.osgi.framework.{BundleContext, BundleActivator} -import se.scalablesolutions.akka.config.ScalaConfig._ -import se.scalablesolutions.akka.actor.{Supervisor, SupervisorFactory} - -class Activator extends BundleActivator { - - var supervisor: Supervisor = _ - - val ping = new Ping - - def start(context: BundleContext) { - println("Starting Akka OSGi sample") - - supervisor = SupervisorFactory( - SupervisorConfig( - RestartStrategy(OneForOne, 3, 100, List(classOf[Exception])), - Supervise(ping, LifeCycle(Permanent)) :: Nil)).newInstance - - supervisor.start - println("Supervisor: " + supervisor) - - println("Sending ping") - ping send CounterMessage(0) - - } - - def stop(context: BundleContext) { - println("Stopping Akka OSGi sample") - - supervisor.stop - } - -} \ No newline at end of file diff --git a/akka-osgi/akka-sample-osgi/src/main/scala/Actors.scala b/akka-osgi/akka-sample-osgi/src/main/scala/Actors.scala deleted file mode 100644 index 008ea98ef1..0000000000 --- a/akka-osgi/akka-sample-osgi/src/main/scala/Actors.scala +++ /dev/null @@ -1,18 +0,0 @@ - -package se.scalablesolutions.akka.osgi.sample - -import se.scalablesolutions.akka.actor.Actor - -case class CounterMessage(counter: Int) - -class Ping extends Actor { - def receive = { - case CounterMessage(i) => println("Got message " + i) - } -} - -class Pong extends Actor { - def receive = { - case _ => - } -} diff --git a/akka-osgi/deployer/pom.xml b/akka-osgi/deployer/pom.xml deleted file mode 100644 index db35d10dc1..0000000000 --- a/akka-osgi/deployer/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - 4.0.0 - - - se.scalablesolutions.akka - akka-osgi-parent - 0.7-SNAPSHOT - - - akka-deployer - Akka Deployer - - - - org.scala-lang - scala-library - ${scala.version} - - - org.osgi - org.osgi.core - - - org.osgi - org.osgi.compendium - - - - - - - org.apache.felix - maven-bundle-plugin - - - se.scalablesolutions.akka.osgi.deployer.Activator - se.scalablesolutions.akka.osgi.deployer.* - - - - - - - diff --git a/akka-osgi/deployer/src/main/scala/Activator.scala b/akka-osgi/deployer/src/main/scala/Activator.scala deleted file mode 100644 index d12b63ba16..0000000000 --- a/akka-osgi/deployer/src/main/scala/Activator.scala +++ /dev/null @@ -1,36 +0,0 @@ - -package se.scalablesolutions.akka.osgi.deployer - -import org.osgi.framework.{BundleContext, BundleActivator} -import java.io.File - -class Activator extends BundleActivator { - - private val AKKA_DEPLOYER_DIR = "akka.deployer.dir" - private val AKKA_DEPLOYER_POLL = "akka.deployer.poll" - - private var watcher: DirWatcher = _ - - def start(context: BundleContext) { - var bundlesDir = context.getProperty(AKKA_DEPLOYER_DIR) - bundlesDir = if (bundlesDir == null) "akka" else bundlesDir - - // check dir exists - if (new File(bundlesDir).listFiles == null) { - System.out.println("DirInstaller WARNING: Directory '" + bundlesDir + "' does not exist!") - return - } - - var interval = context.getProperty(AKKA_DEPLOYER_POLL) - interval = if (interval == null) "2000" else interval - - watcher = new DirWatcher(context, bundlesDir, interval.toInt) - watcher.startWatching - } - - def stop(context: BundleContext) { - if (watcher != null) - watcher.stopWatching - } - -} diff --git a/akka-osgi/deployer/src/main/scala/DirWatcher.scala b/akka-osgi/deployer/src/main/scala/DirWatcher.scala deleted file mode 100644 index 4d4292604c..0000000000 --- a/akka-osgi/deployer/src/main/scala/DirWatcher.scala +++ /dev/null @@ -1,112 +0,0 @@ - -package se.scalablesolutions.akka.osgi.deployer - -import org.osgi.util.tracker.ServiceTracker -import java.io.File -import org.osgi.service.packageadmin.PackageAdmin -import org.osgi.framework.{Bundle, BundleContext} - -class DirWatcher(context: BundleContext, bundlesDir: String, interval: Int) { - - private var running = false - - private final var timestamps = Map[String, Long]() - - private val packageAdminTracker = new ServiceTracker(context, classOf[PackageAdmin].getName, null) - packageAdminTracker.open - - def startWatching { - if (running) return - running = true - new Thread { - override def run { - try { - while (running) { - val found = getAllFiles(bundlesDir) - analyseNewState(found) - Thread.sleep(interval) - } - } - catch { - case e: InterruptedException => - } - } - }.start() - } - - def stopWatching { - running = false - } - - private def getAllFiles(dirName: String): List[File] = { - val content = new File(dirName).listFiles - val files = content.filter(_.isFile).toList - val childs = content.filter(_.isDirectory).toList.flatMap(d => getAllFiles(d.getCanonicalPath)) - files ::: childs - } - - private def analyseNewState(found: List[File]) { - println("FOUND:" + found) - - // new or updated - val changed = found.filter(f => timestamps.getOrElse(f.getCanonicalPath, -1L) < f.lastModified) - changed.foreach {f => - val name = f.getCanonicalPath - timestamps += (name -> f.lastModified) - if (name.endsWith(".jar")) installOrUpdateBundle(name) - } - println("CHANGED:" + changed) - - // removed - val removed = timestamps.filter(f => !found.map(_.getCanonicalPath).contains(f._1)) - removed.foreach {f => - context.getBundles.filter(b => b.getLocation.equals("file:" + f._1)).foreach(_.uninstall) - timestamps -= f._1 - } - println("REMOVED:" + removed) - - if (changed.size + removed.size > 0) - startAllAndRefresh() - - println("") - } - - private def startAllAndRefresh() { - context.getBundles.filter(b => b.getState != Bundle.ACTIVE && !isFragment(b)).foreach {b => - try { - b.start - } catch { - case e: Exception => { - System.out.println("Problems starting bundle: " + b) - e.printStackTrace - } - } - } - - val admin = this.packageAdminTracker.getService.asInstanceOf[PackageAdmin] - System.out.println("DirInstaller: Refreshing packages") - admin.refreshPackages(null) - } - - - private def isFragment(b: Bundle): Boolean = { - var admin: PackageAdmin = this.packageAdminTracker.getService.asInstanceOf[PackageAdmin] - return admin.getBundleType(b) == PackageAdmin.BUNDLE_TYPE_FRAGMENT - } - - - private def installOrUpdateBundle(s: String) { - for (b <- context.getBundles) { - if (b.getLocation.endsWith(s)) { - System.out.println("DirInstaller: Updating bundle [" + b.getSymbolicName + "]") - b.stop - b.update - return - } - } - System.out.println("DirInstaller: Installing bundle [" + s + "]") - context.installBundle("file:" + s) - } - - -} \ No newline at end of file diff --git a/akka-osgi/karaf/pom.xml b/akka-osgi/karaf/pom.xml deleted file mode 100644 index aaf297a82c..0000000000 --- a/akka-osgi/karaf/pom.xml +++ /dev/null @@ -1,127 +0,0 @@ - - - - 4.0.0 - - - akka-osgi-parent - se.scalablesolutions.akka - 0.7-SNAPSHOT - - - akka-karaf - Akka OSGi Karaf Distribution - pom - - - http://www.apache.org/dist/felix/apache-felix-karaf-1.4.0.tar.gz - apache-felix-karaf-1.4.0 - - - - - - akka-dependencies-bundle - se.scalablesolutions.akka - ${project.version} - - - - - scala-library - org.scala-lang-osgi - 2.7.7 - - - commons-io - commons-io - 1.4 - - - org.codehaus.jackson - jackson-core-asl - 1.2.1 - - - org.codehaus.jackson - jackson-mapper-asl - 1.2.1 - - - org.jboss.netty - netty - 3.2.0.ALPHA3 - - - - - akka-core - se.scalablesolutions.akka - ${project.version} - - - akka-deployer - se.scalablesolutions.akka - ${project.version} - - - akka-sample-osgi - se.scalablesolutions.akka - ${project.version} - - - - - - - org.apache.maven.plugins - maven-antrun-plugin - - generate-resources - generate-resources - - - - - - - - - run - - - - - - maven-assembly-plugin - - - src/main/assembly/runtime.xml - - - - - make-distribution-dir - package - - directory-single - - - - make-distribution-zip - package - - single - - - - - - - - diff --git a/akka-osgi/karaf/src/main/assembly/runtime.xml b/akka-osgi/karaf/src/main/assembly/runtime.xml deleted file mode 100644 index 2fe4ef12cd..0000000000 --- a/akka-osgi/karaf/src/main/assembly/runtime.xml +++ /dev/null @@ -1,37 +0,0 @@ - - runtime - - zip - - false - - - src/main/resources/runtime - - - - target/generated/runtime - - - - - - - se.scalablesolutions.akka:akka-deployer - - ${karaf.root.dir}/akka - false - false - false - - - - se.scalablesolutions.akka:akka-deployer - - ${karaf.root.dir}/deploy - false - false - false - - - diff --git a/akka-osgi/pom.xml b/akka-osgi/pom.xml deleted file mode 100644 index 9748335c9b..0000000000 --- a/akka-osgi/pom.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - 4.0.0 - - - se.scalablesolutions.akka - akka - 0.7-SNAPSHOT - - - akka-osgi-parent - Akka OSGi Parent - - pom - - - 4.2.0 - - - - deployer - akka-dependencies-bundle - akka-sample-osgi - karaf - - - - - - org.osgi - org.osgi.core - ${osgi.version} - provided - - - org.osgi - org.osgi.compendium - ${osgi.version} - provided - - - - - diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index a26396c8e8..d3491f6a3f 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -10,6 +10,8 @@ import java.util.jar.Attributes import java.util.jar.Attributes.Name._ import java.io.File +import com.weiglewilczek.bnd4sbt.BNDPlugin + class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------ @@ -65,6 +67,7 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { lazy val akka_jta = project("akka-jta", "akka-jta", new AkkaJTAProject(_), akka_core) lazy val akka_kernel = project("akka-kernel", "akka-kernel", new AkkaKernelProject(_), akka_core, akka_http, akka_spring, akka_camel, akka_persistence, akka_amqp) + lazy val akka_osgi = project("akka-osgi", "akka-osgi", new AkkaOSGiParentProject(_)) // functional tests in java lazy val akka_fun_test = project("akka-fun-test-java", "akka-fun-test-java", new AkkaFunTestProject(_), akka_kernel) @@ -273,6 +276,29 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { val jta_spec = "org.apache.geronimo.specs" % "geronimo-jta_1.1_spec" % "1.1.1" % "compile" } + // ================= OSGi Packaging ================== + class AkkaOSGiBundleProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with BNDPlugin { + override def bndClasspath = compileClasspath + override def bndPrivatePackage = Set("") + override def bndExportPackage = Set("se.scalablesolutions.akka.*;version=0.9") + } + + class AkkaOSGiAssemblyProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { + // FIXME: Find out how to replace mvn-assembly within SBT + + //override def packageAction = task { + //FileUtilities.copy(info.dependencies.map(_.outputPath), "XXX", true, true, log) + //None + //} dependsOn(compile) describedAs("Creates the OSGi distribution.") + } + + class AkkaOSGiParentProject(info: ProjectInfo) extends ParentProject(info) { + lazy val akka_osgi_bundle = project("akka-osgi-bundle", "akka-osgi-bundle", + new AkkaOSGiBundleProject(_), akka_kernel) + lazy val akka_osgi_assembly = project("akka-osgi-assembly", "akka-osgi-assembly", + new AkkaOSGiAssemblyProject(_), akka_osgi_bundle) + } + // ================= TEST ================== class AkkaFunTestProject(info: ProjectInfo) extends DefaultProject(info) { val jackson_core_asl = "org.codehaus.jackson" % "jackson-core-asl" % "1.2.1" % "compile" diff --git a/project/plugins/Plugins.scala b/project/plugins/Plugins.scala index f36c65ed13..895df56970 100644 --- a/project/plugins/Plugins.scala +++ b/project/plugins/Plugins.scala @@ -5,4 +5,6 @@ class Plugins(info: ProjectInfo) extends PluginDefinition(info) { val spdeSbt = "us.technically.spde" % "spde-sbt-plugin" % "0.4.1" // val repo = "GH-pages repo" at "http://mpeltonen.github.com/maven/" // val idea = "com.github.mpeltonen" % "sbt-idea-plugin" % "0.1-SNAPSHOT" -} \ No newline at end of file + + lazy val bnd4sbt = "com.weiglewilczek" % "bnd4sbt" % "0.4" +} From c7c54559662531524ae025630fe25ed9aecf18fc Mon Sep 17 00:00:00 2001 From: Roman Roelofsen Date: Mon, 7 Jun 2010 16:28:19 +0200 Subject: [PATCH 008/188] Added dependencies-bundle. --- project/build/AkkaProject.scala | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index c5dbec2f30..945cd2491f 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -302,6 +302,13 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { override def bndExportPackage = Set("se.scalablesolutions.akka.*;version=0.9") } + class AkkaOSGiDependenciesBundleProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with BNDPlugin { + override def bndClasspath = compileClasspath + override def bndPrivatePackage = Set("") + override def bndImportPackage = Set("*;resolution:=optional") + override def bndExportPackage = Set("!se.scalablesolutions.akka.*", "*") + } + class AkkaOSGiAssemblyProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { // FIXME: Find out how to replace mvn-assembly within SBT @@ -314,6 +321,8 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { class AkkaOSGiParentProject(info: ProjectInfo) extends ParentProject(info) { lazy val akka_osgi_bundle = project("akka-osgi-bundle", "akka-osgi-bundle", new AkkaOSGiBundleProject(_), akka_kernel) + lazy val akka_osgi_dependencies_bundle = project("akka-osgi-dependencies-bundle", "akka-osgi-dependencies-bundle", + new AkkaOSGiDependenciesBundleProject(_), akka_kernel) lazy val akka_osgi_assembly = project("akka-osgi-assembly", "akka-osgi-assembly", new AkkaOSGiAssemblyProject(_), akka_osgi_bundle) } From db2dd5735044f9eb18c3ec86d9888ec957bd2a8e Mon Sep 17 00:00:00 2001 From: Roman Roelofsen Date: Mon, 7 Jun 2010 16:46:49 +0200 Subject: [PATCH 009/188] Removed some dependencies since they will be provided by their own bundles --- project/build/AkkaProject.scala | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 945cd2491f..3b8bdf44da 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -306,7 +306,18 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { override def bndClasspath = compileClasspath override def bndPrivatePackage = Set("") override def bndImportPackage = Set("*;resolution:=optional") - override def bndExportPackage = Set("!se.scalablesolutions.akka.*", "*") + override def bndExportPackage = Set( + // Provided by Akka bundle + "!se.scalablesolutions.akka.*", + + // Provided by other bundles + "!org.apache.commons.io.*", + "!org.codehaus.jackson.*", + "!org.codehaus.jettison.*", + "!org.jboss.netty.*", + + // Export the rest + "*") } class AkkaOSGiAssemblyProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { From 1a4267612d0272962094b67e775b88eb8db1eba2 Mon Sep 17 00:00:00 2001 From: Roman Roelofsen Date: Mon, 7 Jun 2010 17:36:11 +0200 Subject: [PATCH 010/188] Work in progress! Trying to find an alternative to mvn assembly --- project/build/AkkaProject.scala | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 3b8bdf44da..706e0573ac 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -323,19 +323,24 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { class AkkaOSGiAssemblyProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { // FIXME: Find out how to replace mvn-assembly within SBT - //override def packageAction = task { - //FileUtilities.copy(info.dependencies.map(_.outputPath), "XXX", true, true, log) - //None - //} dependsOn(compile) describedAs("Creates the OSGi distribution.") + override def packageAction = task { + + println("----------------------------") + println("2" + unmanagedClasspath) + + + //FileUtilities.copy(info.dependencies.map(_.outputPath), "bundles", true, true, log) + None + } //dependsOn(compile) describedAs("Creates the OSGi distribution.") } class AkkaOSGiParentProject(info: ProjectInfo) extends ParentProject(info) { lazy val akka_osgi_bundle = project("akka-osgi-bundle", "akka-osgi-bundle", new AkkaOSGiBundleProject(_), akka_kernel) lazy val akka_osgi_dependencies_bundle = project("akka-osgi-dependencies-bundle", "akka-osgi-dependencies-bundle", - new AkkaOSGiDependenciesBundleProject(_), akka_kernel) + new AkkaOSGiDependenciesBundleProject(_), akka_osgi_bundle) lazy val akka_osgi_assembly = project("akka-osgi-assembly", "akka-osgi-assembly", - new AkkaOSGiAssemblyProject(_), akka_osgi_bundle) + new AkkaOSGiAssemblyProject(_), akka_osgi_bundle, akka_osgi_dependencies_bundle) } // ================= TEST ================== From 94b87cff58b52c51b94e0f293fe3eb32df2f301a Mon Sep 17 00:00:00 2001 From: Roman Roelofsen Date: Tue, 8 Jun 2010 10:36:41 +0200 Subject: [PATCH 011/188] Use more idiomatic way to add the assembly task --- project/build/AkkaProject.scala | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 706e0573ac..98441a44e1 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -323,15 +323,17 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { class AkkaOSGiAssemblyProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { // FIXME: Find out how to replace mvn-assembly within SBT - override def packageAction = task { + lazy val assemblyAction = task { println("----------------------------") println("2" + unmanagedClasspath) - //FileUtilities.copy(info.dependencies.map(_.outputPath), "bundles", true, true, log) None - } //dependsOn(compile) describedAs("Creates the OSGi distribution.") + } + + override def packageAction = super.packageAction dependsOn(assemblyAction) + } class AkkaOSGiParentProject(info: ProjectInfo) extends ParentProject(info) { From f8240a24364486527040639a03e3142098fee0a6 Mon Sep 17 00:00:00 2001 From: Andreas Kollegger Date: Tue, 8 Jun 2010 22:57:55 -0400 Subject: [PATCH 012/188] pulled wrappers into AkkaWrapperProject trait file; sjson, objenesis, dispatch-json, netty ok; multiverse is next --- .../src/main/resources/features.xml | 15 ++++ project/build/AkkaProject.scala | 52 +----------- project/build/AkkaWrappersProject.scala | 81 +++++++++++++++++++ 3 files changed, 97 insertions(+), 51 deletions(-) create mode 100644 project/build/AkkaWrappersProject.scala diff --git a/akka-karaf/akka-features/src/main/resources/features.xml b/akka-karaf/akka-features/src/main/resources/features.xml index 9176437f46..7506820024 100644 --- a/akka-karaf/akka-features/src/main/resources/features.xml +++ b/akka-karaf/akka-features/src/main/resources/features.xml @@ -1,7 +1,22 @@ + + + mvn:com.weiglewilczek.scala-lang-osgi/scala-library/2.8.0.RC2 + mvn:org.eclipse.scalamodules/scalamodules-core/2.0-M2 + + + + + mvn:se.scalablesolutions.akka.akka-wrap/dispatch-json_2.8.0.RC3_osgi/0.7.4 + mvn:org.objenesis/objenesis/1.2 + mvn:sjson.json/sjson/0.6-SNAPSHOT + + + sjson mvn:se.scalablesolutions.akka.akka-wrap/jgroups-wrapper_2.8.0.RC3_osgi/2.9.0.GA + mvn:org.jboss.netty/netty/3.2.0.CR1 mvn:se.scalablesolutions.akka/akka-core_2.8.0.RC3_osgi/0.9 diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 2b96abb597..90e9a3124e 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -12,7 +12,7 @@ import java.io.File import com.weiglewilczek.bnd4sbt._ -class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { +class AkkaParent(info: ProjectInfo) extends DefaultProject(info) with AkkaWrappersProject { // ------------------------------------------------------------ // project versions @@ -86,9 +86,6 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { // examples lazy val akka_samples = project("akka-samples", "akka-samples", new AkkaSamplesParentProject(_)) - // OSGi wrappers - lazy val akka_wrappers = project("akka-wrap", "akka-wrap", new AkkaWrappersParentProject(_)) - // ------------------------------------------------------------ // Run Akka microkernel using 'sbt run' + use for packaging executable JAR override def mainClass = Some("se.scalablesolutions.akka.kernel.Main") @@ -175,25 +172,6 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { None } dependsOn(dist) describedAs("Run mvn install for artifacts in dist.") - lazy val publishLocalMvnWrapped = runMvnInstallWrapped - def runMvnInstallWrapped = task { - for (absPath <- wrappedArtifacts.getPaths) { - val artifactRE = """.*/([^/]+)-([^-]+).jar""".r - val artifactRE(artifactId, artifactVersion) = absPath - val command = "mvn install:install-file" + - " -Dfile=" + absPath + - " -DgroupId=se.scalablesolutions.akka.akka-wrap" + - " -DartifactId=" + artifactId + - " -Dversion=" + artifactVersion + - " -Dpackaging=jar -DgeneratePom=true" - command ! log - } - None - } dependsOn(`package`) describedAs("Run mvn install for wrapped artifacts in akka-wrap.") - - - - // ------------------------------------------------------------ // subprojects class AkkaCoreProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { @@ -384,23 +362,6 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { new AkkaSampleRemoteProject(_), akka_kernel) } - - // ================= OSGi Wrappers ================== - class JgroupsWrapperProject(info: ProjectInfo) extends OSGiWrapperProject(info) { - override def wrappedVersion = "2.9.0.GA" - override def bndImportPackage = Set("org.testng.*;resolution:=optional", - "org.bouncycastle.jce.provider;resolution:=optional", - "bsh;resolution:=optional", - "*") - - val jgroups = "jgroups" % "jgroups" % wrappedVersion % "compile" - } - - class AkkaWrappersParentProject(info: ProjectInfo) extends ParentProject(info) { - lazy val jgroups_wrapper = project("jgroups-wrapper", "jgroups-wrapper", - new JgroupsWrapperProject(_)) - } - // ------------------------------------------------------------ // helper functions def removeDupEntries(paths: PathFinder) = @@ -429,8 +390,6 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { def akkaArtifacts = descendents(info.projectPath / "dist", "*" + buildScalaVersion + "_osgi-" + version + ".jar") - def wrappedArtifacts = descendents(info.projectPath / "akka-wrap", "*" + buildScalaVersion + "_osgi-" + "*.jar") - // ------------------------------------------------------------ class AkkaDefaultProject(info: ProjectInfo, val deployPath: Path) extends DefaultProject(info) with DeployProject with OSGiProject @@ -460,13 +419,4 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { } - abstract class OSGiWrapperProject(info: ProjectInfo) extends DefaultProject(info) with BNDPlugin { - def wrappedVersion:String - override def version = OpaqueVersion(wrappedVersion) - override def artifactID = moduleID + "_osgi" - override def bndEmbedDependencies = true - override def bndExportPackage = Set("*") - } - - } diff --git a/project/build/AkkaWrappersProject.scala b/project/build/AkkaWrappersProject.scala new file mode 100644 index 0000000000..5826ee4d55 --- /dev/null +++ b/project/build/AkkaWrappersProject.scala @@ -0,0 +1,81 @@ + /*---------------------------------------------------------------------------\ +| Copyright (C) 2009-2010 Scalable Solutions AB | +\---------------------------------------------------------------------------*/ + +import sbt._ +import sbt.CompileOrder._ +import spde._ + +import java.util.jar.Attributes +import java.util.jar.Attributes.Name._ +import java.io.File + +import com.weiglewilczek.bnd4sbt._ + +trait AkkaWrappersProject extends DefaultProject { + + // ------------------------------------------------------------ + // project versions + val JERSEY_VERSION:String + val ATMO_VERSION:String + val CASSANDRA_VERSION:String + val LIFT_VERSION:String + val SCALATEST_VERSION:String + val MULTIVERSE_VERSION:String + + // OSGi wrappers + lazy val akka_wrappers = project("akka-wrap", "akka-wrap", new AkkaWrappersParentProject(_)) + + import Process._ + lazy val publishLocalMvnWrapped = runMvnInstallWrapped + def runMvnInstallWrapped = task { + for (absPath <- wrappedArtifacts.getPaths) { + val artifactRE = """.*/([^/]+)-([^-]+).jar""".r + val artifactRE(artifactId, artifactVersion) = absPath + val command = "mvn install:install-file" + + " -Dfile=" + absPath + + " -DgroupId=se.scalablesolutions.akka.akka-wrap" + + " -DartifactId=" + artifactId + + " -Dversion=" + artifactVersion + + " -Dpackaging=jar -DgeneratePom=true" + command ! log + } + None + } dependsOn(`package`) describedAs("Run mvn install for wrapped artifacts in akka-wrap.") + + // ================= OSGi Wrappers ================== + class JgroupsWrapperProject(info: ProjectInfo) extends OSGiWrapperProject(info) { + override def wrappedVersion = "2.9.0.GA" + override def bndImportPackage = Set("org.testng.*;resolution:=optional", + "org.bouncycastle.jce.provider;resolution:=optional", + "bsh;resolution:=optional", + "*") + + val jgroups = "jgroups" % "jgroups" % wrappedVersion % "compile" + } + + class DispatchJsonWrapperProject(info: ProjectInfo) extends OSGiWrapperProject(info) { + override def wrappedVersion = "0.7.4" + + val dispatch_json = "net.databinder" % "dispatch-json_2.8.0.RC3" % wrappedVersion % "compile" + } + + class AkkaWrappersParentProject(info: ProjectInfo) extends ParentProject(info) { + lazy val jgroups_wrapper = project("jgroups-wrapper", "jgroups-wrapper", + new JgroupsWrapperProject(_)) + lazy val dispath_json = project("dispatch-json", "dispatch-json", + new DispatchJsonWrapperProject(_)) + } + + def wrappedArtifacts = descendents(info.projectPath / "akka-wrap", "*" + buildScalaVersion + "_osgi-" + "*.jar") + + abstract class OSGiWrapperProject(info: ProjectInfo) extends DefaultProject(info) with BNDPlugin { + def wrappedVersion:String + override def version = OpaqueVersion(wrappedVersion) + override def artifactID = moduleID + "_osgi" + override def bndEmbedDependencies = true + override def bndExportPackage = Set("*") + } + + +} From a3baa7b95b1432b5306000c97764f4c325c19c27 Mon Sep 17 00:00:00 2001 From: Roman Roelofsen Date: Wed, 16 Jun 2010 00:50:52 +0200 Subject: [PATCH 013/188] Basic OSGi stuff working. Need to exclude transitive dependencies from the bundle list. --- project/build/AkkaProject.scala | 39 +++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 98441a44e1..6f5002d543 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -311,29 +311,46 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { "!se.scalablesolutions.akka.*", // Provided by other bundles + "!com.google.inject.*", + "!javax.transaction.*", + "!javax.ws.rs.*", + "!net.liftweb.common.*", + "!net.liftweb.util.*", + "!org.apache.camel.*", "!org.apache.commons.io.*", + "!org.apache.commons.pool.*", "!org.codehaus.jackson.*", - "!org.codehaus.jettison.*", "!org.jboss.netty.*", + "!org.springframework.*", // Export the rest "*") } - class AkkaOSGiAssemblyProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { - // FIXME: Find out how to replace mvn-assembly within SBT + class AkkaOSGiAssemblyProject(info: ProjectInfo) extends DefaultProject(info) { - lazy val assemblyAction = task { - - println("----------------------------") - println("2" + unmanagedClasspath) + // FIXME: Transitive dependencies should not be included, we should list every bundle individually - //FileUtilities.copy(info.dependencies.map(_.outputPath), "bundles", true, true, log) + val guicey = "org.guiceyfruit" % "guice-all" % "2.0" % "compile" + val commons_io = "commons-io" % "commons-io" % "1.4" % "compile" + val jta_1_1 = "org.apache.geronimo.specs" % "geronimo-jta_1.1_spec" % "1.1.1" % "compile" + val jsr311 = "javax.ws.rs" % "jsr311-api" % "1.1" % "compile" + val lift_common = "net.liftweb" % "lift-common" % LIFT_VERSION % "compile" + val lift_util = "net.liftweb" % "lift-util" % LIFT_VERSION % "compile" + val camel_core = "org.apache.camel" % "camel-core" % "2.3.0" % "compile" + val commons_pool = "commons-pool" % "commons-pool" % "1.5.4" % "compile" + val jackson = "org.codehaus.jackson" % "jackson-mapper-asl" % "1.2.1" % "compile" + val netty = "org.jboss.netty" % "netty" % "3.2.0.CR1" % "compile" + val spring_beans = "org.springframework" % "spring-beans" % "3.0.1.RELEASE" % "compile" + val spring_context = "org.springframework" % "spring-context" % "3.0.1.RELEASE" % "compile" + + override def packageAction = task { + val libs: Seq[Path] = managedClasspath(config("compile")).get.toSeq + val prjs: Seq[Path] = info.dependencies.toSeq.asInstanceOf[Seq[DefaultProject]].map(_.jarPath) + val all = libs ++ prjs + FileUtilities.copyFlat(all, outputPath / "bundles", log) None } - - override def packageAction = super.packageAction dependsOn(assemblyAction) - } class AkkaOSGiParentProject(info: ProjectInfo) extends ParentProject(info) { From 6410473bd93b66c956b2853bd4a6b28d9439b3de Mon Sep 17 00:00:00 2001 From: Roman Roelofsen Date: Wed, 16 Jun 2010 11:55:25 +0200 Subject: [PATCH 014/188] Updated bnd4sbt plugin --- project/plugins/Plugins.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins/Plugins.scala b/project/plugins/Plugins.scala index 895df56970..a133f55757 100644 --- a/project/plugins/Plugins.scala +++ b/project/plugins/Plugins.scala @@ -6,5 +6,5 @@ class Plugins(info: ProjectInfo) extends PluginDefinition(info) { // val repo = "GH-pages repo" at "http://mpeltonen.github.com/maven/" // val idea = "com.github.mpeltonen" % "sbt-idea-plugin" % "0.1-SNAPSHOT" - lazy val bnd4sbt = "com.weiglewilczek" % "bnd4sbt" % "0.4" + lazy val bnd4sbt = "com.weiglewilczek.bnd4sbt" % "bnd4sbt" % "1.0.0.RC1" } From 1936695a9f0ea43eddc45addafd34e66fb5b4afa Mon Sep 17 00:00:00 2001 From: Roman Roelofsen Date: Wed, 16 Jun 2010 11:55:57 +0200 Subject: [PATCH 015/188] Exclude transitive dependencies Ongoing work on finding the bundle list --- project/build/AkkaProject.scala | 50 ++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 3eba7ef4a5..3ddc872cc6 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -67,6 +67,7 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { val grizzlyModuleConfig = ModuleConfiguration("com.sun.grizzly", javaNetRepo) // val atmosphereModuleConfig = ModuleConfiguration("org.atmosphere", sonatypeSnapshotRepo) val liftModuleConfig = ModuleConfiguration("net.liftweb", ScalaToolsSnapshots) + val scalaBundleConfig = ModuleConfiguration("com.weiglewilczek.scala-lang-osgi", ScalaToolsReleases) // ------------------------------------------------------------ // project defintions @@ -308,42 +309,51 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { override def bndPrivatePackage = Set("") override def bndImportPackage = Set("*;resolution:=optional") override def bndExportPackage = Set( - // Provided by Akka bundle - "!se.scalablesolutions.akka.*", + "org.aopalliance.*;version=1.0.0", // Provided by other bundles + "!se.scalablesolutions.akka.*", "!com.google.inject.*", "!javax.transaction.*", "!javax.ws.rs.*", - "!net.liftweb.common.*", - "!net.liftweb.util.*", - "!org.apache.camel.*", "!org.apache.commons.io.*", "!org.apache.commons.pool.*", "!org.codehaus.jackson.*", "!org.jboss.netty.*", "!org.springframework.*", + "!org.apache.camel.*", + "!org.fusesource.commons.management.*", - // Export the rest - "*") + "*;version=0.0.0") } class AkkaOSGiAssemblyProject(info: ProjectInfo) extends DefaultProject(info) { - // FIXME: Transitive dependencies should not be included, we should list every bundle individually + // Scala bundle + val scala_bundle = "com.weiglewilczek.scala-lang-osgi" % "scala-library_2.8.0.RC3" % "1.0" % "compile" intransitive() - val guicey = "org.guiceyfruit" % "guice-all" % "2.0" % "compile" - val commons_io = "commons-io" % "commons-io" % "1.4" % "compile" - val jta_1_1 = "org.apache.geronimo.specs" % "geronimo-jta_1.1_spec" % "1.1.1" % "compile" - val jsr311 = "javax.ws.rs" % "jsr311-api" % "1.1" % "compile" - val lift_common = "net.liftweb" % "lift-common" % LIFT_VERSION % "compile" - val lift_util = "net.liftweb" % "lift-util" % LIFT_VERSION % "compile" - val camel_core = "org.apache.camel" % "camel-core" % "2.3.0" % "compile" - val commons_pool = "commons-pool" % "commons-pool" % "1.5.4" % "compile" - val jackson = "org.codehaus.jackson" % "jackson-mapper-asl" % "1.2.1" % "compile" - val netty = "org.jboss.netty" % "netty" % "3.2.0.CR1" % "compile" - val spring_beans = "org.springframework" % "spring-beans" % "3.0.1.RELEASE" % "compile" - val spring_context = "org.springframework" % "spring-context" % "3.0.1.RELEASE" % "compile" + // Camel bundles + val camel_core = "org.apache.camel" % "camel-core" % "2.3.0" % "compile" intransitive() + val fusesource_commonman = "org.fusesource.commonman" % "commons-management" % "1.0" intransitive() + + // Spring bundles + val spring_beans = "org.springframework" % "spring-beans" % "3.0.1.RELEASE" % "compile" intransitive() + val spring_context = "org.springframework" % "spring-context" % "3.0.1.RELEASE" % "compile" intransitive() + val spring_jms = "org.springframework" % "spring-jms" % "3.0.1.RELEASE" % "compile" intransitive() + val spring_aop = "org.springframework" % "spring-aop" % "3.0.1.RELEASE" % "compile" intransitive() + val spring_asm = "org.springframework" % "spring-asm" % "3.0.1.RELEASE" % "compile" intransitive() + val spring_core = "org.springframework" % "spring-core" % "3.0.1.RELEASE" % "compile" intransitive() + val spring_expression = "org.springframework" % "spring-expression" % "3.0.1.RELEASE" % "compile" intransitive() + val spring_tx = "org.springframework" % "spring-tx" % "3.0.1.RELEASE" % "compile" intransitive() + + val commons_io = "commons-io" % "commons-io" % "1.4" % "compile" intransitive() + val commons_pool = "commons-pool" % "commons-pool" % "1.5.4" % "compile" intransitive() + val jackson_core = "org.codehaus.jackson" % "jackson-core-asl" % "1.2.1" % "compile" intransitive() + val jackson = "org.codehaus.jackson" % "jackson-mapper-asl" % "1.2.1" % "compile" intransitive() + val netty = "org.jboss.netty" % "netty" % "3.2.0.CR1" % "compile" intransitive() + val guicey = "org.guiceyfruit" % "guice-all" % "2.0" % "compile" intransitive() + val jta_1_1 = "org.apache.geronimo.specs" % "geronimo-jta_1.1_spec" % "1.1.1" % "compile" intransitive() + val jsr311 = "javax.ws.rs" % "jsr311-api" % "1.1" % "compile" intransitive() override def packageAction = task { val libs: Seq[Path] = managedClasspath(config("compile")).get.toSeq From 36c830ccfc07f99a72249cb80b52c41491219ecd Mon Sep 17 00:00:00 2001 From: Roman Roelofsen Date: Thu, 17 Jun 2010 14:19:33 +0200 Subject: [PATCH 016/188] All bundles resolve! --- project/build/AkkaProject.scala | 42 +++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 3ddc872cc6..1c7170a078 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -300,22 +300,25 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { // ================= OSGi Packaging ================== class AkkaOSGiBundleProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with BNDPlugin { override def bndClasspath = compileClasspath - override def bndPrivatePackage = Set("") - override def bndExportPackage = Set("se.scalablesolutions.akka.*;version=0.9") + override def bndPrivatePackage = Seq("") + override def bndExportPackage = Seq("se.scalablesolutions.akka.*;version=0.9") } class AkkaOSGiDependenciesBundleProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with BNDPlugin { override def bndClasspath = compileClasspath - override def bndPrivatePackage = Set("") - override def bndImportPackage = Set("*;resolution:=optional") - override def bndExportPackage = Set( + override def bndPrivatePackage = Seq("") + override def bndImportPackage = Seq("*;resolution:=optional") + override def bndExportPackage = Seq( "org.aopalliance.*;version=1.0.0", // Provided by other bundles "!se.scalablesolutions.akka.*", + "!net.liftweb.*", "!com.google.inject.*", "!javax.transaction.*", "!javax.ws.rs.*", + "!javax.jms.*", + "!javax.transaction,*", "!org.apache.commons.io.*", "!org.apache.commons.pool.*", "!org.codehaus.jackson.*", @@ -332,27 +335,40 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { // Scala bundle val scala_bundle = "com.weiglewilczek.scala-lang-osgi" % "scala-library_2.8.0.RC3" % "1.0" % "compile" intransitive() + // Lift bundles + val lift_actor = "net.liftweb" % "lift-actor" % LIFT_VERSION % "compile" intransitive() + val lift_common = "net.liftweb" % "lift-common" % LIFT_VERSION % "compile" intransitive() + val lift_json = "net.liftweb" % "lift-json" % LIFT_VERSION % "compile" intransitive() + val lift_util = "net.liftweb" % "lift-util" % LIFT_VERSION % "compile" intransitive() + //val lift_webkit = "net.liftweb" % "lift-webkit" % LIFT_VERSION % "compile" intransitive() + //val lift_testkit = "net.liftweb" % "lift-testkit" % LIFT_VERSION % "compile" intransitive() + // Camel bundles val camel_core = "org.apache.camel" % "camel-core" % "2.3.0" % "compile" intransitive() val fusesource_commonman = "org.fusesource.commonman" % "commons-management" % "1.0" intransitive() // Spring bundles - val spring_beans = "org.springframework" % "spring-beans" % "3.0.1.RELEASE" % "compile" intransitive() - val spring_context = "org.springframework" % "spring-context" % "3.0.1.RELEASE" % "compile" intransitive() - val spring_jms = "org.springframework" % "spring-jms" % "3.0.1.RELEASE" % "compile" intransitive() - val spring_aop = "org.springframework" % "spring-aop" % "3.0.1.RELEASE" % "compile" intransitive() - val spring_asm = "org.springframework" % "spring-asm" % "3.0.1.RELEASE" % "compile" intransitive() - val spring_core = "org.springframework" % "spring-core" % "3.0.1.RELEASE" % "compile" intransitive() - val spring_expression = "org.springframework" % "spring-expression" % "3.0.1.RELEASE" % "compile" intransitive() - val spring_tx = "org.springframework" % "spring-tx" % "3.0.1.RELEASE" % "compile" intransitive() + val spring_beans = "org.springframework" % "spring-beans" % "3.0.2.RELEASE" % "compile" intransitive() + val spring_context = "org.springframework" % "spring-context" % "3.0.2.RELEASE" % "compile" intransitive() + val spring_jms = "org.springframework" % "spring-jms" % "3.0.2.RELEASE" % "compile" intransitive() + val spring_aop = "org.springframework" % "spring-aop" % "3.0.2.RELEASE" % "compile" intransitive() + val spring_asm = "org.springframework" % "spring-asm" % "3.0.2.RELEASE" % "compile" intransitive() + val spring_core = "org.springframework" % "spring-core" % "3.0.2.RELEASE" % "compile" intransitive() + val spring_expression = "org.springframework" % "spring-expression" % "3.0.2.RELEASE" % "compile" intransitive() + val spring_tx = "org.springframework" % "spring-tx" % "3.0.2.RELEASE" % "compile" intransitive() val commons_io = "commons-io" % "commons-io" % "1.4" % "compile" intransitive() val commons_pool = "commons-pool" % "commons-pool" % "1.5.4" % "compile" intransitive() + val commons_codec = "commons-codec" % "commons-codec" % "1.4" % "compile" intransitive() + val commons_fileupload = "commons-fileupload" % "commons-fileupload" % "1.2.1" % "compile" intransitive() val jackson_core = "org.codehaus.jackson" % "jackson-core-asl" % "1.2.1" % "compile" intransitive() val jackson = "org.codehaus.jackson" % "jackson-mapper-asl" % "1.2.1" % "compile" intransitive() val netty = "org.jboss.netty" % "netty" % "3.2.0.CR1" % "compile" intransitive() val guicey = "org.guiceyfruit" % "guice-all" % "2.0" % "compile" intransitive() + val joda = "joda-time" % "joda-time" % "1.6" intransitive() + val jta_1_1 = "org.apache.geronimo.specs" % "geronimo-jta_1.1_spec" % "1.1.1" % "compile" intransitive() + val jms_1_1 = "org.apache.geronimo.specs" % "geronimo-jms_1.1_spec" % "1.1.1" % "compile" intransitive() val jsr311 = "javax.ws.rs" % "jsr311-api" % "1.1" % "compile" intransitive() override def packageAction = task { From 8d6642f0d57d1b39d84d802b332baefdf5596453 Mon Sep 17 00:00:00 2001 From: Roman Roelofsen Date: Thu, 17 Jun 2010 15:10:39 +0200 Subject: [PATCH 017/188] Started work on OSGi sample --- .../src/main/scala/Activator.scala | 26 +++++++++++++++++++ .../src/main/scala/Actor.scala | 12 +++++++++ project/build/AkkaProject.scala | 12 +++++++++ 3 files changed, 50 insertions(+) create mode 100644 akka-samples/akka-sample-osgi/src/main/scala/Activator.scala create mode 100644 akka-samples/akka-sample-osgi/src/main/scala/Actor.scala diff --git a/akka-samples/akka-sample-osgi/src/main/scala/Activator.scala b/akka-samples/akka-sample-osgi/src/main/scala/Activator.scala new file mode 100644 index 0000000000..81e2d25d97 --- /dev/null +++ b/akka-samples/akka-sample-osgi/src/main/scala/Activator.scala @@ -0,0 +1,26 @@ +/** + * Copyright (C) 2009-2010 Scalable Solutions AB + */ + +package sample.osgi + +import org.osgi.framework.{BundleActivator, BundleContext} + + +class Activator extends BundleActivator { + + def start(context: BundleContext) { + println("Start") + val osgiActor = new OSGiActor + osgiActor ! "Hello" + + + + } + + def stop(context: BundleContext) { + println("stop") + } + +} + diff --git a/akka-samples/akka-sample-osgi/src/main/scala/Actor.scala b/akka-samples/akka-sample-osgi/src/main/scala/Actor.scala new file mode 100644 index 0000000000..90bd521d7b --- /dev/null +++ b/akka-samples/akka-sample-osgi/src/main/scala/Actor.scala @@ -0,0 +1,12 @@ +package sample.osgi + +import se.scalablesolutions.akka.actor.Actor + + +class OSGiActor extends Actor { + def receive = { + case msg: String => + println("Got message: " + msg) + } +} + diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 1c7170a078..3742089c55 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -436,6 +436,16 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { val commons_codec = "commons-codec" % "commons-codec" % "1.3" % "compile" } + class AkkaSampleOSGiProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with BNDPlugin { + override def bndClasspath = compileClasspath + + val osgi_core = "org.osgi" % "org.osgi.core" % "4.2.0" + + override def bndBundleActivator = Some("sample.osgi.Activator") + override def bndPrivatePackage = Nil + override def bndExportPackage = Seq("sample.osgi.*;version=0.9") + } + class AkkaSamplesParentProject(info: ProjectInfo) extends ParentProject(info) { lazy val akka_sample_ants = project("akka-sample-ants", "akka-sample-ants", new AkkaSampleAntsProject(_), akka_core) @@ -455,6 +465,8 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { new AkkaSampleSecurityProject(_), akka_kernel) lazy val akka_sample_remote = project("akka-sample-remote", "akka-sample-remote", new AkkaSampleRemoteProject(_), akka_kernel) + lazy val akka_sample_osgi = project("akka-sample-osgi", "akka-sample-osgi", + new AkkaSampleOSGiProject(_), akka_core) } // ------------------------------------------------------------ From b0f12f2b9f9b83faf4019ef1ee4e027551e31aca Mon Sep 17 00:00:00 2001 From: Andreas Kollegger Date: Thu, 17 Jun 2010 12:12:42 -0400 Subject: [PATCH 018/188] synced with jboner/master; decoupled AkkaWrapperProject; bumped bnd4sbt to 1.0.0.RC2 --- project/build/AkkaProject.scala | 9 +++++---- project/build/AkkaWrappersProject.scala | 13 ++++++++++--- project/plugins/Plugins.scala | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 0745dcb08a..ca0da80ee3 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -12,7 +12,7 @@ import java.io.File import com.weiglewilczek.bnd4sbt._ -class AkkaParent(info: ProjectInfo) extends DefaultProject(info) with AkkaWrappersProject { +class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------ // project versions @@ -22,6 +22,7 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) with AkkaWrappe val LIFT_VERSION = "2.0-scala280-SNAPSHOT" val SCALATEST_VERSION = "1.2-for-scala-2.8.0.RC3-SNAPSHOT" val MULTIVERSE_VERSION = "0.5.2" + val COMMONS_CODEC_VERSION = "1.4" // ------------------------------------------------------------ lazy val deployPath = info.projectPath / "deploy" @@ -243,7 +244,7 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) with AkkaWrappe class AkkaRedisProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val redis = "com.redis" % "redisclient" % "2.8.0.RC3-1.4-SNAPSHOT" % "compile" - val commons_codec = "commons-codec" % "commons-codec" % "1.4" % "compile" + val commons_codec = "commons-codec" % "commons-codec" % COMMONS_CODEC_VERSION % "compile" override def testOptions = TestFilter((name: String) => name.endsWith("Test")) :: Nil } @@ -339,7 +340,7 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) with AkkaWrappe class AkkaSampleSecurityProject(info: ProjectInfo) extends AkkaDefaultProject(info, deployPath) { val jsr311 = "javax.ws.rs" % "jsr311-api" % "1.1.1" % "compile" val jsr250 = "javax.annotation" % "jsr250-api" % "1.0" % "compile" - val commons_codec = "commons-codec" % "commons-codec" % "1.3" % "compile" + val commons_codec = "commons-codec" % "commons-codec" % COMMONS_CODEC_VERSION % "compile" } class AkkaSamplesParentProject(info: ProjectInfo) extends ParentProject(info) { @@ -416,7 +417,7 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) with AkkaWrappe trait OSGiProject extends DefaultProject with BNDPlugin { override def artifactID = moduleID + "_osgi" - override def bndExportPackage = Set("*") + override def bndExportPackage = Seq("se.scalablesolutions.akka.*;version=0.9") } diff --git a/project/build/AkkaWrappersProject.scala b/project/build/AkkaWrappersProject.scala index 5826ee4d55..f92e91d191 100644 --- a/project/build/AkkaWrappersProject.scala +++ b/project/build/AkkaWrappersProject.scala @@ -46,7 +46,7 @@ trait AkkaWrappersProject extends DefaultProject { // ================= OSGi Wrappers ================== class JgroupsWrapperProject(info: ProjectInfo) extends OSGiWrapperProject(info) { override def wrappedVersion = "2.9.0.GA" - override def bndImportPackage = Set("org.testng.*;resolution:=optional", + override def bndImportPackage = Seq("org.testng.*;resolution:=optional", "org.bouncycastle.jce.provider;resolution:=optional", "bsh;resolution:=optional", "*") @@ -60,11 +60,19 @@ trait AkkaWrappersProject extends DefaultProject { val dispatch_json = "net.databinder" % "dispatch-json_2.8.0.RC3" % wrappedVersion % "compile" } + class MultiverseWrapperProject(info: ProjectInfo) extends OSGiWrapperProject(info) { + override def wrappedVersion = "0.5.2" + + val multiverse = "org.multiverse" % "multiverse-alpha" % wrappedVersion % "compile" + } + class AkkaWrappersParentProject(info: ProjectInfo) extends ParentProject(info) { lazy val jgroups_wrapper = project("jgroups-wrapper", "jgroups-wrapper", new JgroupsWrapperProject(_)) lazy val dispath_json = project("dispatch-json", "dispatch-json", new DispatchJsonWrapperProject(_)) + lazy val multiverse_wrapper = project("multiverse-wrapper", "multiverse-wrapper", + new MultiverseWrapperProject(_)) } def wrappedArtifacts = descendents(info.projectPath / "akka-wrap", "*" + buildScalaVersion + "_osgi-" + "*.jar") @@ -73,8 +81,7 @@ trait AkkaWrappersProject extends DefaultProject { def wrappedVersion:String override def version = OpaqueVersion(wrappedVersion) override def artifactID = moduleID + "_osgi" - override def bndEmbedDependencies = true - override def bndExportPackage = Set("*") + override def bndExportPackage = Seq("*") } diff --git a/project/plugins/Plugins.scala b/project/plugins/Plugins.scala index 997b1e8e67..ac9ff64e25 100644 --- a/project/plugins/Plugins.scala +++ b/project/plugins/Plugins.scala @@ -5,5 +5,5 @@ class Plugins(info: ProjectInfo) extends PluginDefinition(info) { val spdeSbt = "us.technically.spde" % "spde-sbt-plugin" % "0.4.1" // val repo = "GH-pages repo" at "http://mpeltonen.github.com/maven/" // val idea = "com.github.mpeltonen" % "sbt-idea-plugin" % "0.1-SNAPSHOT" - val bnd4sbt = "com.weiglewilczek" % "bnd4sbt" % "0.4" + val bnd4sbt = "com.weiglewilczek.bnd4sbt" % "bnd4sbt" % "1.0.0.RC2" } From 03b90a16d4d6359fd7e751fc11d49a070a772dc9 Mon Sep 17 00:00:00 2001 From: Heiko Seeberger Date: Mon, 21 Jun 2010 18:40:15 +0200 Subject: [PATCH 019/188] OSGi work: Switched to bnd4sbt 1.0.0.RC3, using projectVersion for exported packages now and fixed a merge bug. --- project/build/AkkaProject.scala | 10 ++-------- project/plugins/Plugins.scala | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index d4f563f1d5..31bd9e9245 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -21,7 +21,6 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { val CASSANDRA_VERSION = "0.6.1" val LIFT_VERSION = "2.0-scala280-SNAPSHOT" val SCALATEST_VERSION = "1.2-for-scala-2.8.0.RC3-SNAPSHOT" - val MULTIVERSE_VERSION = "0.5.2" val COMMONS_CODEC_VERSION = "1.4" val MULTIVERSE_VERSION = "0.6-SNAPSHOT" @@ -69,12 +68,9 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { val grizzlyModuleConfig = ModuleConfiguration("com.sun.grizzly", javaNetRepo) // val atmosphereModuleConfig = ModuleConfiguration("org.atmosphere", sonatypeSnapshotRepo) val liftModuleConfig = ModuleConfiguration("net.liftweb", ScalaToolsSnapshots) -<<<<<<< HEAD - val scalaBundleConfig = ModuleConfiguration("com.weiglewilczek.scala-lang-osgi", ScalaToolsReleases) -======= +// val scalaBundleConfig = ModuleConfiguration("com.weiglewilczek.scala-lang-osgi", ScalaToolsReleases) def codehausSnapshotRepo = "Codehaus Snapshots" at "http://snapshots.repository.codehaus.org" val multiverseModuleConfig = ModuleConfiguration("org.multiverse", codehausSnapshotRepo) ->>>>>>> master // ------------------------------------------------------------ // project defintions @@ -528,8 +524,6 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { trait OSGiProject extends DefaultProject with BNDPlugin { override def artifactID = moduleID + "_osgi" - override def bndExportPackage = Seq("se.scalablesolutions.akka.*;version=0.9") - + override def bndExportPackage = Seq("se.scalablesolutions.akka.*;version=%s".format(projectVersion.value)) } - } diff --git a/project/plugins/Plugins.scala b/project/plugins/Plugins.scala index bee2aec2f2..1efcad620c 100644 --- a/project/plugins/Plugins.scala +++ b/project/plugins/Plugins.scala @@ -6,5 +6,5 @@ class Plugins(info: ProjectInfo) extends PluginDefinition(info) { // val repo = "GH-pages repo" at "http://mpeltonen.github.com/maven/" // val idea = "com.github.mpeltonen" % "sbt-idea-plugin" % "0.1-SNAPSHOT" - val bnd4sbt = "com.weiglewilczek.bnd4sbt" % "bnd4sbt" % "1.0.0.RC2" + val bnd4sbt = "com.weiglewilczek.bnd4sbt" % "bnd4sbt" % "1.0.0.RC3" } From b72b5b40f15a27dde66623f5e218a1def6f1d6ee Mon Sep 17 00:00:00 2001 From: Heiko Seeberger Date: Mon, 21 Jun 2010 22:02:15 +0200 Subject: [PATCH 020/188] OSGi work: Fixed packageAction for AkkaOSGiAssemblyProject (publish-local working now) and reverted to default artifactID (removed superfluous suffix '_osgi'). --- project/build/AkkaProject.scala | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 31bd9e9245..600f075a5f 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -370,12 +370,12 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { val jms_1_1 = "org.apache.geronimo.specs" % "geronimo-jms_1.1_spec" % "1.1.1" % "compile" intransitive() val jsr311 = "javax.ws.rs" % "jsr311-api" % "1.1" % "compile" intransitive() - override def packageAction = task { + override def packageAction = { val libs: Seq[Path] = managedClasspath(config("compile")).get.toSeq val prjs: Seq[Path] = info.dependencies.toSeq.asInstanceOf[Seq[DefaultProject]].map(_.jarPath) val all = libs ++ prjs FileUtilities.copyFlat(all, outputPath / "bundles", log) - None + super.packageAction } } @@ -523,7 +523,6 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { } trait OSGiProject extends DefaultProject with BNDPlugin { - override def artifactID = moduleID + "_osgi" override def bndExportPackage = Seq("se.scalablesolutions.akka.*;version=%s".format(projectVersion.value)) } } From 7dfe392264290295b066e28625fa48e3d2c808d9 Mon Sep 17 00:00:00 2001 From: Heiko Seeberger Date: Mon, 21 Jun 2010 23:29:09 +0200 Subject: [PATCH 021/188] OSGi work: Fixed plugin configuration => Added missing repo and module config for BND. --- project/plugins/Plugins.scala | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/project/plugins/Plugins.scala b/project/plugins/Plugins.scala index 1efcad620c..3abc87270f 100644 --- a/project/plugins/Plugins.scala +++ b/project/plugins/Plugins.scala @@ -1,10 +1,15 @@ import sbt._ class Plugins(info: ProjectInfo) extends PluginDefinition(info) { - val databinderRepo = "Databinder Repository" at "http://databinder.net/repo" - val spdeSbt = "us.technically.spde" % "spde-sbt-plugin" % "0.4.1" // val repo = "GH-pages repo" at "http://mpeltonen.github.com/maven/" // val idea = "com.github.mpeltonen" % "sbt-idea-plugin" % "0.1-SNAPSHOT" - val bnd4sbt = "com.weiglewilczek.bnd4sbt" % "bnd4sbt" % "1.0.0.RC3" + // Repositories: Using module configs to speed up resolution => Repos must be defs! + def aquteRepo = "aQute Maven Repository" at "http://www.aqute.biz/repo" + lazy val aquteModuleConfig = ModuleConfiguration("biz.aQute", aquteRepo) + def databinderRepo = "Databinder Repository" at "http://databinder.net/repo" + lazy val spdeModuleConfig = ModuleConfiguration("us.technically.spde", databinderRepo) + + val bnd4sbt = "com.weiglewilczek.bnd4sbt" % "bnd4sbt" % "1.0.0.RC3" + val spdeSbt = "us.technically.spde" % "spde-sbt-plugin" % "0.4.1" } From e24eb3897bbb19dcaaca5880d246aa90cc986f55 Mon Sep 17 00:00:00 2001 From: Roman Roelofsen Date: Mon, 28 Jun 2010 12:21:56 +0200 Subject: [PATCH 022/188] Removed pom.xml, not needed anymore --- pom.xml | 566 -------------------------------------------------------- 1 file changed, 566 deletions(-) delete mode 100644 pom.xml diff --git a/pom.xml b/pom.xml deleted file mode 100644 index ea7edf729e..0000000000 --- a/pom.xml +++ /dev/null @@ -1,566 +0,0 @@ - - - 4.0.0 - - Akka Project - akka - se.scalablesolutions.akka - 0.7-SNAPSHOT - 2009 - http://akkasource.org - pom - - - Akka implements a unique hybrid of: - * Actors , which gives you: - * Simple and high-level abstractions for concurrency and parallelism. - * Asynchronous, non-blocking and highly performant event-driven programming model. - * Very lightweight event-driven processes (create ~6.5 million actors on 4 G RAM). - * Supervision hierarchies with let-it-crash semantics. For writing highly fault-tolerant systems that never stop, systems that self-heal. - * Software Transactional Memory (STM). (Distributed transactions coming soon). - * Transactors: combine actors and STM into transactional actors. Allows you to compose atomic message flows with automatic rollback and retry. - * Remoting: highly performant distributed actors with remote supervision and error management. - * Cluster membership management. - - Akka also has a set of add-on modules: - * Persistence: A set of pluggable back-end storage modules that works in sync with the STM. - * Cassandra distributed and highly scalable database. - * MongoDB document database. - * Redis data structures database (upcoming) - * REST (JAX-RS): Expose actors as REST services. - * Comet: Expose actors as Comet services. - * Security: Digest and Kerberos based security. - * Microkernel: Run Akka as a stand-alone kernel. - - - - 2.7.7 - UTF-8 - 1.5 - ${maven.compiler.source} - ${project.build.sourceEncoding} - ${project.build.sourceEncoding} - 0.5.2 - 1.1.5 - 1.9.18-i - - - - akka-util-java - akka-util - akka-cluster - akka-core - akka-persistence - akka-rest - akka-comet - akka-amqp - akka-security - akka-patterns - akka-kernel - akka-osgi - akka-fun-test-java - akka-samples - - - - Scalable Solutions AB - http://scalablesolutions.se - - - - - The Apache License, ASL Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0 - - - - - - jboner - Jonas Bonér - +1 - jonas [REMOVE] AT jonasboner DOT com - - Founder - Hacker - Despot - - - - viktorklang - Viktor Klang - +1 - viktor.klang [REMOVE] AT gmail DOT com - - Apostle - - - - - - scm:git:git://github.com/jboner/akka.git - scm:git:git@github.com:jboner/akka.git - http://github.com/jboner/akka - - - - assembla - http://assembla.com/spaces/akka/ - - - - hudson - http://hudson.scala-tools.org/job/akka/ - - - - - - - - - User and Developer Discussion List - http://groups.google.com/group/akka-user - akka-user@googlegroups.com - akka-user+subscribe@googlegroups.com - akka-user+unsubscribe@googlegroups.com - - - - - - project.embedded.module - Project Embedded Repository - file://${env.AKKA_HOME}/embedded-repo - - - repo1.maven - Maven Main Repository - http://repo1.maven.org/maven2 - - - scala-tools-snapshots - Scala-Tools Maven2 Snapshot Repository - http://scala-tools.org/repo-snapshots - - - scala-tools - Scala-Tools Maven2 Repository - http://scala-tools.org/repo-releases - - - lag - Configgy's' Repository - http://www.lag.net/repo - - - multiverse-releases - http://multiverse.googlecode.com/svn/maven-repository/releases - - false - - - - multiverse-snaphosts - http://multiverse.googlecode.com/svn/maven-repository/snapshots - - - maven2-repository.dev.java.net - Java.net Repository for Maven - http://download.java.net/maven/2 - - - java.net - Java.net Legacy Repository for Maven - http://download.java.net/maven/1 - legacy - - - guiceyfruit.release - GuiceyFruit Release Repository - http://guiceyfruit.googlecode.com/svn/repo/releases/ - - false - - - true - - - - guiceyfruit.snapshot - GuiceyFruit Snapshot Repository - http://guiceyfruit.googlecode.com/svn/repo/snapshots/ - - true - - - false - - - - guice-maven - guice maven - http://guice-maven.googlecode.com/svn/trunk - - - google-maven-repository - Google Maven Repository - http://google-maven-repository.googlecode.com/svn/repository/ - - - repository.codehaus.org - Codehaus Maven Repository - http://repository.codehaus.org - - true - - - - repository.jboss.org - JBoss Repository for Maven - http://repository.jboss.org/maven2 - - false - - - - nexus.griddynamics.net - Grid Dynamics Maven Repository - https://nexus.griddynamics.net/nexus/content/groups/public - - false - - - - databinder.net/repo/ - dbDispatch Repository for Maven - http://databinder.net/repo - - false - - - - - - - onejar-maven-plugin.googlecode.com - http://onejar-maven-plugin.googlecode.com/svn/mavenrepo - - - scala-tools.org - Scala-Tools Maven2 Repository - http://scala-tools.org/repo-releases - - - - - src/main/scala - src/test/scala - - - org.apache.maven.plugins - maven-enforcer-plugin - 1.0-beta-1 - - - enforce-akka-home - - enforce - - - - - env.AKKA_HOME - "You must have set AKKA_HOME!" - - - - ${env.AKKA_HOME}/embedded-repo - - - - true - - - - enforce-java - - enforce - - - - - 1.6.0 - - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.4.2 - - - **/*Test.java - - - - **/InMemNestedStateTest.java - - - - akka.home - ${basedir}/.. - - - org.multiverse.api.exceptions.WriteConflictException.reuse - true - - - - - - org.mortbay.jetty - maven-jetty-plugin - - / - 5 - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.0.2 - - 1.5 - 1.5 - - - - org.scala-tools - maven-scala-plugin - 2.10.1 - - - - compile - testCompile - - - - - - -Xmx1024m - - - ${scala.version} - - - - true - maven-source-plugin - - - attach-sources - - jar - - - - - - org.apache.maven.plugins - maven-changes-plugin - 2.0 - - - org.apache.maven.plugins - maven-jar-plugin - 2.2 - - - - ${project.version} - - - - - - org.apache.maven.plugins - maven-antrun-plugin - - - - - - org.apache.maven.plugins - maven-enforcer-plugin - 1.0-beta-1 - - - org.apache.felix - maven-bundle-plugin - 2.0.0 - true - - - J2SE-1.5 - <_versionpolicy>[$(@),$(version;=+;$(@))) - - - - - create-bundle - package - - bundle - - - - bundle-install - install - - install - - - - - - - - - - - org.codehaus.mojo - taglist-maven-plugin - 2.3 - - - FIXME - TODO - XXX - @fixme - @todo - @deprecated - - - - - org.apache.maven.plugins - maven-project-info-reports-plugin - 2.1.2 - - - - cim - dependencies - dependency-convergence - - index - issue-tracking - license - mailing-list - - plugins - project-team - scm - summary - - - - - - org.scala-tools - maven-scala-plugin - 2.12.2 - - ${project.build.sourceEncoding} - - 1.2-SNAPSHOT - ${scala.version} - - -Xmx1024m - -DpackageLinkDefs=file://${project.build.directory}/packageLinkDefs.properties - - - - - - - org.apache.maven.plugins - maven-changes-plugin - 2.1 - - - - changes-report - - - - - ${basedir}/changes.xml - - - - maven-surefire-report-plugin - - - - - report-only - - - - - - - - - release - - - scala-tools.org - http://nexus.scala-tools.org/content/repositories/releases - - - scala-tools.org - file://${user.home}/.m2/mvnsites/akka - - - - - hudson - - - hudson.scala-tools.org - file:///home/scala-tools.org/www/repo-snapshots - - - hudson.scala-tools.org - file:///home/scala-tools.org/www/repo-snapshots - false - - - hudson.scala-tools.org - file:///home/scala-tools.org/www/mvnsites-snapshots/akka - - - - - From cca1c2fa9d23aaa1cdda626282d6c36675ab4e77 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Sun, 25 Apr 2010 20:32:52 +0200 Subject: [PATCH 023/188] Initial code for SSL remote actors --- .../src/main/scala/remote/RemoteClient.scala | 26 ++++++++--- .../src/main/scala/remote/RemoteServer.scala | 44 ++++++++++++++++++- 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/akka-core/src/main/scala/remote/RemoteClient.scala b/akka-core/src/main/scala/remote/RemoteClient.scala index 4c18dcc6c8..60cbfbdd36 100644 --- a/akka-core/src/main/scala/remote/RemoteClient.scala +++ b/akka-core/src/main/scala/remote/RemoteClient.scala @@ -19,6 +19,7 @@ import org.jboss.netty.handler.codec.compression.{ZlibDecoder, ZlibEncoder} import org.jboss.netty.handler.codec.protobuf.{ProtobufDecoder, ProtobufEncoder} import org.jboss.netty.handler.timeout.ReadTimeoutHandler import org.jboss.netty.util.{TimerTask, Timeout, HashedWheelTimer} +import org.jboss.netty.handler.ssl.SslHandler import java.net.{SocketAddress, InetSocketAddress} import java.util.concurrent.{TimeUnit, Executors, ConcurrentMap, ConcurrentHashMap, ConcurrentSkipListSet} @@ -249,6 +250,10 @@ class RemoteClientPipelineFactory(name: String, timer: HashedWheelTimer, client: RemoteClient) extends ChannelPipelineFactory { def getPipeline: ChannelPipeline = { + val engine = RemoteServerSslContext.client.createSSLEngine() + engine.setUseClientMode(true) + + val ssl = new SslHandler(engine) val timeout = new ReadTimeoutHandler(timer, RemoteClient.READ_TIMEOUT) val lenDec = new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4) val lenPrep = new LengthFieldPrepender(4) @@ -262,8 +267,8 @@ class RemoteClientPipelineFactory(name: String, val remoteClient = new RemoteClientHandler(name, futures, supervisors, bootstrap, remoteAddress, timer, client) val stages: Array[ChannelHandler] = - zipCodec.map(codec => Array(timeout, codec.decoder, lenDec, protobufDec, codec.encoder, lenPrep, protobufEnc, remoteClient)) - .getOrElse(Array(timeout, lenDec, protobufDec, lenPrep, protobufEnc, remoteClient)) + zipCodec.map(codec => Array(ssl, timeout, codec.decoder, lenDec, protobufDec, codec.encoder, lenPrep, protobufEnc, remoteClient)) + .getOrElse(Array(ssl, timeout, lenDec, protobufDec, lenPrep, protobufEnc, remoteClient)) new StaticChannelPipeline(stages: _*) } } @@ -342,9 +347,20 @@ class RemoteClientHandler(val name: String, } override def channelConnected(ctx: ChannelHandlerContext, event: ChannelStateEvent) = { - client.listeners.toArray.foreach(l => - l.asInstanceOf[ActorRef] ! RemoteClientConnected(client.hostname, client.port)) - log.debug("Remote client connected to [%s]", ctx.getChannel.getRemoteAddress) + +// client.listeners.toArray.foreach(l => +// l.asInstanceOf[ActorRef] ! RemoteClientConnected(client.hostname, client.port)) +// log.debug("Remote client connected to [%s]", ctx.getChannel.getRemoteAddress) + + val sslHandler : SslHandler = ctx.getPipeline.get(classOf[SslHandler]) + sslHandler.handshake().addListener( new ChannelFutureListener { + def operationComplete(future : ChannelFuture) : Unit = { + if(future.isSuccess) { + client.listeners.toArray.foreach(l => l.asInstanceOf[ActorRef] ! RemoteClientConnected(client.hostname, client.port)) + log.debug("Remote client connected to [%s]", ctx.getChannel.getRemoteAddress) + } + } + }) } override def channelDisconnected(ctx: ChannelHandlerContext, event: ChannelStateEvent) = { diff --git a/akka-core/src/main/scala/remote/RemoteServer.scala b/akka-core/src/main/scala/remote/RemoteServer.scala index 28d087b3e1..08c402f15a 100644 --- a/akka-core/src/main/scala/remote/RemoteServer.scala +++ b/akka-core/src/main/scala/remote/RemoteServer.scala @@ -22,6 +22,8 @@ import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory import org.jboss.netty.handler.codec.frame.{LengthFieldBasedFrameDecoder, LengthFieldPrepender} import org.jboss.netty.handler.codec.protobuf.{ProtobufDecoder, ProtobufEncoder} import org.jboss.netty.handler.codec.compression.{ZlibEncoder, ZlibDecoder} +import org.jboss.netty.handler.ssl.SslHandler + import scala.collection.mutable.Map @@ -279,6 +281,32 @@ class RemoteServer extends Logging { case class Codec(encoder: ChannelHandler, decoder: ChannelHandler) +object RemoteServerSslContext { + import java.security.{KeyStore,Security} + import javax.net.ssl.{KeyManager,KeyManagerFactory,SSLContext,TrustManagerFactory} + + val (client,server) = { + val protocol = "TLS" + val algorithm = Option(Security.getProperty("ssl.KeyManagerFactory.algorithm")).getOrElse("SunX509") + val store = KeyStore.getInstance("JKS") + store.load(getClass.getResourceAsStream("keystore"),"keystorepassword".toCharArray) + + val keyMan = KeyManagerFactory.getInstance(algorithm) + keyMan.init(store, "certificatepassword".toCharArray) + + val trustMan = TrustManagerFactory.getInstance("SunX509"); + trustMan.init(store) //TODO safe to use same keystore? Or should use it's own keystore? + + val s = SSLContext.getInstance(protocol) + s.init(keyMan.getKeyManagers, null, null) + + val c = SSLContext.getInstance(protocol) + c.init(null, trustMan.getTrustManagers, null) + + (c,s) + } +} + /** * @author Jonas Bonér */ @@ -291,6 +319,10 @@ class RemoteServerPipelineFactory( import RemoteServer._ def getPipeline: ChannelPipeline = { + val engine = RemoteServerSslContext.server.createSSLEngine() + engine.setUseClientMode(false) + + val ssl = new SslHandler(engine) val lenDec = new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4) val lenPrep = new LengthFieldPrepender(4) val protobufDec = new ProtobufDecoder(RemoteRequestProtocol.getDefaultInstance) @@ -303,8 +335,8 @@ class RemoteServerPipelineFactory( val remoteServer = new RemoteServerHandler(name, openChannels, loader, actors, activeObjects) val stages: Array[ChannelHandler] = - zipCodec.map(codec => Array(codec.decoder, lenDec, protobufDec, codec.encoder, lenPrep, protobufEnc, remoteServer)) - .getOrElse(Array(lenDec, protobufDec, lenPrep, protobufEnc, remoteServer)) + zipCodec.map(codec => Array(ssl,codec.decoder, lenDec, protobufDec, codec.encoder, lenPrep, protobufEnc, remoteServer)) + .getOrElse(Array(ssl,lenDec, protobufDec, lenPrep, protobufEnc, remoteServer)) new StaticChannelPipeline(stages: _*) } } @@ -330,6 +362,14 @@ class RemoteServerHandler( override def channelOpen(ctx: ChannelHandlerContext, event: ChannelStateEvent) { openChannels.add(ctx.getChannel) } + + override def channelConnected(ctx : ChannelHandlerContext, e : ChannelStateEvent) { + val sslHandler : SslHandler = ctx.getPipeline.get(classOf[SslHandler]) + + // Begin handshake. + sslHandler.handshake() + } + override def handleUpstream(ctx: ChannelHandlerContext, event: ChannelEvent) = { if (event.isInstanceOf[ChannelStateEvent] && From cf802252294fa86a7c64a57fe37b2902bd16b113 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Sun, 25 Apr 2010 20:40:47 +0200 Subject: [PATCH 024/188] Adding SSL code to RemoteServer --- akka-core/src/main/scala/remote/RemoteServer.scala | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/akka-core/src/main/scala/remote/RemoteServer.scala b/akka-core/src/main/scala/remote/RemoteServer.scala index 08c402f15a..2cd5a6dd4f 100644 --- a/akka-core/src/main/scala/remote/RemoteServer.scala +++ b/akka-core/src/main/scala/remote/RemoteServer.scala @@ -367,7 +367,14 @@ class RemoteServerHandler( val sslHandler : SslHandler = ctx.getPipeline.get(classOf[SslHandler]) // Begin handshake. - sslHandler.handshake() + sslHandler.handshake().addListener( new ChannelFutureListener { + def operationComplete(future : ChannelFuture) : Unit = { + if(future.isSuccess) + openChannels.add(future.getChannel) + else + future.getChannel.close + } + }) } From b976591fb1a79b15d8fd133ee764333724b1beea Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Sun, 25 Apr 2010 21:16:16 +0200 Subject: [PATCH 025/188] Added some Dummy SSL config to assist in proof-of-concept --- .../main/scala/remote/DummySSLConfig.scala | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 akka-core/src/main/scala/remote/DummySSLConfig.scala diff --git a/akka-core/src/main/scala/remote/DummySSLConfig.scala b/akka-core/src/main/scala/remote/DummySSLConfig.scala new file mode 100644 index 0000000000..ddb743cf3f --- /dev/null +++ b/akka-core/src/main/scala/remote/DummySSLConfig.scala @@ -0,0 +1,19 @@ +package se.scalablesolutions.akka.remote + +import java.security.KeyStore +import java.security.cert.X509Certificate +import javax.net.ssl.{ManagerFactoryParameters,TrustManager,TrustManagerFactorySpi,X509TrustManager}; + +object DummyTrustManagerFactory extends TrustManagerFactorySpi { + private val DUMMY_TRUST_MANAGER : TrustManager = new X509TrustManager { + def getAcceptedIssuers() = Array[X509Certificate]() + def checkClientTrusted(chain : Array[X509Certificate], authType : String) = println("UNKNOWN CLIENT CERTIFICATE: " + chain(0).getSubjectDN) + def checkServerTrusted(chain : Array[X509Certificate], authType : String) = println("UNKNOWN SERVER CERTIFICATE: " + chain(0).getSubjectDN) + } + + def getTrustManagers = Array(DUMMY_TRUST_MANAGER) + + protected override def engineGetTrustManagers = getTrustManagers + protected override def engineInit(keystore:KeyStore) = () + protected override def engineInit(managerFactoryParameters : ManagerFactoryParameters) = () +} From ca6013222d3fb0eb666738c0806b9960fcb7bbc2 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Sun, 25 Apr 2010 23:11:28 +0200 Subject: [PATCH 026/188] Tests pass with Dummy SSL config! --- akka-core/src/main/scala/remote/RemoteClient.scala | 1 + akka-core/src/main/scala/remote/RemoteServer.scala | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/akka-core/src/main/scala/remote/RemoteClient.scala b/akka-core/src/main/scala/remote/RemoteClient.scala index 60cbfbdd36..5e90f3585b 100644 --- a/akka-core/src/main/scala/remote/RemoteClient.scala +++ b/akka-core/src/main/scala/remote/RemoteClient.scala @@ -251,6 +251,7 @@ class RemoteClientPipelineFactory(name: String, client: RemoteClient) extends ChannelPipelineFactory { def getPipeline: ChannelPipeline = { val engine = RemoteServerSslContext.client.createSSLEngine() + engine.setEnabledCipherSuites(engine.getSupportedCipherSuites) //TODO is this sensible? engine.setUseClientMode(true) val ssl = new SslHandler(engine) diff --git a/akka-core/src/main/scala/remote/RemoteServer.scala b/akka-core/src/main/scala/remote/RemoteServer.scala index 2cd5a6dd4f..1b646e1fe9 100644 --- a/akka-core/src/main/scala/remote/RemoteServer.scala +++ b/akka-core/src/main/scala/remote/RemoteServer.scala @@ -289,19 +289,19 @@ object RemoteServerSslContext { val protocol = "TLS" val algorithm = Option(Security.getProperty("ssl.KeyManagerFactory.algorithm")).getOrElse("SunX509") val store = KeyStore.getInstance("JKS") - store.load(getClass.getResourceAsStream("keystore"),"keystorepassword".toCharArray) + store.load(DummyKeyStore.asInputStream,DummyKeyStore.getKeyStorePassword) //TODO replace with getResourceAsStream + config-pass val keyMan = KeyManagerFactory.getInstance(algorithm) - keyMan.init(store, "certificatepassword".toCharArray) + keyMan.init(store, DummyKeyStore.getCertificatePassword) //TODO replace with config-pass - val trustMan = TrustManagerFactory.getInstance("SunX509"); - trustMan.init(store) //TODO safe to use same keystore? Or should use it's own keystore? + //val trustMan = TrustManagerFactory.getInstance("SunX509"); + //trustMan.init(store) //TODO safe to use same keystore? Or should use it's own keystore? val s = SSLContext.getInstance(protocol) s.init(keyMan.getKeyManagers, null, null) val c = SSLContext.getInstance(protocol) - c.init(null, trustMan.getTrustManagers, null) + c.init(null, DummyTrustManagerFactory.getTrustManagers, null) //TODO replace with TrustManagerFactory (c,s) } @@ -320,6 +320,7 @@ class RemoteServerPipelineFactory( def getPipeline: ChannelPipeline = { val engine = RemoteServerSslContext.server.createSSLEngine() + engine.setEnabledCipherSuites(engine.getSupportedCipherSuites) //TODO is this sensible? engine.setUseClientMode(false) val ssl = new SslHandler(engine) From 9cd36f1299639b34e2c5c2efc1fe4ce2850a7b45 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 26 Apr 2010 21:47:20 +0200 Subject: [PATCH 027/188] ... --- .../main/scala/remote/DummySSLConfig.scala | 266 ++++++++++++++++++ 1 file changed, 266 insertions(+) diff --git a/akka-core/src/main/scala/remote/DummySSLConfig.scala b/akka-core/src/main/scala/remote/DummySSLConfig.scala index ddb743cf3f..2a24ead57b 100644 --- a/akka-core/src/main/scala/remote/DummySSLConfig.scala +++ b/akka-core/src/main/scala/remote/DummySSLConfig.scala @@ -1,5 +1,6 @@ package se.scalablesolutions.akka.remote +import java.io.{ByteArrayInputStream,InputStream} import java.security.KeyStore import java.security.cert.X509Certificate import javax.net.ssl.{ManagerFactoryParameters,TrustManager,TrustManagerFactorySpi,X509TrustManager}; @@ -17,3 +18,268 @@ object DummyTrustManagerFactory extends TrustManagerFactorySpi { protected override def engineInit(keystore:KeyStore) = () protected override def engineInit(managerFactoryParameters : ManagerFactoryParameters) = () } + +object DummyKeyStore { + def asInputStream : InputStream = new ByteArrayInputStream(for(d <- DATA) yield d.toByte) + def getCertificatePassword = "secret".toCharArray + def getKeyStorePassword = "secret".toCharArray + private val DATA = Array[Short]( + 0xfe, 0xed, 0xfe, 0xed, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x00, 0x00, 0x01, 0x1a, 0x9f, 0x57, 0xa5, + 0x27, 0x00, 0x00, 0x01, 0x9a, 0x30, 0x82, 0x01, + 0x96, 0x30, 0x0e, 0x06, 0x0a, 0x2b, 0x06, 0x01, + 0x04, 0x01, 0x2a, 0x02, 0x11, 0x01, 0x01, 0x05, + 0x00, 0x04, 0x82, 0x01, 0x82, 0x48, 0x6d, 0xcf, + 0x16, 0xb5, 0x50, 0x95, 0x36, 0xbf, 0x47, 0x27, + 0x50, 0x58, 0x0d, 0xa2, 0x52, 0x7e, 0x25, 0xab, + 0x14, 0x1a, 0x26, 0x5e, 0x2d, 0x8a, 0x23, 0x90, + 0x60, 0x7f, 0x12, 0x20, 0x56, 0xd1, 0x43, 0xa2, + 0x6b, 0x47, 0x5d, 0xed, 0x9d, 0xd4, 0xe5, 0x83, + 0x28, 0x89, 0xc2, 0x16, 0x4c, 0x76, 0x06, 0xad, + 0x8e, 0x8c, 0x29, 0x1a, 0x9b, 0x0f, 0xdd, 0x60, + 0x4b, 0xb4, 0x62, 0x82, 0x9e, 0x4a, 0x63, 0x83, + 0x2e, 0xd2, 0x43, 0x78, 0xc2, 0x32, 0x1f, 0x60, + 0xa9, 0x8a, 0x7f, 0x0f, 0x7c, 0xa6, 0x1d, 0xe6, + 0x92, 0x9e, 0x52, 0xc7, 0x7d, 0xbb, 0x35, 0x3b, + 0xaa, 0x89, 0x73, 0x4c, 0xfb, 0x99, 0x54, 0x97, + 0x99, 0x28, 0x6e, 0x66, 0x5b, 0xf7, 0x9b, 0x7e, + 0x6d, 0x8a, 0x2f, 0xfa, 0xc3, 0x1e, 0x71, 0xb9, + 0xbd, 0x8f, 0xc5, 0x63, 0x25, 0x31, 0x20, 0x02, + 0xff, 0x02, 0xf0, 0xc9, 0x2c, 0xdd, 0x3a, 0x10, + 0x30, 0xab, 0xe5, 0xad, 0x3d, 0x1a, 0x82, 0x77, + 0x46, 0xed, 0x03, 0x38, 0xa4, 0x73, 0x6d, 0x36, + 0x36, 0x33, 0x70, 0xb2, 0x63, 0x20, 0xca, 0x03, + 0xbf, 0x5a, 0xf4, 0x7c, 0x35, 0xf0, 0x63, 0x1a, + 0x12, 0x33, 0x12, 0x58, 0xd9, 0xa2, 0x63, 0x6b, + 0x63, 0x82, 0x41, 0x65, 0x70, 0x37, 0x4b, 0x99, + 0x04, 0x9f, 0xdd, 0x5e, 0x07, 0x01, 0x95, 0x9f, + 0x36, 0xe8, 0xc3, 0x66, 0x2a, 0x21, 0x69, 0x68, + 0x40, 0xe6, 0xbc, 0xbb, 0x85, 0x81, 0x21, 0x13, + 0xe6, 0xa4, 0xcf, 0xd3, 0x67, 0xe3, 0xfd, 0x75, + 0xf0, 0xdf, 0x83, 0xe0, 0xc5, 0x36, 0x09, 0xac, + 0x1b, 0xd4, 0xf7, 0x2a, 0x23, 0x57, 0x1c, 0x5c, + 0x0f, 0xf4, 0xcf, 0xa2, 0xcf, 0xf5, 0xbd, 0x9c, + 0x69, 0x98, 0x78, 0x3a, 0x25, 0xe4, 0xfd, 0x85, + 0x11, 0xcc, 0x7d, 0xef, 0xeb, 0x74, 0x60, 0xb1, + 0xb7, 0xfb, 0x1f, 0x0e, 0x62, 0xff, 0xfe, 0x09, + 0x0a, 0xc3, 0x80, 0x2f, 0x10, 0x49, 0x89, 0x78, + 0xd2, 0x08, 0xfa, 0x89, 0x22, 0x45, 0x91, 0x21, + 0xbc, 0x90, 0x3e, 0xad, 0xb3, 0x0a, 0xb4, 0x0e, + 0x1c, 0xa1, 0x93, 0x92, 0xd8, 0x72, 0x07, 0x54, + 0x60, 0xe7, 0x91, 0xfc, 0xd9, 0x3c, 0xe1, 0x6f, + 0x08, 0xe4, 0x56, 0xf6, 0x0b, 0xb0, 0x3c, 0x39, + 0x8a, 0x2d, 0x48, 0x44, 0x28, 0x13, 0xca, 0xe9, + 0xf7, 0xa3, 0xb6, 0x8a, 0x5f, 0x31, 0xa9, 0x72, + 0xf2, 0xde, 0x96, 0xf2, 0xb1, 0x53, 0xb1, 0x3e, + 0x24, 0x57, 0xfd, 0x18, 0x45, 0x1f, 0xc5, 0x33, + 0x1b, 0xa4, 0xe8, 0x21, 0xfa, 0x0e, 0xb2, 0xb9, + 0xcb, 0xc7, 0x07, 0x41, 0xdd, 0x2f, 0xb6, 0x6a, + 0x23, 0x18, 0xed, 0xc1, 0xef, 0xe2, 0x4b, 0xec, + 0xc9, 0xba, 0xfb, 0x46, 0x43, 0x90, 0xd7, 0xb5, + 0x68, 0x28, 0x31, 0x2b, 0x8d, 0xa8, 0x51, 0x63, + 0xf7, 0x53, 0x99, 0x19, 0x68, 0x85, 0x66, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x05, 0x58, 0x2e, 0x35, + 0x30, 0x39, 0x00, 0x00, 0x02, 0x3a, 0x30, 0x82, + 0x02, 0x36, 0x30, 0x82, 0x01, 0xe0, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x04, 0x48, 0x59, 0xf1, + 0x92, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x30, 0x81, 0xa0, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4b, 0x52, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x13, 0x0a, 0x4b, 0x79, 0x75, 0x6e, 0x67, + 0x67, 0x69, 0x2d, 0x64, 0x6f, 0x31, 0x14, 0x30, + 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0b, + 0x53, 0x65, 0x6f, 0x6e, 0x67, 0x6e, 0x61, 0x6d, + 0x2d, 0x73, 0x69, 0x31, 0x1a, 0x30, 0x18, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x54, 0x68, + 0x65, 0x20, 0x4e, 0x65, 0x74, 0x74, 0x79, 0x20, + 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x31, + 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x13, 0x0f, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x73, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x27, 0x73, 0x65, 0x63, 0x75, + 0x72, 0x65, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x65, + 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6e, + 0x65, 0x74, 0x74, 0x79, 0x2e, 0x67, 0x6c, 0x65, + 0x61, 0x6d, 0x79, 0x6e, 0x6f, 0x64, 0x65, 0x2e, + 0x6e, 0x65, 0x74, 0x30, 0x20, 0x17, 0x0d, 0x30, + 0x38, 0x30, 0x36, 0x31, 0x39, 0x30, 0x35, 0x34, + 0x31, 0x33, 0x38, 0x5a, 0x18, 0x0f, 0x32, 0x31, + 0x38, 0x37, 0x31, 0x31, 0x32, 0x34, 0x30, 0x35, + 0x34, 0x31, 0x33, 0x38, 0x5a, 0x30, 0x81, 0xa0, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x4b, 0x52, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, + 0x4b, 0x79, 0x75, 0x6e, 0x67, 0x67, 0x69, 0x2d, + 0x64, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x13, 0x0b, 0x53, 0x65, 0x6f, + 0x6e, 0x67, 0x6e, 0x61, 0x6d, 0x2d, 0x73, 0x69, + 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x11, 0x54, 0x68, 0x65, 0x20, 0x4e, + 0x65, 0x74, 0x74, 0x79, 0x20, 0x50, 0x72, 0x6f, + 0x6a, 0x65, 0x63, 0x74, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0f, 0x45, + 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x73, 0x31, 0x30, + 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x27, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x63, + 0x68, 0x61, 0x74, 0x2e, 0x65, 0x78, 0x61, 0x6d, + 0x70, 0x6c, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x74, + 0x79, 0x2e, 0x67, 0x6c, 0x65, 0x61, 0x6d, 0x79, + 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x65, 0x74, + 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, + 0x00, 0xc3, 0xe3, 0x5e, 0x41, 0xa7, 0x87, 0x11, + 0x00, 0x42, 0x2a, 0xb0, 0x4b, 0xed, 0xb2, 0xe0, + 0x23, 0xdb, 0xb1, 0x3d, 0x58, 0x97, 0x35, 0x60, + 0x0b, 0x82, 0x59, 0xd3, 0x00, 0xea, 0xd4, 0x61, + 0xb8, 0x79, 0x3f, 0xb6, 0x3c, 0x12, 0x05, 0x93, + 0x2e, 0x9a, 0x59, 0x68, 0x14, 0x77, 0x3a, 0xc8, + 0x50, 0x25, 0x57, 0xa4, 0x49, 0x18, 0x63, 0x41, + 0xf0, 0x2d, 0x28, 0xec, 0x06, 0xfb, 0xb4, 0x9f, + 0xbf, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, + 0x65, 0x6c, 0x30, 0x01, 0xc2, 0x8e, 0x3e, 0xcb, + 0xb3, 0x77, 0x48, 0xe9, 0x66, 0x61, 0x9a, 0x40, + 0x86, 0xaf, 0xf6, 0x03, 0xeb, 0xba, 0x6a, 0xf2, + 0xfd, 0xe2, 0xaf, 0x36, 0x5e, 0x7b, 0xaa, 0x22, + 0x04, 0xdd, 0x2c, 0x20, 0xc4, 0xfc, 0xdd, 0xd0, + 0x82, 0x20, 0x1c, 0x3d, 0xd7, 0x9e, 0x5e, 0x5c, + 0x92, 0x5a, 0x76, 0x71, 0x28, 0xf5, 0x07, 0x7d, + 0xa2, 0x81, 0xba, 0x77, 0x9f, 0x2a, 0xd9, 0x44, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x6d, 0x79, + 0x6b, 0x65, 0x79, 0x00, 0x00, 0x01, 0x1a, 0x9f, + 0x5b, 0x56, 0xa0, 0x00, 0x00, 0x01, 0x99, 0x30, + 0x82, 0x01, 0x95, 0x30, 0x0e, 0x06, 0x0a, 0x2b, + 0x06, 0x01, 0x04, 0x01, 0x2a, 0x02, 0x11, 0x01, + 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x81, 0x29, + 0xa8, 0xb6, 0x08, 0x0c, 0x85, 0x75, 0x3e, 0xdd, + 0xb5, 0xe5, 0x1a, 0x87, 0x68, 0xd1, 0x90, 0x4b, + 0x29, 0x31, 0xee, 0x90, 0xbc, 0x9d, 0x73, 0xa0, + 0x3f, 0xe9, 0x0b, 0xa4, 0xef, 0x30, 0x9b, 0x36, + 0x9a, 0xb2, 0x54, 0x77, 0x81, 0x07, 0x4b, 0xaa, + 0xa5, 0x77, 0x98, 0xe1, 0xeb, 0xb5, 0x7c, 0x4e, + 0x48, 0xd5, 0x08, 0xfc, 0x2c, 0x36, 0xe2, 0x65, + 0x03, 0xac, 0xe5, 0xf3, 0x96, 0xb7, 0xd0, 0xb5, + 0x3b, 0x92, 0xe4, 0x14, 0x05, 0x7a, 0x6a, 0x92, + 0x56, 0xfe, 0x4e, 0xab, 0xd3, 0x0e, 0x32, 0x04, + 0x22, 0x22, 0x74, 0x47, 0x7d, 0xec, 0x21, 0x99, + 0x30, 0x31, 0x64, 0x46, 0x64, 0x9b, 0xc7, 0x13, + 0xbf, 0xbe, 0xd0, 0x31, 0x49, 0xe7, 0x3c, 0xbf, + 0xba, 0xb1, 0x20, 0xf9, 0x42, 0xf4, 0xa9, 0xa9, + 0xe5, 0x13, 0x65, 0x32, 0xbf, 0x7c, 0xcc, 0x91, + 0xd3, 0xfd, 0x24, 0x47, 0x0b, 0xe5, 0x53, 0xad, + 0x50, 0x30, 0x56, 0xd1, 0xfa, 0x9c, 0x37, 0xa8, + 0xc1, 0xce, 0xf6, 0x0b, 0x18, 0xaa, 0x7c, 0xab, + 0xbd, 0x1f, 0xdf, 0xe4, 0x80, 0xb8, 0xa7, 0xe0, + 0xad, 0x7d, 0x50, 0x74, 0xf1, 0x98, 0x78, 0xbc, + 0x58, 0xb9, 0xc2, 0x52, 0xbe, 0xd2, 0x5b, 0x81, + 0x94, 0x83, 0x8f, 0xb9, 0x4c, 0xee, 0x01, 0x2b, + 0x5e, 0xc9, 0x6e, 0x9b, 0xf5, 0x63, 0x69, 0xe4, + 0xd8, 0x0b, 0x47, 0xd8, 0xfd, 0xd8, 0xe0, 0xed, + 0xa8, 0x27, 0x03, 0x74, 0x1e, 0x5d, 0x32, 0xe6, + 0x5c, 0x63, 0xc2, 0xfb, 0x3f, 0xee, 0xb4, 0x13, + 0xc6, 0x0e, 0x6e, 0x74, 0xe0, 0x22, 0xac, 0xce, + 0x79, 0xf9, 0x43, 0x68, 0xc1, 0x03, 0x74, 0x2b, + 0xe1, 0x18, 0xf8, 0x7f, 0x76, 0x9a, 0xea, 0x82, + 0x3f, 0xc2, 0xa6, 0xa7, 0x4c, 0xfe, 0xae, 0x29, + 0x3b, 0xc1, 0x10, 0x7c, 0xd5, 0x77, 0x17, 0x79, + 0x5f, 0xcb, 0xad, 0x1f, 0xd8, 0xa1, 0xfd, 0x90, + 0xe1, 0x6b, 0xb2, 0xef, 0xb9, 0x41, 0x26, 0xa4, + 0x0b, 0x4f, 0xc6, 0x83, 0x05, 0x6f, 0xf0, 0x64, + 0x40, 0xe1, 0x44, 0xc4, 0xf9, 0x40, 0x2b, 0x3b, + 0x40, 0xdb, 0xaf, 0x35, 0xa4, 0x9b, 0x9f, 0xc4, + 0x74, 0x07, 0xe5, 0x18, 0x60, 0xc5, 0xfe, 0x15, + 0x0e, 0x3a, 0x25, 0x2a, 0x11, 0xee, 0x78, 0x2f, + 0xb8, 0xd1, 0x6e, 0x4e, 0x3c, 0x0a, 0xb5, 0xb9, + 0x40, 0x86, 0x27, 0x6d, 0x8f, 0x53, 0xb7, 0x77, + 0x36, 0xec, 0x5d, 0xed, 0x32, 0x40, 0x43, 0x82, + 0xc3, 0x52, 0x58, 0xc4, 0x26, 0x39, 0xf3, 0xb3, + 0xad, 0x58, 0xab, 0xb7, 0xf7, 0x8e, 0x0e, 0xba, + 0x8e, 0x78, 0x9d, 0xbf, 0x58, 0x34, 0xbd, 0x77, + 0x73, 0xa6, 0x50, 0x55, 0x00, 0x60, 0x26, 0xbf, + 0x6d, 0xb4, 0x98, 0x8a, 0x18, 0x83, 0x89, 0xf8, + 0xcd, 0x0d, 0x49, 0x06, 0xae, 0x51, 0x6e, 0xaf, + 0xbd, 0xe2, 0x07, 0x13, 0xd8, 0x64, 0xcc, 0xbf, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x58, 0x2e, + 0x35, 0x30, 0x39, 0x00, 0x00, 0x02, 0x34, 0x30, + 0x82, 0x02, 0x30, 0x30, 0x82, 0x01, 0xda, 0xa0, + 0x03, 0x02, 0x01, 0x02, 0x02, 0x04, 0x48, 0x59, + 0xf2, 0x84, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, + 0x00, 0x30, 0x81, 0x9d, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4b, + 0x52, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x13, 0x0a, 0x4b, 0x79, 0x75, 0x6e, + 0x67, 0x67, 0x69, 0x2d, 0x64, 0x6f, 0x31, 0x14, + 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, + 0x0b, 0x53, 0x65, 0x6f, 0x6e, 0x67, 0x6e, 0x61, + 0x6d, 0x2d, 0x73, 0x69, 0x31, 0x1a, 0x30, 0x18, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x54, + 0x68, 0x65, 0x20, 0x4e, 0x65, 0x74, 0x74, 0x79, + 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, + 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x13, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x73, 0x31, + 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x27, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x63, 0x68, 0x61, 0x74, 0x2e, 0x65, 0x78, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6e, 0x65, 0x74, + 0x74, 0x79, 0x2e, 0x67, 0x6c, 0x65, 0x61, 0x6d, + 0x79, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x65, + 0x74, 0x30, 0x20, 0x17, 0x0d, 0x30, 0x38, 0x30, + 0x36, 0x31, 0x39, 0x30, 0x35, 0x34, 0x35, 0x34, + 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x31, 0x38, 0x37, + 0x31, 0x31, 0x32, 0x33, 0x30, 0x35, 0x34, 0x35, + 0x34, 0x30, 0x5a, 0x30, 0x81, 0x9d, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x4b, 0x52, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x4b, 0x79, + 0x75, 0x6e, 0x67, 0x67, 0x69, 0x2d, 0x64, 0x6f, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x0b, 0x53, 0x65, 0x6f, 0x6e, 0x67, + 0x6e, 0x61, 0x6d, 0x2d, 0x73, 0x69, 0x31, 0x1a, + 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, + 0x11, 0x54, 0x68, 0x65, 0x20, 0x4e, 0x65, 0x74, + 0x74, 0x79, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x13, 0x0c, 0x43, 0x6f, 0x6e, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, + 0x73, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x27, 0x73, 0x65, 0x63, 0x75, + 0x72, 0x65, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x65, + 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6e, + 0x65, 0x74, 0x74, 0x79, 0x2e, 0x67, 0x6c, 0x65, + 0x61, 0x6d, 0x79, 0x6e, 0x6f, 0x64, 0x65, 0x2e, + 0x6e, 0x65, 0x74, 0x30, 0x5c, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, + 0x48, 0x02, 0x41, 0x00, 0x95, 0xb3, 0x47, 0x17, + 0x95, 0x0f, 0x57, 0xcf, 0x66, 0x72, 0x0a, 0x7e, + 0x5b, 0x54, 0xea, 0x8c, 0x6f, 0x79, 0xde, 0x94, + 0xac, 0x0b, 0x5a, 0xd4, 0xd6, 0x1b, 0x58, 0x12, + 0x1a, 0x16, 0x3d, 0xfe, 0xdf, 0xa5, 0x2b, 0x86, + 0xbc, 0x64, 0xd4, 0x80, 0x1e, 0x3f, 0xf9, 0xe2, + 0x04, 0x03, 0x79, 0x9b, 0xc1, 0x5c, 0xf0, 0xf1, + 0xf3, 0xf1, 0xe3, 0xbf, 0x3f, 0xc0, 0x1f, 0xdd, + 0xdb, 0xc0, 0x5b, 0x21, 0x02, 0x03, 0x01, 0x00, + 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x03, 0x41, 0x00, 0x02, 0xd7, 0xdd, 0xbd, 0x0c, + 0x8e, 0x21, 0x20, 0xef, 0x9e, 0x4f, 0x1f, 0xf5, + 0x49, 0xf1, 0xae, 0x58, 0x9b, 0x94, 0x3a, 0x1f, + 0x70, 0x33, 0xf0, 0x9b, 0xbb, 0xe9, 0xc0, 0xf3, + 0x72, 0xcb, 0xde, 0xb6, 0x56, 0x72, 0xcc, 0x1c, + 0xf0, 0xd6, 0x5a, 0x2a, 0xbc, 0xa1, 0x7e, 0x23, + 0x83, 0xe9, 0xe7, 0xcf, 0x9e, 0xa5, 0xf9, 0xcc, + 0xc2, 0x61, 0xf4, 0xdb, 0x40, 0x93, 0x1d, 0x63, + 0x8a, 0x50, 0x4c, 0x11, 0x39, 0xb1, 0x91, 0xc1, + 0xe6, 0x9d, 0xd9, 0x1a, 0x62, 0x1b, 0xb8, 0xd3, + 0xd6, 0x9a, 0x6d, 0xb9, 0x8e, 0x15, 0x51 ) +} From d748bd5e9ed50415e2adbed3afe7ad2510364ae8 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Thu, 15 Jul 2010 21:33:44 +0200 Subject: [PATCH 028/188] Initial code, ble to turn ssl on/off, not verified --- .../main/scala/remote/DummySSLConfig.scala | 285 ------------------ .../src/main/scala/remote/RemoteClient.scala | 47 +-- .../src/main/scala/remote/RemoteServer.scala | 95 +++--- config/akka-reference.conf | 17 ++ 4 files changed, 100 insertions(+), 344 deletions(-) delete mode 100644 akka-core/src/main/scala/remote/DummySSLConfig.scala diff --git a/akka-core/src/main/scala/remote/DummySSLConfig.scala b/akka-core/src/main/scala/remote/DummySSLConfig.scala deleted file mode 100644 index 2a24ead57b..0000000000 --- a/akka-core/src/main/scala/remote/DummySSLConfig.scala +++ /dev/null @@ -1,285 +0,0 @@ -package se.scalablesolutions.akka.remote - -import java.io.{ByteArrayInputStream,InputStream} -import java.security.KeyStore -import java.security.cert.X509Certificate -import javax.net.ssl.{ManagerFactoryParameters,TrustManager,TrustManagerFactorySpi,X509TrustManager}; - -object DummyTrustManagerFactory extends TrustManagerFactorySpi { - private val DUMMY_TRUST_MANAGER : TrustManager = new X509TrustManager { - def getAcceptedIssuers() = Array[X509Certificate]() - def checkClientTrusted(chain : Array[X509Certificate], authType : String) = println("UNKNOWN CLIENT CERTIFICATE: " + chain(0).getSubjectDN) - def checkServerTrusted(chain : Array[X509Certificate], authType : String) = println("UNKNOWN SERVER CERTIFICATE: " + chain(0).getSubjectDN) - } - - def getTrustManagers = Array(DUMMY_TRUST_MANAGER) - - protected override def engineGetTrustManagers = getTrustManagers - protected override def engineInit(keystore:KeyStore) = () - protected override def engineInit(managerFactoryParameters : ManagerFactoryParameters) = () -} - -object DummyKeyStore { - def asInputStream : InputStream = new ByteArrayInputStream(for(d <- DATA) yield d.toByte) - def getCertificatePassword = "secret".toCharArray - def getKeyStorePassword = "secret".toCharArray - private val DATA = Array[Short]( - 0xfe, 0xed, 0xfe, 0xed, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, - 0x65, 0x00, 0x00, 0x01, 0x1a, 0x9f, 0x57, 0xa5, - 0x27, 0x00, 0x00, 0x01, 0x9a, 0x30, 0x82, 0x01, - 0x96, 0x30, 0x0e, 0x06, 0x0a, 0x2b, 0x06, 0x01, - 0x04, 0x01, 0x2a, 0x02, 0x11, 0x01, 0x01, 0x05, - 0x00, 0x04, 0x82, 0x01, 0x82, 0x48, 0x6d, 0xcf, - 0x16, 0xb5, 0x50, 0x95, 0x36, 0xbf, 0x47, 0x27, - 0x50, 0x58, 0x0d, 0xa2, 0x52, 0x7e, 0x25, 0xab, - 0x14, 0x1a, 0x26, 0x5e, 0x2d, 0x8a, 0x23, 0x90, - 0x60, 0x7f, 0x12, 0x20, 0x56, 0xd1, 0x43, 0xa2, - 0x6b, 0x47, 0x5d, 0xed, 0x9d, 0xd4, 0xe5, 0x83, - 0x28, 0x89, 0xc2, 0x16, 0x4c, 0x76, 0x06, 0xad, - 0x8e, 0x8c, 0x29, 0x1a, 0x9b, 0x0f, 0xdd, 0x60, - 0x4b, 0xb4, 0x62, 0x82, 0x9e, 0x4a, 0x63, 0x83, - 0x2e, 0xd2, 0x43, 0x78, 0xc2, 0x32, 0x1f, 0x60, - 0xa9, 0x8a, 0x7f, 0x0f, 0x7c, 0xa6, 0x1d, 0xe6, - 0x92, 0x9e, 0x52, 0xc7, 0x7d, 0xbb, 0x35, 0x3b, - 0xaa, 0x89, 0x73, 0x4c, 0xfb, 0x99, 0x54, 0x97, - 0x99, 0x28, 0x6e, 0x66, 0x5b, 0xf7, 0x9b, 0x7e, - 0x6d, 0x8a, 0x2f, 0xfa, 0xc3, 0x1e, 0x71, 0xb9, - 0xbd, 0x8f, 0xc5, 0x63, 0x25, 0x31, 0x20, 0x02, - 0xff, 0x02, 0xf0, 0xc9, 0x2c, 0xdd, 0x3a, 0x10, - 0x30, 0xab, 0xe5, 0xad, 0x3d, 0x1a, 0x82, 0x77, - 0x46, 0xed, 0x03, 0x38, 0xa4, 0x73, 0x6d, 0x36, - 0x36, 0x33, 0x70, 0xb2, 0x63, 0x20, 0xca, 0x03, - 0xbf, 0x5a, 0xf4, 0x7c, 0x35, 0xf0, 0x63, 0x1a, - 0x12, 0x33, 0x12, 0x58, 0xd9, 0xa2, 0x63, 0x6b, - 0x63, 0x82, 0x41, 0x65, 0x70, 0x37, 0x4b, 0x99, - 0x04, 0x9f, 0xdd, 0x5e, 0x07, 0x01, 0x95, 0x9f, - 0x36, 0xe8, 0xc3, 0x66, 0x2a, 0x21, 0x69, 0x68, - 0x40, 0xe6, 0xbc, 0xbb, 0x85, 0x81, 0x21, 0x13, - 0xe6, 0xa4, 0xcf, 0xd3, 0x67, 0xe3, 0xfd, 0x75, - 0xf0, 0xdf, 0x83, 0xe0, 0xc5, 0x36, 0x09, 0xac, - 0x1b, 0xd4, 0xf7, 0x2a, 0x23, 0x57, 0x1c, 0x5c, - 0x0f, 0xf4, 0xcf, 0xa2, 0xcf, 0xf5, 0xbd, 0x9c, - 0x69, 0x98, 0x78, 0x3a, 0x25, 0xe4, 0xfd, 0x85, - 0x11, 0xcc, 0x7d, 0xef, 0xeb, 0x74, 0x60, 0xb1, - 0xb7, 0xfb, 0x1f, 0x0e, 0x62, 0xff, 0xfe, 0x09, - 0x0a, 0xc3, 0x80, 0x2f, 0x10, 0x49, 0x89, 0x78, - 0xd2, 0x08, 0xfa, 0x89, 0x22, 0x45, 0x91, 0x21, - 0xbc, 0x90, 0x3e, 0xad, 0xb3, 0x0a, 0xb4, 0x0e, - 0x1c, 0xa1, 0x93, 0x92, 0xd8, 0x72, 0x07, 0x54, - 0x60, 0xe7, 0x91, 0xfc, 0xd9, 0x3c, 0xe1, 0x6f, - 0x08, 0xe4, 0x56, 0xf6, 0x0b, 0xb0, 0x3c, 0x39, - 0x8a, 0x2d, 0x48, 0x44, 0x28, 0x13, 0xca, 0xe9, - 0xf7, 0xa3, 0xb6, 0x8a, 0x5f, 0x31, 0xa9, 0x72, - 0xf2, 0xde, 0x96, 0xf2, 0xb1, 0x53, 0xb1, 0x3e, - 0x24, 0x57, 0xfd, 0x18, 0x45, 0x1f, 0xc5, 0x33, - 0x1b, 0xa4, 0xe8, 0x21, 0xfa, 0x0e, 0xb2, 0xb9, - 0xcb, 0xc7, 0x07, 0x41, 0xdd, 0x2f, 0xb6, 0x6a, - 0x23, 0x18, 0xed, 0xc1, 0xef, 0xe2, 0x4b, 0xec, - 0xc9, 0xba, 0xfb, 0x46, 0x43, 0x90, 0xd7, 0xb5, - 0x68, 0x28, 0x31, 0x2b, 0x8d, 0xa8, 0x51, 0x63, - 0xf7, 0x53, 0x99, 0x19, 0x68, 0x85, 0x66, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x05, 0x58, 0x2e, 0x35, - 0x30, 0x39, 0x00, 0x00, 0x02, 0x3a, 0x30, 0x82, - 0x02, 0x36, 0x30, 0x82, 0x01, 0xe0, 0xa0, 0x03, - 0x02, 0x01, 0x02, 0x02, 0x04, 0x48, 0x59, 0xf1, - 0x92, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, - 0x30, 0x81, 0xa0, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4b, 0x52, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, - 0x08, 0x13, 0x0a, 0x4b, 0x79, 0x75, 0x6e, 0x67, - 0x67, 0x69, 0x2d, 0x64, 0x6f, 0x31, 0x14, 0x30, - 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0b, - 0x53, 0x65, 0x6f, 0x6e, 0x67, 0x6e, 0x61, 0x6d, - 0x2d, 0x73, 0x69, 0x31, 0x1a, 0x30, 0x18, 0x06, - 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x54, 0x68, - 0x65, 0x20, 0x4e, 0x65, 0x74, 0x74, 0x79, 0x20, - 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x31, - 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x13, 0x0f, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, - 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x73, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x27, 0x73, 0x65, 0x63, 0x75, - 0x72, 0x65, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x65, - 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6e, - 0x65, 0x74, 0x74, 0x79, 0x2e, 0x67, 0x6c, 0x65, - 0x61, 0x6d, 0x79, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x6e, 0x65, 0x74, 0x30, 0x20, 0x17, 0x0d, 0x30, - 0x38, 0x30, 0x36, 0x31, 0x39, 0x30, 0x35, 0x34, - 0x31, 0x33, 0x38, 0x5a, 0x18, 0x0f, 0x32, 0x31, - 0x38, 0x37, 0x31, 0x31, 0x32, 0x34, 0x30, 0x35, - 0x34, 0x31, 0x33, 0x38, 0x5a, 0x30, 0x81, 0xa0, - 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x4b, 0x52, 0x31, 0x13, 0x30, - 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, - 0x4b, 0x79, 0x75, 0x6e, 0x67, 0x67, 0x69, 0x2d, - 0x64, 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, - 0x55, 0x04, 0x07, 0x13, 0x0b, 0x53, 0x65, 0x6f, - 0x6e, 0x67, 0x6e, 0x61, 0x6d, 0x2d, 0x73, 0x69, - 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x13, 0x11, 0x54, 0x68, 0x65, 0x20, 0x4e, - 0x65, 0x74, 0x74, 0x79, 0x20, 0x50, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x31, 0x18, 0x30, 0x16, - 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0f, 0x45, - 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x41, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x73, 0x31, 0x30, - 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, - 0x27, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x63, - 0x68, 0x61, 0x74, 0x2e, 0x65, 0x78, 0x61, 0x6d, - 0x70, 0x6c, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x74, - 0x79, 0x2e, 0x67, 0x6c, 0x65, 0x61, 0x6d, 0x79, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x65, 0x74, - 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, - 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, - 0x00, 0xc3, 0xe3, 0x5e, 0x41, 0xa7, 0x87, 0x11, - 0x00, 0x42, 0x2a, 0xb0, 0x4b, 0xed, 0xb2, 0xe0, - 0x23, 0xdb, 0xb1, 0x3d, 0x58, 0x97, 0x35, 0x60, - 0x0b, 0x82, 0x59, 0xd3, 0x00, 0xea, 0xd4, 0x61, - 0xb8, 0x79, 0x3f, 0xb6, 0x3c, 0x12, 0x05, 0x93, - 0x2e, 0x9a, 0x59, 0x68, 0x14, 0x77, 0x3a, 0xc8, - 0x50, 0x25, 0x57, 0xa4, 0x49, 0x18, 0x63, 0x41, - 0xf0, 0x2d, 0x28, 0xec, 0x06, 0xfb, 0xb4, 0x9f, - 0xbf, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, - 0x65, 0x6c, 0x30, 0x01, 0xc2, 0x8e, 0x3e, 0xcb, - 0xb3, 0x77, 0x48, 0xe9, 0x66, 0x61, 0x9a, 0x40, - 0x86, 0xaf, 0xf6, 0x03, 0xeb, 0xba, 0x6a, 0xf2, - 0xfd, 0xe2, 0xaf, 0x36, 0x5e, 0x7b, 0xaa, 0x22, - 0x04, 0xdd, 0x2c, 0x20, 0xc4, 0xfc, 0xdd, 0xd0, - 0x82, 0x20, 0x1c, 0x3d, 0xd7, 0x9e, 0x5e, 0x5c, - 0x92, 0x5a, 0x76, 0x71, 0x28, 0xf5, 0x07, 0x7d, - 0xa2, 0x81, 0xba, 0x77, 0x9f, 0x2a, 0xd9, 0x44, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x6d, 0x79, - 0x6b, 0x65, 0x79, 0x00, 0x00, 0x01, 0x1a, 0x9f, - 0x5b, 0x56, 0xa0, 0x00, 0x00, 0x01, 0x99, 0x30, - 0x82, 0x01, 0x95, 0x30, 0x0e, 0x06, 0x0a, 0x2b, - 0x06, 0x01, 0x04, 0x01, 0x2a, 0x02, 0x11, 0x01, - 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x81, 0x29, - 0xa8, 0xb6, 0x08, 0x0c, 0x85, 0x75, 0x3e, 0xdd, - 0xb5, 0xe5, 0x1a, 0x87, 0x68, 0xd1, 0x90, 0x4b, - 0x29, 0x31, 0xee, 0x90, 0xbc, 0x9d, 0x73, 0xa0, - 0x3f, 0xe9, 0x0b, 0xa4, 0xef, 0x30, 0x9b, 0x36, - 0x9a, 0xb2, 0x54, 0x77, 0x81, 0x07, 0x4b, 0xaa, - 0xa5, 0x77, 0x98, 0xe1, 0xeb, 0xb5, 0x7c, 0x4e, - 0x48, 0xd5, 0x08, 0xfc, 0x2c, 0x36, 0xe2, 0x65, - 0x03, 0xac, 0xe5, 0xf3, 0x96, 0xb7, 0xd0, 0xb5, - 0x3b, 0x92, 0xe4, 0x14, 0x05, 0x7a, 0x6a, 0x92, - 0x56, 0xfe, 0x4e, 0xab, 0xd3, 0x0e, 0x32, 0x04, - 0x22, 0x22, 0x74, 0x47, 0x7d, 0xec, 0x21, 0x99, - 0x30, 0x31, 0x64, 0x46, 0x64, 0x9b, 0xc7, 0x13, - 0xbf, 0xbe, 0xd0, 0x31, 0x49, 0xe7, 0x3c, 0xbf, - 0xba, 0xb1, 0x20, 0xf9, 0x42, 0xf4, 0xa9, 0xa9, - 0xe5, 0x13, 0x65, 0x32, 0xbf, 0x7c, 0xcc, 0x91, - 0xd3, 0xfd, 0x24, 0x47, 0x0b, 0xe5, 0x53, 0xad, - 0x50, 0x30, 0x56, 0xd1, 0xfa, 0x9c, 0x37, 0xa8, - 0xc1, 0xce, 0xf6, 0x0b, 0x18, 0xaa, 0x7c, 0xab, - 0xbd, 0x1f, 0xdf, 0xe4, 0x80, 0xb8, 0xa7, 0xe0, - 0xad, 0x7d, 0x50, 0x74, 0xf1, 0x98, 0x78, 0xbc, - 0x58, 0xb9, 0xc2, 0x52, 0xbe, 0xd2, 0x5b, 0x81, - 0x94, 0x83, 0x8f, 0xb9, 0x4c, 0xee, 0x01, 0x2b, - 0x5e, 0xc9, 0x6e, 0x9b, 0xf5, 0x63, 0x69, 0xe4, - 0xd8, 0x0b, 0x47, 0xd8, 0xfd, 0xd8, 0xe0, 0xed, - 0xa8, 0x27, 0x03, 0x74, 0x1e, 0x5d, 0x32, 0xe6, - 0x5c, 0x63, 0xc2, 0xfb, 0x3f, 0xee, 0xb4, 0x13, - 0xc6, 0x0e, 0x6e, 0x74, 0xe0, 0x22, 0xac, 0xce, - 0x79, 0xf9, 0x43, 0x68, 0xc1, 0x03, 0x74, 0x2b, - 0xe1, 0x18, 0xf8, 0x7f, 0x76, 0x9a, 0xea, 0x82, - 0x3f, 0xc2, 0xa6, 0xa7, 0x4c, 0xfe, 0xae, 0x29, - 0x3b, 0xc1, 0x10, 0x7c, 0xd5, 0x77, 0x17, 0x79, - 0x5f, 0xcb, 0xad, 0x1f, 0xd8, 0xa1, 0xfd, 0x90, - 0xe1, 0x6b, 0xb2, 0xef, 0xb9, 0x41, 0x26, 0xa4, - 0x0b, 0x4f, 0xc6, 0x83, 0x05, 0x6f, 0xf0, 0x64, - 0x40, 0xe1, 0x44, 0xc4, 0xf9, 0x40, 0x2b, 0x3b, - 0x40, 0xdb, 0xaf, 0x35, 0xa4, 0x9b, 0x9f, 0xc4, - 0x74, 0x07, 0xe5, 0x18, 0x60, 0xc5, 0xfe, 0x15, - 0x0e, 0x3a, 0x25, 0x2a, 0x11, 0xee, 0x78, 0x2f, - 0xb8, 0xd1, 0x6e, 0x4e, 0x3c, 0x0a, 0xb5, 0xb9, - 0x40, 0x86, 0x27, 0x6d, 0x8f, 0x53, 0xb7, 0x77, - 0x36, 0xec, 0x5d, 0xed, 0x32, 0x40, 0x43, 0x82, - 0xc3, 0x52, 0x58, 0xc4, 0x26, 0x39, 0xf3, 0xb3, - 0xad, 0x58, 0xab, 0xb7, 0xf7, 0x8e, 0x0e, 0xba, - 0x8e, 0x78, 0x9d, 0xbf, 0x58, 0x34, 0xbd, 0x77, - 0x73, 0xa6, 0x50, 0x55, 0x00, 0x60, 0x26, 0xbf, - 0x6d, 0xb4, 0x98, 0x8a, 0x18, 0x83, 0x89, 0xf8, - 0xcd, 0x0d, 0x49, 0x06, 0xae, 0x51, 0x6e, 0xaf, - 0xbd, 0xe2, 0x07, 0x13, 0xd8, 0x64, 0xcc, 0xbf, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x58, 0x2e, - 0x35, 0x30, 0x39, 0x00, 0x00, 0x02, 0x34, 0x30, - 0x82, 0x02, 0x30, 0x30, 0x82, 0x01, 0xda, 0xa0, - 0x03, 0x02, 0x01, 0x02, 0x02, 0x04, 0x48, 0x59, - 0xf2, 0x84, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, - 0x00, 0x30, 0x81, 0x9d, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4b, - 0x52, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x0a, 0x4b, 0x79, 0x75, 0x6e, - 0x67, 0x67, 0x69, 0x2d, 0x64, 0x6f, 0x31, 0x14, - 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, - 0x0b, 0x53, 0x65, 0x6f, 0x6e, 0x67, 0x6e, 0x61, - 0x6d, 0x2d, 0x73, 0x69, 0x31, 0x1a, 0x30, 0x18, - 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x54, - 0x68, 0x65, 0x20, 0x4e, 0x65, 0x74, 0x74, 0x79, - 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, - 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, - 0x0b, 0x13, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x73, 0x31, - 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, 0x04, 0x03, - 0x13, 0x27, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, - 0x63, 0x68, 0x61, 0x74, 0x2e, 0x65, 0x78, 0x61, - 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6e, 0x65, 0x74, - 0x74, 0x79, 0x2e, 0x67, 0x6c, 0x65, 0x61, 0x6d, - 0x79, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x6e, 0x65, - 0x74, 0x30, 0x20, 0x17, 0x0d, 0x30, 0x38, 0x30, - 0x36, 0x31, 0x39, 0x30, 0x35, 0x34, 0x35, 0x34, - 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x31, 0x38, 0x37, - 0x31, 0x31, 0x32, 0x33, 0x30, 0x35, 0x34, 0x35, - 0x34, 0x30, 0x5a, 0x30, 0x81, 0x9d, 0x31, 0x0b, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x4b, 0x52, 0x31, 0x13, 0x30, 0x11, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x4b, 0x79, - 0x75, 0x6e, 0x67, 0x67, 0x69, 0x2d, 0x64, 0x6f, - 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x13, 0x0b, 0x53, 0x65, 0x6f, 0x6e, 0x67, - 0x6e, 0x61, 0x6d, 0x2d, 0x73, 0x69, 0x31, 0x1a, - 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x11, 0x54, 0x68, 0x65, 0x20, 0x4e, 0x65, 0x74, - 0x74, 0x79, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, - 0x55, 0x04, 0x0b, 0x13, 0x0c, 0x43, 0x6f, 0x6e, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, - 0x73, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x27, 0x73, 0x65, 0x63, 0x75, - 0x72, 0x65, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x65, - 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x6e, - 0x65, 0x74, 0x74, 0x79, 0x2e, 0x67, 0x6c, 0x65, - 0x61, 0x6d, 0x79, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x6e, 0x65, 0x74, 0x30, 0x5c, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, - 0x48, 0x02, 0x41, 0x00, 0x95, 0xb3, 0x47, 0x17, - 0x95, 0x0f, 0x57, 0xcf, 0x66, 0x72, 0x0a, 0x7e, - 0x5b, 0x54, 0xea, 0x8c, 0x6f, 0x79, 0xde, 0x94, - 0xac, 0x0b, 0x5a, 0xd4, 0xd6, 0x1b, 0x58, 0x12, - 0x1a, 0x16, 0x3d, 0xfe, 0xdf, 0xa5, 0x2b, 0x86, - 0xbc, 0x64, 0xd4, 0x80, 0x1e, 0x3f, 0xf9, 0xe2, - 0x04, 0x03, 0x79, 0x9b, 0xc1, 0x5c, 0xf0, 0xf1, - 0xf3, 0xf1, 0xe3, 0xbf, 0x3f, 0xc0, 0x1f, 0xdd, - 0xdb, 0xc0, 0x5b, 0x21, 0x02, 0x03, 0x01, 0x00, - 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, - 0x03, 0x41, 0x00, 0x02, 0xd7, 0xdd, 0xbd, 0x0c, - 0x8e, 0x21, 0x20, 0xef, 0x9e, 0x4f, 0x1f, 0xf5, - 0x49, 0xf1, 0xae, 0x58, 0x9b, 0x94, 0x3a, 0x1f, - 0x70, 0x33, 0xf0, 0x9b, 0xbb, 0xe9, 0xc0, 0xf3, - 0x72, 0xcb, 0xde, 0xb6, 0x56, 0x72, 0xcc, 0x1c, - 0xf0, 0xd6, 0x5a, 0x2a, 0xbc, 0xa1, 0x7e, 0x23, - 0x83, 0xe9, 0xe7, 0xcf, 0x9e, 0xa5, 0xf9, 0xcc, - 0xc2, 0x61, 0xf4, 0xdb, 0x40, 0x93, 0x1d, 0x63, - 0x8a, 0x50, 0x4c, 0x11, 0x39, 0xb1, 0x91, 0xc1, - 0xe6, 0x9d, 0xd9, 0x1a, 0x62, 0x1b, 0xb8, 0xd3, - 0xd6, 0x9a, 0x6d, 0xb9, 0x8e, 0x15, 0x51 ) -} diff --git a/akka-core/src/main/scala/remote/RemoteClient.scala b/akka-core/src/main/scala/remote/RemoteClient.scala index 5e90f3585b..c90d472c09 100644 --- a/akka-core/src/main/scala/remote/RemoteClient.scala +++ b/akka-core/src/main/scala/remote/RemoteClient.scala @@ -250,26 +250,27 @@ class RemoteClientPipelineFactory(name: String, timer: HashedWheelTimer, client: RemoteClient) extends ChannelPipelineFactory { def getPipeline: ChannelPipeline = { + def join(ch: ChannelHandler*) = Array[ChannelHandler](ch:_*) + val engine = RemoteServerSslContext.client.createSSLEngine() engine.setEnabledCipherSuites(engine.getSupportedCipherSuites) //TODO is this sensible? engine.setUseClientMode(true) - val ssl = new SslHandler(engine) - val timeout = new ReadTimeoutHandler(timer, RemoteClient.READ_TIMEOUT) - val lenDec = new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4) - val lenPrep = new LengthFieldPrepender(4) + val ssl = if(RemoteServer.SECURE) join(new SslHandler(engine)) else join() + val timeout = new ReadTimeoutHandler(timer, RemoteClient.READ_TIMEOUT) + val lenDec = new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4) + val lenPrep = new LengthFieldPrepender(4) val protobufDec = new ProtobufDecoder(RemoteReplyProtocol.getDefaultInstance) val protobufEnc = new ProtobufEncoder - val zipCodec = RemoteServer.COMPRESSION_SCHEME match { - case "zlib" => Some(Codec(new ZlibEncoder(RemoteServer.ZLIB_COMPRESSION_LEVEL), new ZlibDecoder)) - //case "lzf" => Some(Codec(new LzfEncoder, new LzfDecoder)) - case _ => None + val(enc,dec) = RemoteServer.COMPRESSION_SCHEME match { + case "zlib" => (join(new ZlibEncoder(RemoteServer.ZLIB_COMPRESSION_LEVEL)),join(new ZlibDecoder)) + case _ => (join(),join()) } + val remoteClient = new RemoteClientHandler(name, futures, supervisors, bootstrap, remoteAddress, timer, client) - val stages: Array[ChannelHandler] = - zipCodec.map(codec => Array(ssl, timeout, codec.decoder, lenDec, protobufDec, codec.encoder, lenPrep, protobufEnc, remoteClient)) - .getOrElse(Array(ssl, timeout, lenDec, protobufDec, lenPrep, protobufEnc, remoteClient)) + val stages = ssl ++ join(timeout) ++ dec ++ join(lenDec, protobufDec) ++ enc ++ join(lenPrep, protobufEnc, remoteClient) + new StaticChannelPipeline(stages: _*) } } @@ -348,20 +349,24 @@ class RemoteClientHandler(val name: String, } override def channelConnected(ctx: ChannelHandlerContext, event: ChannelStateEvent) = { + def connect = { + client.listeners.toArray.foreach(l => l.asInstanceOf[ActorRef] ! RemoteClientConnected(client.hostname, client.port)) + log.debug("Remote client connected to [%s]", ctx.getChannel.getRemoteAddress) + } -// client.listeners.toArray.foreach(l => -// l.asInstanceOf[ActorRef] ! RemoteClientConnected(client.hostname, client.port)) -// log.debug("Remote client connected to [%s]", ctx.getChannel.getRemoteAddress) - - val sslHandler : SslHandler = ctx.getPipeline.get(classOf[SslHandler]) - sslHandler.handshake().addListener( new ChannelFutureListener { + if(RemoteServer.SECURE){ + val sslHandler : SslHandler = ctx.getPipeline.get(classOf[SslHandler]) + sslHandler.handshake().addListener( new ChannelFutureListener { def operationComplete(future : ChannelFuture) : Unit = { - if(future.isSuccess) { - client.listeners.toArray.foreach(l => l.asInstanceOf[ActorRef] ! RemoteClientConnected(client.hostname, client.port)) - log.debug("Remote client connected to [%s]", ctx.getChannel.getRemoteAddress) - } + if(future.isSuccess) + connect + //else + //FIXME: What is the correct action here? } }) + } else { + connect + } } override def channelDisconnected(ctx: ChannelHandlerContext, event: ChannelStateEvent) = { diff --git a/akka-core/src/main/scala/remote/RemoteServer.scala b/akka-core/src/main/scala/remote/RemoteServer.scala index 1b646e1fe9..93386311f2 100644 --- a/akka-core/src/main/scala/remote/RemoteServer.scala +++ b/akka-core/src/main/scala/remote/RemoteServer.scala @@ -75,6 +75,32 @@ object RemoteServer { level } + val SECURE = { + if(config.getBool("akka.remote.ssl.service",false)){ + + val properties = List( + ("key-store-type" ,"keyStoreType"), + ("key-store" ,"keyStore"), + ("key-store-pass" ,"keyStorePassword"), + ("trust-store-type","trustStoreType"), + ("trust-store" ,"trustStore"), + ("trust-store-pass","trustStorePassword") + ).map(x => ("akka.remote.ssl." + x._1,"javax.net.ssl."+x._2)) + + //If property is not set, and we have a value from our akka.conf, use that value + for{ p <- properties if System.getProperty(p._2) eq null + c <- config.getString(p._1) + } System.setProperty(p._2,c) + + if(config.getBool("akka.remote.ssl.debug",false)) + System.setProperty("javax.net.debug","ssl") + + true + } + else + false + } + object Address { def apply(hostname: String, port: Int) = new Address(hostname, port) } @@ -279,30 +305,20 @@ class RemoteServer extends Logging { } } -case class Codec(encoder: ChannelHandler, decoder: ChannelHandler) - object RemoteServerSslContext { - import java.security.{KeyStore,Security} - import javax.net.ssl.{KeyManager,KeyManagerFactory,SSLContext,TrustManagerFactory} + import javax.net.ssl.SSLContext val (client,server) = { val protocol = "TLS" - val algorithm = Option(Security.getProperty("ssl.KeyManagerFactory.algorithm")).getOrElse("SunX509") - val store = KeyStore.getInstance("JKS") - store.load(DummyKeyStore.asInputStream,DummyKeyStore.getKeyStorePassword) //TODO replace with getResourceAsStream + config-pass - - val keyMan = KeyManagerFactory.getInstance(algorithm) - keyMan.init(store, DummyKeyStore.getCertificatePassword) //TODO replace with config-pass - - //val trustMan = TrustManagerFactory.getInstance("SunX509"); - //trustMan.init(store) //TODO safe to use same keystore? Or should use it's own keystore? + //val algorithm = Option(Security.getProperty("ssl.KeyManagerFactory.algorithm")).getOrElse("SunX509") + //val store = KeyStore.getInstance("JKS") val s = SSLContext.getInstance(protocol) - s.init(keyMan.getKeyManagers, null, null) + s.init(null,null,null) val c = SSLContext.getInstance(protocol) - c.init(null, DummyTrustManagerFactory.getTrustManagers, null) //TODO replace with TrustManagerFactory - + c.init(null,null,null) + (c,s) } } @@ -319,25 +335,26 @@ class RemoteServerPipelineFactory( import RemoteServer._ def getPipeline: ChannelPipeline = { + def join(ch: ChannelHandler*) = Array[ChannelHandler](ch:_*) + val engine = RemoteServerSslContext.server.createSSLEngine() engine.setEnabledCipherSuites(engine.getSupportedCipherSuites) //TODO is this sensible? engine.setUseClientMode(false) - val ssl = new SslHandler(engine) - val lenDec = new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4) - val lenPrep = new LengthFieldPrepender(4) - val protobufDec = new ProtobufDecoder(RemoteRequestProtocol.getDefaultInstance) - val protobufEnc = new ProtobufEncoder - val zipCodec = RemoteServer.COMPRESSION_SCHEME match { - case "zlib" => Some(Codec(new ZlibEncoder(RemoteServer.ZLIB_COMPRESSION_LEVEL), new ZlibDecoder)) - //case "lzf" => Some(Codec(new LzfEncoder, new LzfDecoder)) - case _ => None + val ssl = if(RemoteServer.SECURE) join(new SslHandler(engine)) else join() + val lenDec = new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4) + val lenPrep = new LengthFieldPrepender(4) + val protobufDec = new ProtobufDecoder(RemoteRequestProtocol.getDefaultInstance) + val protobufEnc = new ProtobufEncoder + val(enc,dec) = RemoteServer.COMPRESSION_SCHEME match { + case "zlib" => (join(new ZlibEncoder(RemoteServer.ZLIB_COMPRESSION_LEVEL)),join(new ZlibDecoder)) + case _ => (join(),join()) } + val remoteServer = new RemoteServerHandler(name, openChannels, loader, actors, activeObjects) - val stages: Array[ChannelHandler] = - zipCodec.map(codec => Array(ssl,codec.decoder, lenDec, protobufDec, codec.encoder, lenPrep, protobufEnc, remoteServer)) - .getOrElse(Array(ssl,lenDec, protobufDec, lenPrep, protobufEnc, remoteServer)) + val stages = ssl ++ dec ++ join(lenDec, protobufDec) ++ enc ++ join(lenPrep, protobufEnc, remoteServer) + new StaticChannelPipeline(stages: _*) } } @@ -365,17 +382,19 @@ class RemoteServerHandler( } override def channelConnected(ctx : ChannelHandlerContext, e : ChannelStateEvent) { - val sslHandler : SslHandler = ctx.getPipeline.get(classOf[SslHandler]) + if(RemoteServer.SECURE) { + val sslHandler : SslHandler = ctx.getPipeline.get(classOf[SslHandler]) - // Begin handshake. - sslHandler.handshake().addListener( new ChannelFutureListener { - def operationComplete(future : ChannelFuture) : Unit = { - if(future.isSuccess) - openChannels.add(future.getChannel) - else - future.getChannel.close - } - }) + // Begin handshake. + sslHandler.handshake().addListener( new ChannelFutureListener { + def operationComplete(future : ChannelFuture) : Unit = { + if(future.isSuccess) + openChannels.add(future.getChannel) + else + future.getChannel.close + } + }) + } } diff --git a/config/akka-reference.conf b/config/akka-reference.conf index e20a745ca1..c96782406b 100644 --- a/config/akka-reference.conf +++ b/config/akka-reference.conf @@ -64,6 +64,23 @@ compression-scheme = "zlib" # Options: "zlib" (lzf to come), leave out for no compression zlib-compression-level = 6 # Options: 0-9 (1 being fastest and 9 being the most compressed), default is 6 + + service = off #on / off + + #You can either use java command-line options or use the settings below + + #key-store-type = "pkcs12" #Same as -Djavax.net.ssl.keyStoreType=pkcs12 + #key-store = "yourcertificate.p12" #Same as -Djavax.net.ssl.keyStore=yourcertificate.p12 + #key-store-pass = "$PASS" #Same as -Djavax.net.ssl.keyStorePassword=$PASS + + #trust-store-type = "jks" #Same as -Djavax.net.ssl.trustStoreType=jks + #trust-store = "your.keystore" #Same as -Djavax.net.ssl.trustStore=your.keystore + #trust-store-pass = "$PASS" #-Djavax.net.ssl.trustStorePassword=$PASS + + #This can be useful for debugging + debug = off #if on, very verbose debug, same as -Djavax.net.debug=ssl + + service = on name = "default" # The name of the cluster From 64b249ae7e591c5e7d111bf9c54135f684191d15 Mon Sep 17 00:00:00 2001 From: Martin Krasser Date: Mon, 19 Jul 2010 20:45:06 +0200 Subject: [PATCH 029/188] Remove listener from listener list before stopping the listener (avoids warning that stopped listener cannot be notified) --- akka-core/src/main/scala/util/ListenerManagement.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/akka-core/src/main/scala/util/ListenerManagement.scala b/akka-core/src/main/scala/util/ListenerManagement.scala index 7316beba64..8b53cc7d0a 100644 --- a/akka-core/src/main/scala/util/ListenerManagement.scala +++ b/akka-core/src/main/scala/util/ListenerManagement.scala @@ -31,8 +31,8 @@ trait ListenerManagement extends Logging { * The listener is stopped by this method. */ def removeListener(listener: ActorRef) = { - listener.stop listeners.remove(listener) + listener.stop } /** From 96533ee381a63ffbeec39f6bc488cb3eefcd6cdd Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 19 Jul 2010 21:47:28 +0200 Subject: [PATCH 030/188] Fixing case 334 --- .../src/main/scala/akka/SimpleService.scala | 85 ++++++++++++------- .../main/scala/bootstrap/liftweb/Boot.scala | 8 +- .../src/main/webapp/WEB-INF/web.xml | 2 +- config/akka-reference.conf | 4 +- project/build/AkkaProject.scala | 7 +- 5 files changed, 65 insertions(+), 41 deletions(-) diff --git a/akka-samples/akka-sample-lift/src/main/scala/akka/SimpleService.scala b/akka-samples/akka-sample-lift/src/main/scala/akka/SimpleService.scala index 7557404da9..4d20b60448 100644 --- a/akka-samples/akka-sample-lift/src/main/scala/akka/SimpleService.scala +++ b/akka-samples/akka-sample-lift/src/main/scala/akka/SimpleService.scala @@ -1,35 +1,24 @@ package sample.lift -import se.scalablesolutions.akka.actor.{Transactor, Actor} +import se.scalablesolutions.akka.actor._ +import se.scalablesolutions.akka.actor.Actor._ import se.scalablesolutions.akka.config.ScalaConfig._ import se.scalablesolutions.akka.stm.TransactionalMap import se.scalablesolutions.akka.persistence.cassandra.CassandraStorage -import Actor._ - +import scala.xml.Node import java.lang.Integer import javax.ws.rs.{GET, Path, Produces} import java.nio.ByteBuffer +import net.liftweb.http._ +import net.liftweb.http.rest._ -/** - * Try service out by invoking (multiple times): - *
- * curl http://localhost:9998/liftcount
- * 
- * Or browse to the URL from a web browser. - */ -@Path("/liftcount") -class SimpleService extends Transactor { - case object Tick +class SimpleServiceActor extends Transactor { private val KEY = "COUNTER" private var hasStartedTicking = false private lazy val storage = TransactionalMap[String, Integer]() - @GET - @Produces(Array("text/html")) - def count = (self !! Tick).getOrElse(

Error in counter

) - def receive = { - case Tick => if (hasStartedTicking) { + case "Tick" => if (hasStartedTicking) { val counter = storage.get(KEY).get.asInstanceOf[Integer].intValue storage.put(KEY, new Integer(counter + 1)) self.reply(

Tick: {counter + 1}

) @@ -41,27 +30,14 @@ class SimpleService extends Transactor { } } -/** - * Try service out by invoking (multiple times): - *
- * curl http://localhost:9998/persistentliftcount
- * 
- * Or browse to the URL from a web browser. - */ -@Path("/persistentliftcount") -class PersistentSimpleService extends Transactor { +class PersistentServiceActor extends Transactor { - case object Tick private val KEY = "COUNTER" private var hasStartedTicking = false private lazy val storage = CassandraStorage.newMap - @GET - @Produces(Array("text/html")) - def count = (self !! Tick).getOrElse(

Error in counter

) - def receive = { - case Tick => if (hasStartedTicking) { + case "Tick" => if (hasStartedTicking) { val bytes = storage.get(KEY.getBytes).get val counter = ByteBuffer.wrap(bytes).getInt storage.put(KEY.getBytes, ByteBuffer.allocate(4).putInt(counter + 1).array) @@ -73,3 +49,46 @@ class PersistentSimpleService extends Transactor { } } } + + +/** + * Try service out by invoking (multiple times): + *
+ * curl http://localhost:8080/liftcount
+ * 
+ * Or browse to the URL from a web browser. + */ + +object SimpleRestService extends RestHelper { + serve { + case Get("liftcount" :: _, req) => + //Fetch the first actor of type SimpleServiceActor + //Send it the "Tick" message and expect a Node back + val result = for( a <- ActorRegistry.actorsFor(classOf[SimpleServiceActor]).headOption; + r <- (a !! "Tick").as[Node] ) yield r + + //Return either the resulting NodeSeq or a default one + (result getOrElse

Error in counter

).asInstanceOf[Node] + } +} + + +/** + * Try service out by invoking (multiple times): + *
+ * curl http://localhost:8080/persistentliftcount
+ * 
+ * Or browse to the URL from a web browser. + */ + object PersistentRestService extends RestHelper { + serve { + case Get("persistentliftcount" :: _, req) => + //Fetch the first actor of type SimpleServiceActor + //Send it the "Tick" message and expect a Node back + val result = for( a <- ActorRegistry.actorsFor(classOf[PersistentServiceActor]).headOption; + r <- (a !! "Tick").as[Node] ) yield r + + //Return either the resulting NodeSeq or a default one + (result getOrElse

Error in counter

).asInstanceOf[Node] + } + } \ No newline at end of file diff --git a/akka-samples/akka-sample-lift/src/main/scala/bootstrap/liftweb/Boot.scala b/akka-samples/akka-sample-lift/src/main/scala/bootstrap/liftweb/Boot.scala index 0f4a0e9020..2e56a5857a 100644 --- a/akka-samples/akka-sample-lift/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/akka-samples/akka-sample-lift/src/main/scala/bootstrap/liftweb/Boot.scala @@ -13,7 +13,7 @@ import se.scalablesolutions.akka.actor.Actor._ import se.scalablesolutions.akka.config.ScalaConfig._ import se.scalablesolutions.akka.util.Logging -import sample.lift.{PersistentSimpleService, SimpleService} +import sample.lift._ /** * A class that's instantiated early and run. It allows the application @@ -35,6 +35,8 @@ class Boot extends Logging { true } } + LiftRules.statelessDispatchTable.append(SimpleRestService) + LiftRules.statelessDispatchTable.append(PersistentRestService) LiftRules.passNotFoundToChain = true @@ -42,10 +44,10 @@ class Boot extends Logging { SupervisorConfig( RestartStrategy(OneForOne, 3, 100, List(classOf[Exception])), Supervise( - actorOf[SimpleService], + actorOf[SimpleServiceActor], LifeCycle(Permanent)) :: Supervise( - actorOf[PersistentSimpleService], + actorOf[PersistentServiceActor], LifeCycle(Permanent)) :: Nil)) factory.newInstance.start diff --git a/akka-samples/akka-sample-lift/src/main/webapp/WEB-INF/web.xml b/akka-samples/akka-sample-lift/src/main/webapp/WEB-INF/web.xml index 23348604bb..3a1b672cec 100644 --- a/akka-samples/akka-sample-lift/src/main/webapp/WEB-INF/web.xml +++ b/akka-samples/akka-sample-lift/src/main/webapp/WEB-INF/web.xml @@ -13,7 +13,7 @@ AkkaServlet - se.scalablesolutions.akka.rest.AkkaServlet + se.scalablesolutions.akka.comet.AkkaServlet AkkaServlet diff --git a/config/akka-reference.conf b/config/akka-reference.conf index 23412db3d3..c504598e31 100644 --- a/config/akka-reference.conf +++ b/config/akka-reference.conf @@ -57,7 +57,9 @@ akka { hostname = "localhost" port = 9998 filters = ["se.scalablesolutions.akka.security.AkkaSecurityFilterFactory"] # List with all jersey filters to use - resource_packages = ["sample.rest.scala","sample.rest.java","sample.security"] # List with all resource packages for your Jersey services + resource_packages = ["sample.rest.scala", + "sample.rest.java", + "sample.security"] # List with all resource packages for your Jersey services authenticator = "sample.security.BasicAuthenticationService" # The authentication service to use. Need to be overridden (uses sample now) #maxInactiveActivity = 60000 #Atmosphere CometSupport maxInactiveActivity #IF you are using a KerberosAuthenticationActor diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 8020b848af..b642b977ea 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -310,13 +310,14 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { class AkkaSampleChatProject(info: ProjectInfo) extends AkkaDefaultProject(info, deployPath) with CodeFellowPlugin class AkkaSamplePubSubProject(info: ProjectInfo) extends AkkaDefaultProject(info, deployPath) with CodeFellowPlugin - class AkkaSampleLiftProject(info: ProjectInfo) extends AkkaDefaultProject(info, deployPath) with CodeFellowPlugin { + class AkkaSampleLiftProject(info: ProjectInfo) extends DefaultWebProject(info) with DeployProject with CodeFellowPlugin { + def deployPath = AkkaParent.this.deployPath val commons_logging = "commons-logging" % "commons-logging" % "1.1.1" % "compile" val lift = "net.liftweb" % "lift-webkit" % LIFT_VERSION % "compile" val lift_util = "net.liftweb" % "lift-util" % LIFT_VERSION % "compile" val servlet = "javax.servlet" % "servlet-api" % "2.5" % "compile" // testing - val jetty = "org.mortbay.jetty" % "jetty" % "6.1.22" % "test" + val jettyServer = "org.mortbay.jetty" % "jetty" % "6.1.22" % "test" val junit = "junit" % "junit" % "4.5" % "test" } @@ -403,7 +404,7 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------ class AkkaDefaultProject(info: ProjectInfo, val deployPath: Path) extends DefaultProject(info) with DeployProject - trait DeployProject extends DefaultProject { + trait DeployProject { self: Project => // defines where the deployTask copies jars to def deployPath: Path From 02bf9552ca254dc44df3c746cc7fb0310312f2b6 Mon Sep 17 00:00:00 2001 From: Heiko Seeberger Date: Tue, 20 Jul 2010 08:39:18 +0200 Subject: [PATCH 031/188] re #277: Created objects for repositories and dependencies and started transformig akka-core. --- project/build/AkkaProject.scala | 339 +++++++++++++++++++++++--------- 1 file changed, 250 insertions(+), 89 deletions(-) diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 8020b848af..453a60f9df 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -12,23 +12,11 @@ import java.util.jar.Attributes import java.util.jar.Attributes.Name._ import java.io.File -class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { - - // ------------------------------------------------------------ - // project versions - val JERSEY_VERSION = "1.2" - val ATMO_VERSION = "0.6" - val CAMEL_VERSION = "2.4.0" - val SPRING_VERSION = "3.0.3.RELEASE" - val CASSANDRA_VERSION = "0.6.1" - val LIFT_VERSION = "2.0-scala280-SNAPSHOT" - val SCALATEST_VERSION = "1.2-for-scala-2.8.0.final-SNAPSHOT" - val MULTIVERSE_VERSION = "0.6-SNAPSHOT" - - // ------------------------------------------------------------ - lazy val deployPath = info.projectPath / "deploy" - lazy val distPath = info.projectPath / "dist" +class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { + // ------------------------------------------------------------------------------------------------------------------- + // Compile settings + // ------------------------------------------------------------------------------------------------------------------- override def compileOptions = super.compileOptions ++ Seq("-deprecation", "-Xmigration", @@ -37,55 +25,194 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { "-Xwarninit", "-encoding", "utf8") .map(x => CompileOption(x)) - override def javaCompileOptions = JavaCompileOption("-Xlint:unchecked") :: super.javaCompileOptions.toList + // ------------------------------------------------------------------------------------------------------------------- + // Deploy/dist settings + // ------------------------------------------------------------------------------------------------------------------- + lazy val deployPath = info.projectPath / "deploy" + lazy val distPath = info.projectPath / "dist" def distName = "%s_%s-%s.zip".format(name, buildScalaVersion, version) - lazy val dist = zipTask(allArtifacts, "dist", distName) dependsOn (`package`) describedAs("Zips up the distribution.") // ------------------------------------------------------------------------------------------------------------------- - // Repositories + // All repositories *must* go here! See ModuleConigurations below. + // ------------------------------------------------------------------------------------------------------------------- + object Repositories { + lazy val AkkaRepo = MavenRepository("Akka Repository", "http://scalablesolutions.se/akka/repository") + lazy val CodehausSnapshotRepo = MavenRepository("Codehaus Snapshots", "http://snapshots.repository.codehaus.org") + lazy val EmbeddedRepo = MavenRepository("Embedded Repo", (info.projectPath / "embedded-repo").asURL.toString) + lazy val GuiceyFruitRepo = MavenRepository("GuiceyFruit Repo", "http://guiceyfruit.googlecode.com/svn/repo/releases/") + lazy val JBossRepo = MavenRepository("JBoss Repo", "https://repository.jboss.org/nexus/content/groups/public/") + lazy val JavaNetRepo = MavenRepository("java.net Repo", "http://download.java.net/maven/2") + lazy val SonatypeSnapshotRepo = MavenRepository("Sonatype OSS Repo", "http://oss.sonatype.org/content/repositories/releases") + lazy val SunJDMKRepo = MavenRepository("Sun JDMK Repo", "http://wp5.e-taxonomy.eu/cdmlib/mavenrepo") + } + + // ------------------------------------------------------------------------------------------------------------------- + // ModuleConfigurations // Every dependency that cannot be resolved from the built-in repositories (Maven Central and Scala Tools Releases) // must be resolved from a ModuleConfiguration. This will result in a significant acceleration of the update action. // Therefore, if repositories are defined, this must happen as def, not as val. // ------------------------------------------------------------------------------------------------------------------- - val embeddedRepo = "Embedded Repo" at (info.projectPath / "embedded-repo").asURL.toString - val scalaTestModuleConfig = ModuleConfiguration("org.scalatest", ScalaToolsSnapshots) - def guiceyFruitRepo = "GuiceyFruit Repo" at "http://guiceyfruit.googlecode.com/svn/repo/releases/" - val guiceyFruitModuleConfig = ModuleConfiguration("org.guiceyfruit", guiceyFruitRepo) - def jbossRepo = "JBoss Repo" at "https://repository.jboss.org/nexus/content/groups/public/" - val jbossModuleConfig = ModuleConfiguration("org.jboss", jbossRepo) - val nettyModuleConfig = ModuleConfiguration("org.jboss.netty", jbossRepo) - val jgroupsModuleConfig = ModuleConfiguration("jgroups", jbossRepo) - def sunjdmkRepo = "Sun JDMK Repo" at "http://wp5.e-taxonomy.eu/cdmlib/mavenrepo" - val jmsModuleConfig = ModuleConfiguration("javax.jms", sunjdmkRepo) - val jdmkModuleConfig = ModuleConfiguration("com.sun.jdmk", sunjdmkRepo) - val jmxModuleConfig = ModuleConfiguration("com.sun.jmx", sunjdmkRepo) - def javaNetRepo = "java.net Repo" at "http://download.java.net/maven/2" - def sonatypeSnapshotRepo = "Sonatype OSS Repo" at "http://oss.sonatype.org/content/repositories/releases" - val jerseyModuleConfig = ModuleConfiguration("com.sun.jersey", javaNetRepo) - val jerseyContrModuleConfig = ModuleConfiguration("com.sun.jersey.contribs", javaNetRepo) - val grizzlyModuleConfig = ModuleConfiguration("com.sun.grizzly", javaNetRepo) - val atmosphereModuleConfig = ModuleConfiguration("org.atmosphere", sonatypeSnapshotRepo) - val liftModuleConfig = ModuleConfiguration("net.liftweb", ScalaToolsSnapshots) - def codehausSnapshotRepo = "Codehaus Snapshots" at "http://snapshots.repository.codehaus.org" - val multiverseModuleConfig = ModuleConfiguration("org.multiverse", codehausSnapshotRepo) + import Repositories._ + lazy val atmosphereModuleConfig = ModuleConfiguration("org.atmosphere", SonatypeSnapshotRepo) + lazy val grizzlyModuleConfig = ModuleConfiguration("com.sun.grizzly", JavaNetRepo) + lazy val guiceyFruitModuleConfig = ModuleConfiguration("org.guiceyfruit", GuiceyFruitRepo) + lazy val jbossModuleConfig = ModuleConfiguration("org.jboss", JBossRepo) + lazy val jdmkModuleConfig = ModuleConfiguration("com.sun.jdmk", SunJDMKRepo) + lazy val jerseyContrModuleConfig = ModuleConfiguration("com.sun.jersey.contribs", JavaNetRepo) + lazy val jerseyModuleConfig = ModuleConfiguration("com.sun.jersey", JavaNetRepo) + lazy val jgroupsModuleConfig = ModuleConfiguration("jgroups", JBossRepo) + lazy val jmsModuleConfig = ModuleConfiguration("javax.jms", SunJDMKRepo) + lazy val jmxModuleConfig = ModuleConfiguration("com.sun.jmx", SunJDMKRepo) + lazy val liftModuleConfig = ModuleConfiguration("net.liftweb", ScalaToolsSnapshots) + lazy val multiverseModuleConfig = ModuleConfiguration("org.multiverse", CodehausSnapshotRepo) + lazy val nettyModuleConfig = ModuleConfiguration("org.jboss.netty", JBossRepo) + lazy val scalaTestModuleConfig = ModuleConfiguration("org.scalatest", ScalaToolsSnapshots) - // ------------------------------------------------------------ - // project defintions - lazy val akka_core = project("akka-core", "akka-core", new AkkaCoreProject(_)) - lazy val akka_amqp = project("akka-amqp", "akka-amqp", new AkkaAMQPProject(_), akka_core) - lazy val akka_http = project("akka-http", "akka-http", new AkkaHttpProject(_), akka_core, akka_camel) - lazy val akka_camel = project("akka-camel", "akka-camel", new AkkaCamelProject(_), akka_core) + // ------------------------------------------------------------------------------------------------------------------- + // Versions + // ------------------------------------------------------------------------------------------------------------------- + lazy val ATMO_VERSION = "0.6" + lazy val CAMEL_VERSION = "2.4.0" + lazy val CASSANDRA_VERSION = "0.6.1" + lazy val DispatchVersion = "0.7.4" + lazy val JacksonVersion = "1.2.1" + lazy val JERSEY_VERSION = "1.2" + lazy val LIFT_VERSION = "2.0-scala280-SNAPSHOT" + lazy val MULTIVERSE_VERSION = "0.6-SNAPSHOT" + lazy val SCALATEST_VERSION = "1.2-for-scala-2.8.0.final-SNAPSHOT" + lazy val Slf4jVersion = "1.6.0" + lazy val SPRING_VERSION = "3.0.3.RELEASE" + lazy val WerkzVersion = "2.2.1" + + // ------------------------------------------------------------------------------------------------------------------- + // Dependencies + // ------------------------------------------------------------------------------------------------------------------- + object Dependencies { + + // Compile + + lazy val annotation = "javax.annotation" % "jsr250-api" % "1.0" % "compile" + + lazy val aopalliance = "aopalliance" % "aopalliance" % "1.0" % "compile" + + lazy val atmo = "org.atmosphere" % "atmosphere-annotations" % ATMO_VERSION % "compile" + lazy val atmo_jbossweb = "org.atmosphere" % "atmosphere-compat-jbossweb" % ATMO_VERSION % "compile" + lazy val atmo_jersey = "org.atmosphere" % "atmosphere-jersey" % ATMO_VERSION % "compile" + lazy val atmo_runtime = "org.atmosphere" % "atmosphere-runtime" % ATMO_VERSION % "compile" + lazy val atmo_tomcat = "org.atmosphere" % "atmosphere-compat-tomcat" % ATMO_VERSION % "compile" + lazy val atmo_weblogic = "org.atmosphere" % "atmosphere-compat-weblogic" % ATMO_VERSION % "compile" + + lazy val atomikos_transactions = "com.atomikos" % "transactions" % "3.2.3" % "compile" + lazy val atomikos_transactions_api = "com.atomikos" % "transactions-api" % "3.2.3" % "compile" + lazy val atomikos_transactions_jta = "com.atomikos" % "transactions-jta" % "3.2.3" % "compile" + + lazy val camel_core = "org.apache.camel" % "camel-core" % CAMEL_VERSION % "compile" + + lazy val cassandra = "org.apache.cassandra" % "cassandra" % CASSANDRA_VERSION % "compile" + + lazy val commons_codec = "commons-codec" % "commons-codec" % "1.4" % "compile" + + lazy val commons_io = "commons-io" % "commons-io" % "1.4" % "compile" + + lazy val commons_logging = "commons-logging" % "commons-logging" % "1.1.1" % "compile" + + lazy val commons_pool = "commons-pool" % "commons-pool" % "1.5.4" % "compile" + + lazy val configgy = "net.lag" % "configgy" % "2.8.0-1.5.5" % "compile" + + lazy val dispatch_http = "net.databinder" % "dispatch-http_2.8.0" % DispatchVersion % "compile" + lazy val dispatch_json = "net.databinder" % "dispatch-json_2.8.0" % DispatchVersion % "compile" + + lazy val grizzly = "com.sun.grizzly" % "grizzly-comet-webserver" % "1.9.18-i" % "compile" + + lazy val guicey = "org.guiceyfruit" % "guice-all" % "2.0" % "compile" + + lazy val h2_lzf = "voldemort.store.compress" % "h2-lzf" % "1.0" % "compile" + + lazy val jackson = "org.codehaus.jackson" % "jackson-mapper-asl" % JacksonVersion % "compile" + lazy val jackson_core = "org.codehaus.jackson" % "jackson-core-asl" % JacksonVersion % "compile" + lazy val jackson_core_asl = "org.codehaus.jackson" % "jackson-core-asl" % JacksonVersion % "compile" + + lazy val jersey = "com.sun.jersey" % "jersey-core" % JERSEY_VERSION % "compile" + lazy val jersey_json = "com.sun.jersey" % "jersey-json" % JERSEY_VERSION % "compile" + lazy val jersey_server = "com.sun.jersey" % "jersey-server" % JERSEY_VERSION % "compile" + lazy val jersey_contrib = "com.sun.jersey.contribs" % "jersey-scala" % JERSEY_VERSION % "compile" + + lazy val jgroups = "jgroups" % "jgroups" % "2.9.0.GA" % "compile" + + lazy val jsr166x = "jsr166x" % "jsr166x" % "1.0" % "compile" + + lazy val jsr250 = "javax.annotation" % "jsr250-api" % "1.0" % "compile" + + lazy val jsr311 = "javax.ws.rs" % "jsr311-api" % "1.1" % "compile" + + lazy val jta_1_1 = "org.apache.geronimo.specs" % "geronimo-jta_1.1_spec" % "1.1.1" % "compile" intransitive() + + lazy val lift = "net.liftweb" % "lift-webkit" % LIFT_VERSION % "compile" + lazy val lift_util = "net.liftweb" % "lift-util" % LIFT_VERSION % "compile" + + lazy val log4j = "log4j" % "log4j" % "1.2.15" % "compile" + + lazy val mongo = "org.mongodb" % "mongo-java-driver" % "1.4" % "compile" + + lazy val multiverse = "org.multiverse" % "multiverse-alpha" % MULTIVERSE_VERSION % "compile" intransitive() + + lazy val netty = "org.jboss.netty" % "netty" % "3.2.1.Final" % "compile" + + lazy val protobuf = "com.google.protobuf" % "protobuf-java" % "2.3.0" % "compile" + + lazy val rabbit = "com.rabbitmq" % "amqp-client" % "1.8.1" % "compile" + + lazy val redis = "com.redis" % "redisclient" % "2.8.0-1.4" % "compile" + + lazy val sbinary = "sbinary" % "sbinary" % "2.8.0-0.3.1" % "compile" + + lazy val servlet = "javax.servlet" % "servlet-api" % "2.5" % "compile" + + lazy val sjson = "sjson.json" % "sjson" % "0.7-SNAPSHOT-2.8.0" % "compile" + + lazy val slf4j = "org.slf4j" % "slf4j-api" % Slf4jVersion % "compile" + lazy val slf4j_log4j = "org.slf4j" % "slf4j-log4j12" % Slf4jVersion % "compile" + + lazy val spring_beans = "org.springframework" % "spring-beans" % SPRING_VERSION % "compile" + lazy val spring_context = "org.springframework" % "spring-context" % SPRING_VERSION % "compile" + + lazy val stax_api = "javax.xml.stream" % "stax-api" % "1.0-2" % "compile" + + lazy val thrift = "com.facebook" % "thrift" % "r917130" % "compile" + + lazy val werkz = "org.codehaus.aspectwerkz" % "aspectwerkz-nodeps-jdk5" % WerkzVersion % "compile" + lazy val werkz_core = "org.codehaus.aspectwerkz" % "aspectwerkz-jdk5" % WerkzVersion % "compile" + + // Test + + lazy val camel_spring = "org.apache.camel" % "camel-spring" % CAMEL_VERSION % "test" + lazy val cassandra_clhm = "org.apache.cassandra" % "clhm-production" % CASSANDRA_VERSION % "test" + lazy val commons_coll = "commons-collections" % "commons-collections" % "3.2.1" % "test" + lazy val google_coll = "com.google.collections" % "google-collections" % "1.0" % "test" + lazy val high_scale = "org.apache.cassandra" % "high-scale-lib" % CASSANDRA_VERSION % "test" + lazy val jetty = "org.mortbay.jetty" % "jetty" % "6.1.22" % "test" + lazy val junit = "junit" % "junit" % "4.5" % "test" + lazy val mockito = "org.mockito" % "mockito-all" % "1.8.1" % "test" + lazy val scalatest = "org.scalatest" % "scalatest" % SCALATEST_VERSION % "test" + } + + // ------------------------------------------------------------------------------------------------------------------- + // Subprojects + // ------------------------------------------------------------------------------------------------------------------- + lazy val akka_core = project("akka-core", "akka-core", new AkkaCoreProject(_)) + lazy val akka_amqp = project("akka-amqp", "akka-amqp", new AkkaAMQPProject(_), akka_core) + lazy val akka_http = project("akka-http", "akka-http", new AkkaHttpProject(_), akka_core, akka_camel) + lazy val akka_camel = project("akka-camel", "akka-camel", new AkkaCamelProject(_), akka_core) lazy val akka_persistence = project("akka-persistence", "akka-persistence", new AkkaPersistenceParentProject(_)) - lazy val akka_spring = project("akka-spring", "akka-spring", new AkkaSpringProject(_), akka_core, akka_camel) - lazy val akka_jta = project("akka-jta", "akka-jta", new AkkaJTAProject(_), akka_core) - lazy val akka_kernel = project("akka-kernel", "akka-kernel", new AkkaKernelProject(_), - akka_core, akka_http, akka_spring, akka_camel, akka_persistence, akka_amqp) - - // examples - lazy val akka_samples = project("akka-samples", "akka-samples", new AkkaSamplesParentProject(_)) + lazy val akka_spring = project("akka-spring", "akka-spring", new AkkaSpringProject(_), akka_core, akka_camel) + lazy val akka_jta = project("akka-jta", "akka-jta", new AkkaJTAProject(_), akka_core) + lazy val akka_kernel = project("akka-kernel", "akka-kernel", new AkkaKernelProject(_), + akka_core, akka_http, akka_spring, akka_camel, akka_persistence, akka_amqp) + lazy val akka_samples = project("akka-samples", "akka-samples", new AkkaSamplesParentProject(_)) // ------------------------------------------------------------ // Run Akka microkernel using 'sbt run' + use for packaging executable JAR @@ -173,35 +300,39 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { None } dependsOn(dist) describedAs("Run mvn install for artifacts in dist.") - // ------------------------------------------------------------ - // subprojects + // ------------------------------------------------------------------------------------------------------------------- + // akka-core subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaCoreProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { - val netty = "org.jboss.netty" % "netty" % "3.2.1.Final" % "compile" - val commons_codec = "commons-codec" % "commons-codec" % "1.4" % "compile" - val commons_io = "commons-io" % "commons-io" % "1.4" % "compile" - val dispatch_json = "net.databinder" % "dispatch-json_2.8.0" % "0.7.4" % "compile" - val dispatch_http = "net.databinder" % "dispatch-http_2.8.0" % "0.7.4" % "compile" - val sjson = "sjson.json" % "sjson" % "0.7-SNAPSHOT-2.8.0" % "compile" - val sbinary = "sbinary" % "sbinary" % "2.8.0-0.3.1" % "compile" - val jackson = "org.codehaus.jackson" % "jackson-mapper-asl" % "1.2.1" % "compile" - val jackson_core = "org.codehaus.jackson" % "jackson-core-asl" % "1.2.1" % "compile" - val h2_lzf = "voldemort.store.compress" % "h2-lzf" % "1.0" % "compile" - val jsr166x = "jsr166x" % "jsr166x" % "1.0" % "compile" - val jta_1_1 = "org.apache.geronimo.specs" % "geronimo-jta_1.1_spec" % "1.1.1" % "compile" intransitive() - val werkz = "org.codehaus.aspectwerkz" % "aspectwerkz-nodeps-jdk5" % "2.2.1" % "compile" - val werkz_core = "org.codehaus.aspectwerkz" % "aspectwerkz-jdk5" % "2.2.1" % "compile" - val configgy = "net.lag" % "configgy" % "2.8.0-1.5.5" % "compile" - val guicey = "org.guiceyfruit" % "guice-all" % "2.0" % "compile" - val aopalliance = "aopalliance" % "aopalliance" % "1.0" % "compile" - val protobuf = "com.google.protobuf" % "protobuf-java" % "2.3.0" % "compile" - val multiverse = "org.multiverse" % "multiverse-alpha" % MULTIVERSE_VERSION % "compile" intransitive() - val jgroups = "jgroups" % "jgroups" % "2.9.0.GA" % "compile" + val netty = Dependencies.netty + val commons_codec = Dependencies.commons_codec + val commons_io = Dependencies.commons_io + val dispatch_json = Dependencies.dispatch_json + val dispatch_http = Dependencies.dispatch_http + val sjson = Dependencies.sjson + val sbinary = Dependencies.sbinary + val jackson = Dependencies.jackson + val jackson_core = Dependencies.jackson_core + val h2_lzf = Dependencies.h2_lzf + val jsr166x = Dependencies.jsr166x + val jta_1_1 = Dependencies.jta_1_1 + val werkz = Dependencies.werkz + val werkz_core = Dependencies.werkz_core + val configgy = Dependencies.configgy + val guicey = Dependencies.guicey + val aopalliance = Dependencies.aopalliance + val protobuf = Dependencies.protobuf + val multiverse = Dependencies.multiverse + val jgroups = Dependencies.jgroups // testing - val scalatest = "org.scalatest" % "scalatest" % SCALATEST_VERSION % "test" - val junit = "junit" % "junit" % "4.5" % "test" + val scalatest = Dependencies.scalatest + val junit = Dependencies.junit } + // ------------------------------------------------------------------------------------------------------------------- + // akka-amqp subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaAMQPProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val commons_io = "commons-io" % "commons-io" % "1.4" % "compile" val rabbit = "com.rabbitmq" % "amqp-client" % "1.8.1" % "compile" @@ -212,6 +343,9 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { val junit = "junit" % "junit" % "4.5" % "test" } + // ------------------------------------------------------------------------------------------------------------------- + // akka-http subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaHttpProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val jackson_core_asl = "org.codehaus.jackson" % "jackson-core-asl" % "1.2.1" % "compile" val stax_api = "javax.xml.stream" % "stax-api" % "1.0-2" % "compile" @@ -237,26 +371,55 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { val mockito = "org.mockito" % "mockito-all" % "1.8.1" % "test" } + // ------------------------------------------------------------------------------------------------------------------- + // akka-camel subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaCamelProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val camel_core = "org.apache.camel" % "camel-core" % CAMEL_VERSION % "compile" } + // ------------------------------------------------------------------------------------------------------------------- + // akka-persistence subproject + // ------------------------------------------------------------------------------------------------------------------- + class AkkaPersistenceParentProject(info: ProjectInfo) extends ParentProject(info) { + lazy val akka_persistence_common = project("akka-persistence-common", "akka-persistence-common", + new AkkaPersistenceCommonProject(_), akka_core) + lazy val akka_persistence_redis = project("akka-persistence-redis", "akka-persistence-redis", + new AkkaRedisProject(_), akka_persistence_common) + lazy val akka_persistence_mongo = project("akka-persistence-mongo", "akka-persistence-mongo", + new AkkaMongoProject(_), akka_persistence_common) + lazy val akka_persistence_cassandra = project("akka-persistence-cassandra", "akka-persistence-cassandra", + new AkkaCassandraProject(_), akka_persistence_common) + } + + // ------------------------------------------------------------------------------------------------------------------- + // akka-persistence-common subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaPersistenceCommonProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val thrift = "com.facebook" % "thrift" % "r917130" % "compile" val commons_pool = "commons-pool" % "commons-pool" % "1.5.4" % "compile" } + // ------------------------------------------------------------------------------------------------------------------- + // akka-persistence-redis subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaRedisProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val redis = "com.redis" % "redisclient" % "2.8.0-1.4" % "compile" val commons_codec = "commons-codec" % "commons-codec" % "1.4" % "compile" override def testOptions = TestFilter((name: String) => name.endsWith("Test")) :: Nil } + // ------------------------------------------------------------------------------------------------------------------- + // akka-persistence-mongo subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaMongoProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val mongo = "org.mongodb" % "mongo-java-driver" % "1.4" % "compile" override def testOptions = TestFilter((name: String) => name.endsWith("Test")) :: Nil } + // ------------------------------------------------------------------------------------------------------------------- + // akka-persistence-cassandra subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaCassandraProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val cassandra = "org.apache.cassandra" % "cassandra" % CASSANDRA_VERSION % "compile" val slf4j = "org.slf4j" % "slf4j-api" % "1.6.0" % "compile" @@ -270,19 +433,14 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { override def testOptions = TestFilter((name: String) => name.endsWith("Test")) :: Nil } - class AkkaPersistenceParentProject(info: ProjectInfo) extends ParentProject(info) { - lazy val akka_persistence_common = project("akka-persistence-common", "akka-persistence-common", - new AkkaPersistenceCommonProject(_), akka_core) - lazy val akka_persistence_redis = project("akka-persistence-redis", "akka-persistence-redis", - new AkkaRedisProject(_), akka_persistence_common) - lazy val akka_persistence_mongo = project("akka-persistence-mongo", "akka-persistence-mongo", - new AkkaMongoProject(_), akka_persistence_common) - lazy val akka_persistence_cassandra = project("akka-persistence-cassandra", "akka-persistence-cassandra", - new AkkaCassandraProject(_), akka_persistence_common) - } - + // ------------------------------------------------------------------------------------------------------------------- + // akka-kernel subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaKernelProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) + // ------------------------------------------------------------------------------------------------------------------- + // akka-spring subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaSpringProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val spring_beans = "org.springframework" % "spring-beans" % SPRING_VERSION % "compile" val spring_context = "org.springframework" % "spring-context" % SPRING_VERSION % "compile" @@ -293,6 +451,9 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { val junit = "junit" % "junit" % "4.5" % "test" } + // ------------------------------------------------------------------------------------------------------------------- + // akka-jta subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaJTAProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val atomikos_transactions = "com.atomikos" % "transactions" % "3.2.3" % "compile" val atomikos_transactions_jta = "com.atomikos" % "transactions-jta" % "3.2.3" % "compile" @@ -303,7 +464,7 @@ class AkkaParent(info: ProjectInfo) extends DefaultProject(info) { // ================= EXAMPLES ================== class AkkaSampleAntsProject(info: ProjectInfo) extends DefaultSpdeProject(info) with CodeFellowPlugin { - val scalaToolsSnapshots = ScalaToolsSnapshots +// val scalaToolsSnapshots = ScalaToolsSnapshots override def spdeSourcePath = mainSourcePath / "spde" } From 995cab9e95335792e7d2949e9b38bcb0d1a16203 Mon Sep 17 00:00:00 2001 From: Heiko Seeberger Date: Tue, 20 Jul 2010 09:45:09 +0200 Subject: [PATCH 032/188] closes #277: Transformed all subprojects to use Dependencies object; also reworked Plugins.scala accordingly. --- project/build/AkkaProject.scala | 151 +++++++++++++++++--------------- project/plugins/Plugins.scala | 30 +++++-- 2 files changed, 103 insertions(+), 78 deletions(-) diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 778de037c8..89685dffd6 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -70,6 +70,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val multiverseModuleConfig = ModuleConfiguration("org.multiverse", CodehausSnapshotRepo) lazy val nettyModuleConfig = ModuleConfiguration("org.jboss.netty", JBossRepo) lazy val scalaTestModuleConfig = ModuleConfiguration("org.scalatest", ScalaToolsSnapshots) + lazy val embeddedRepo = EmbeddedRepo // This is the only exception, because the embedded repo is fast! // ------------------------------------------------------------------------------------------------------------------- // Versions @@ -194,7 +195,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val commons_coll = "commons-collections" % "commons-collections" % "3.2.1" % "test" lazy val google_coll = "com.google.collections" % "google-collections" % "1.0" % "test" lazy val high_scale = "org.apache.cassandra" % "high-scale-lib" % CASSANDRA_VERSION % "test" - lazy val jetty = "org.mortbay.jetty" % "jetty" % "6.1.22" % "test" + lazy val jettyServer = "org.mortbay.jetty" % "jetty" % "6.1.22" % "test" lazy val junit = "junit" % "junit" % "4.5" % "test" lazy val mockito = "org.mockito" % "mockito-all" % "1.8.1" % "test" lazy val scalatest = "org.scalatest" % "scalatest" % SCALATEST_VERSION % "test" @@ -304,78 +305,78 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // akka-core subproject // ------------------------------------------------------------------------------------------------------------------- class AkkaCoreProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { - val netty = Dependencies.netty + val aopalliance = Dependencies.aopalliance val commons_codec = Dependencies.commons_codec val commons_io = Dependencies.commons_io - val dispatch_json = Dependencies.dispatch_json + val configgy = Dependencies.configgy val dispatch_http = Dependencies.dispatch_http - val sjson = Dependencies.sjson - val sbinary = Dependencies.sbinary + val dispatch_json = Dependencies.dispatch_json + val guicey = Dependencies.guicey + val h2_lzf = Dependencies.h2_lzf val jackson = Dependencies.jackson val jackson_core = Dependencies.jackson_core - val h2_lzf = Dependencies.h2_lzf + val jgroups = Dependencies.jgroups val jsr166x = Dependencies.jsr166x val jta_1_1 = Dependencies.jta_1_1 + val multiverse = Dependencies.multiverse + val netty = Dependencies.netty + val protobuf = Dependencies.protobuf + val sbinary = Dependencies.sbinary + val sjson = Dependencies.sjson val werkz = Dependencies.werkz val werkz_core = Dependencies.werkz_core - val configgy = Dependencies.configgy - val guicey = Dependencies.guicey - val aopalliance = Dependencies.aopalliance - val protobuf = Dependencies.protobuf - val multiverse = Dependencies.multiverse - val jgroups = Dependencies.jgroups // testing - val scalatest = Dependencies.scalatest val junit = Dependencies.junit + val scalatest = Dependencies.scalatest } // ------------------------------------------------------------------------------------------------------------------- // akka-amqp subproject // ------------------------------------------------------------------------------------------------------------------- class AkkaAMQPProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { - val commons_io = "commons-io" % "commons-io" % "1.4" % "compile" - val rabbit = "com.rabbitmq" % "amqp-client" % "1.8.1" % "compile" + val commons_io = Dependencies.commons_io + val rabbit = Dependencies.rabbit // testing - val multiverse = "org.multiverse" % "multiverse-alpha" % MULTIVERSE_VERSION % "test" intransitive() - val scalatest = "org.scalatest" % "scalatest" % SCALATEST_VERSION % "test" - val junit = "junit" % "junit" % "4.5" % "test" + val junit = Dependencies.junit + val multiverse = Dependencies.multiverse + val scalatest = Dependencies.scalatest } // ------------------------------------------------------------------------------------------------------------------- // akka-http subproject // ------------------------------------------------------------------------------------------------------------------- class AkkaHttpProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { - val jackson_core_asl = "org.codehaus.jackson" % "jackson-core-asl" % "1.2.1" % "compile" - val stax_api = "javax.xml.stream" % "stax-api" % "1.0-2" % "compile" - val servlet = "javax.servlet" % "servlet-api" % "2.5" % "compile" - val jersey = "com.sun.jersey" % "jersey-core" % JERSEY_VERSION % "compile" - val jersey_server = "com.sun.jersey" % "jersey-server" % JERSEY_VERSION % "compile" - val jersey_json = "com.sun.jersey" % "jersey-json" % JERSEY_VERSION % "compile" - val jersey_contrib = "com.sun.jersey.contribs" % "jersey-scala" % JERSEY_VERSION % "compile" - val jsr311 = "javax.ws.rs" % "jsr311-api" % "1.1" % "compile" - val grizzly = "com.sun.grizzly" % "grizzly-comet-webserver" % "1.9.18-i" % "compile" - val atmo = "org.atmosphere" % "atmosphere-annotations" % ATMO_VERSION % "compile" - val atmo_jersey = "org.atmosphere" % "atmosphere-jersey" % ATMO_VERSION % "compile" - val atmo_runtime = "org.atmosphere" % "atmosphere-runtime" % ATMO_VERSION % "compile" - val atmo_tomcat = "org.atmosphere" % "atmosphere-compat-tomcat" % ATMO_VERSION % "compile" - val atmo_weblogic = "org.atmosphere" % "atmosphere-compat-weblogic" % ATMO_VERSION % "compile" - val atmo_jbossweb = "org.atmosphere" % "atmosphere-compat-jbossweb" % ATMO_VERSION % "compile" - val commons_logging = "commons-logging" % "commons-logging" % "1.1.1" % "compile" - val annotation = "javax.annotation" % "jsr250-api" % "1.0" % "compile" + val annotation = Dependencies.annotation + val atmo = Dependencies.atmo + val atmo_jbossweb = Dependencies.atmo_jbossweb + val atmo_jersey = Dependencies.atmo_jersey + val atmo_runtime = Dependencies.atmo_runtime + val atmo_tomcat = Dependencies.atmo_tomcat + val atmo_weblogic = Dependencies.atmo_weblogic + val commons_logging = Dependencies.commons_logging + val grizzly = Dependencies.grizzly + val jackson_core_asl = Dependencies.jackson_core_asl + val jersey = Dependencies.jersey + val jersey_contrib = Dependencies.jersey_contrib + val jersey_json = Dependencies.jersey_json + val jersey_server = Dependencies.jersey_server + val jsr311 = Dependencies.jsr311 + val servlet = Dependencies.servlet + val stax_api = Dependencies.stax_api // testing - val scalatest = "org.scalatest" % "scalatest" % SCALATEST_VERSION % "test" - val junit = "junit" % "junit" % "4.5" % "test" - val mockito = "org.mockito" % "mockito-all" % "1.8.1" % "test" + val junit = Dependencies.junit + val mockito = Dependencies.mockito + val scalatest = Dependencies.scalatest } // ------------------------------------------------------------------------------------------------------------------- // akka-camel subproject // ------------------------------------------------------------------------------------------------------------------- class AkkaCamelProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { - val camel_core = "org.apache.camel" % "camel-core" % CAMEL_VERSION % "compile" + val camel_core = Dependencies.camel_core } // ------------------------------------------------------------------------------------------------------------------- @@ -396,16 +397,17 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // akka-persistence-common subproject // ------------------------------------------------------------------------------------------------------------------- class AkkaPersistenceCommonProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { - val thrift = "com.facebook" % "thrift" % "r917130" % "compile" - val commons_pool = "commons-pool" % "commons-pool" % "1.5.4" % "compile" + val commons_pool = Dependencies.commons_pool + val thrift = Dependencies.thrift } // ------------------------------------------------------------------------------------------------------------------- // akka-persistence-redis subproject // ------------------------------------------------------------------------------------------------------------------- class AkkaRedisProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { - val redis = "com.redis" % "redisclient" % "2.8.0-1.4" % "compile" - val commons_codec = "commons-codec" % "commons-codec" % "1.4" % "compile" + val commons_codec = Dependencies.commons_codec + val redis = Dependencies.redis + override def testOptions = TestFilter((name: String) => name.endsWith("Test")) :: Nil } @@ -413,7 +415,8 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // akka-persistence-mongo subproject // ------------------------------------------------------------------------------------------------------------------- class AkkaMongoProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { - val mongo = "org.mongodb" % "mongo-java-driver" % "1.4" % "compile" + val mongo = Dependencies.mongo + override def testOptions = TestFilter((name: String) => name.endsWith("Test")) :: Nil } @@ -421,15 +424,17 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // akka-persistence-cassandra subproject // ------------------------------------------------------------------------------------------------------------------- class AkkaCassandraProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { - val cassandra = "org.apache.cassandra" % "cassandra" % CASSANDRA_VERSION % "compile" - val slf4j = "org.slf4j" % "slf4j-api" % "1.6.0" % "compile" - val slf4j_log4j = "org.slf4j" % "slf4j-log4j12" % "1.6.0" % "compile" - val log4j = "log4j" % "log4j" % "1.2.15" % "compile" + val cassandra = Dependencies.cassandra + val log4j = Dependencies.log4j + val slf4j = Dependencies.slf4j + val slf4j_log4j = Dependencies.slf4j_log4j + // testing - val high_scale = "org.apache.cassandra" % "high-scale-lib" % CASSANDRA_VERSION % "test" - val cassandra_clhm = "org.apache.cassandra" % "clhm-production" % CASSANDRA_VERSION % "test" - val commons_coll = "commons-collections" % "commons-collections" % "3.2.1" % "test" - val google_coll = "com.google.collections" % "google-collections" % "1.0" % "test" + val cassandra_clhm = Dependencies.cassandra_clhm + val commons_coll = Dependencies.commons_coll + val google_coll = Dependencies.google_coll + val high_scale = Dependencies.high_scale + override def testOptions = TestFilter((name: String) => name.endsWith("Test")) :: Nil } @@ -442,24 +447,24 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // akka-spring subproject // ------------------------------------------------------------------------------------------------------------------- class AkkaSpringProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { - val spring_beans = "org.springframework" % "spring-beans" % SPRING_VERSION % "compile" - val spring_context = "org.springframework" % "spring-context" % SPRING_VERSION % "compile" + val spring_beans = Dependencies.spring_beans + val spring_context = Dependencies.spring_context // testing - val camel_spring = "org.apache.camel" % "camel-spring" % CAMEL_VERSION % "test" - val scalatest = "org.scalatest" % "scalatest" % SCALATEST_VERSION % "test" - val junit = "junit" % "junit" % "4.5" % "test" + val camel_spring = Dependencies.camel_spring + val junit = Dependencies.junit + val scalatest = Dependencies.scalatest } // ------------------------------------------------------------------------------------------------------------------- // akka-jta subproject // ------------------------------------------------------------------------------------------------------------------- class AkkaJTAProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { - val atomikos_transactions = "com.atomikos" % "transactions" % "3.2.3" % "compile" - val atomikos_transactions_jta = "com.atomikos" % "transactions-jta" % "3.2.3" % "compile" - val atomikos_transactions_api = "com.atomikos" % "transactions-api" % "3.2.3" % "compile" + val atomikos_transactions = Dependencies.atomikos_transactions + val atomikos_transactions_api = Dependencies.atomikos_transactions_api + val atomikos_transactions_jta = Dependencies.atomikos_transactions_jta + val jta_1_1 = Dependencies.jta_1_1 //val atomikos_transactions_util = "com.atomikos" % "transactions-util" % "3.2.3" % "compile" - val jta_spec = "org.apache.geronimo.specs" % "geronimo-jta_1.1_spec" % "1.1.1" % "compile" intransitive() } // ================= EXAMPLES ================== @@ -472,14 +477,16 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { class AkkaSamplePubSubProject(info: ProjectInfo) extends AkkaDefaultProject(info, deployPath) with CodeFellowPlugin class AkkaSampleLiftProject(info: ProjectInfo) extends DefaultWebProject(info) with DeployProject with CodeFellowPlugin { - def deployPath = AkkaParent.this.deployPath - val commons_logging = "commons-logging" % "commons-logging" % "1.1.1" % "compile" - val lift = "net.liftweb" % "lift-webkit" % LIFT_VERSION % "compile" - val lift_util = "net.liftweb" % "lift-util" % LIFT_VERSION % "compile" - val servlet = "javax.servlet" % "servlet-api" % "2.5" % "compile" + val commons_logging = Dependencies.commons_logging + val lift = Dependencies.lift + val lift_util = Dependencies.lift_util + val servlet = Dependencies.servlet + // testing - val jettyServer = "org.mortbay.jetty" % "jetty" % "6.1.22" % "test" - val junit = "junit" % "junit" % "4.5" % "test" + val jettyServer = Dependencies.jettyServer + val junit = Dependencies.junit + + def deployPath = AkkaParentProject.this.deployPath } class AkkaSampleRestJavaProject(info: ProjectInfo) extends AkkaDefaultProject(info, deployPath) with CodeFellowPlugin @@ -487,7 +494,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { class AkkaSampleRemoteProject(info: ProjectInfo) extends AkkaDefaultProject(info, deployPath) with CodeFellowPlugin class AkkaSampleRestScalaProject(info: ProjectInfo) extends AkkaDefaultProject(info, deployPath) with CodeFellowPlugin { - val jsr311 = "javax.ws.rs" % "jsr311-api" % "1.1.1" % "compile" + val jsr311 = Dependencies.jsr311 } class AkkaSampleCamelProject(info: ProjectInfo) extends AkkaDefaultProject(info, deployPath) with CodeFellowPlugin { @@ -508,9 +515,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { } class AkkaSampleSecurityProject(info: ProjectInfo) extends AkkaDefaultProject(info, deployPath) with CodeFellowPlugin { - val jsr311 = "javax.ws.rs" % "jsr311-api" % "1.1.1" % "compile" - val jsr250 = "javax.annotation" % "jsr250-api" % "1.0" % "compile" - val commons_codec = "commons-codec" % "commons-codec" % "1.4" % "compile" + val commons_codec = Dependencies.commons_codec + val jsr250 = Dependencies.jsr250 + val jsr311 = Dependencies.jsr311 } class AkkaSamplesParentProject(info: ProjectInfo) extends ParentProject(info) { diff --git a/project/plugins/Plugins.scala b/project/plugins/Plugins.scala index 92b9943998..b19b0ebf8c 100644 --- a/project/plugins/Plugins.scala +++ b/project/plugins/Plugins.scala @@ -1,10 +1,28 @@ import sbt._ class Plugins(info: ProjectInfo) extends PluginDefinition(info) { - val databinderRepo = "Databinder Repository" at "http://databinder.net/repo" - val embeddedRepo = "Embedded Repo" at (info.projectPath / "embedded-repo").asURL.toString - val spdeSbt = "us.technically.spde" % "spde-sbt-plugin" % "0.4.1" - val codeFellow = "de.tuxed" % "codefellow-plugin" % "0.3" // for code completion and more in VIM -// val repo = "GH-pages repo" at "http://mpeltonen.github.com/maven/" -// val idea = "com.github.mpeltonen" % "sbt-idea-plugin" % "0.1-SNAPSHOT" + + // ------------------------------------------------------------------------------------------------------------------- + // All repositories *must* go here! See ModuleConigurations below. + // ------------------------------------------------------------------------------------------------------------------- + object Repositories { + lazy val DatabinderRepo = "Databinder Repository" at "http://databinder.net/repo" + lazy val EmbeddedRepo = "Embedded Repo" at (info.projectPath / "embedded-repo").asURL.toString + } + + // ------------------------------------------------------------------------------------------------------------------- + // ModuleConfigurations + // Every dependency that cannot be resolved from the built-in repositories (Maven Central and Scala Tools Releases) + // must be resolved from a ModuleConfiguration. This will result in a significant acceleration of the update action. + // Therefore, if repositories are defined, this must happen as def, not as val. + // ------------------------------------------------------------------------------------------------------------------- + import Repositories._ + lazy val codeFellowModuleConfig = ModuleConfiguration("de.tuxed", EmbeddedRepo) + lazy val spdeModuleConfig = ModuleConfiguration("us.technically.spde", DatabinderRepo) + + // ------------------------------------------------------------------------------------------------------------------- + // Dependencies + // ------------------------------------------------------------------------------------------------------------------- + lazy val codeFellow = "de.tuxed" % "codefellow-plugin" % "0.3" // for code completion and more in VIM + lazy val spdeSbt = "us.technically.spde" % "spde-sbt-plugin" % "0.4.1" } From 70bf8b2c4e26f31a0b7282826d3323b52574f428 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Tue, 20 Jul 2010 12:54:33 +0200 Subject: [PATCH 033/188] Adding become to Actor --- akka-core/src/main/scala/actor/Actor.scala | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/akka-core/src/main/scala/actor/Actor.scala b/akka-core/src/main/scala/actor/Actor.scala index 76adf9c729..244fd8fbc7 100644 --- a/akka-core/src/main/scala/actor/Actor.scala +++ b/akka-core/src/main/scala/actor/Actor.scala @@ -414,6 +414,14 @@ trait Actor extends Logging { * Is the actor able to handle the message passed in as arguments? */ def isDefinedAt(message: Any): Boolean = base.isDefinedAt(message) + + /** One of the fundamental methods of the ActorsModel + * Actor assumes a new behavior + */ + def become(behavior: Option[Receive]) { + self.hotswap = behavior + self.checkReceiveTimeout // FIXME : how to reschedule receivetimeout on hotswap? + } // ========================================= // ==== INTERNAL IMPLEMENTATION DETAILS ==== @@ -427,7 +435,7 @@ trait Actor extends Logging { } private val lifeCycles: Receive = { - case HotSwap(code) => self.hotswap = code; self.checkReceiveTimeout // FIXME : how to reschedule receivetimeout on hotswap? + case HotSwap(code) => become(code) case Exit(dead, reason) => self.handleTrapExit(dead, reason) case Link(child) => self.link(child) case Unlink(child) => self.unlink(child) From e289bacfdd62573e711f160867b07c9013fe3314 Mon Sep 17 00:00:00 2001 From: Martin Krasser Date: Tue, 20 Jul 2010 18:48:34 +0200 Subject: [PATCH 034/188] Minor changes in akka-sample-camel --- .../src/main/scala/Actors.scala | 8 +++- .../src/main/scala/Boot.scala | 38 +++++++++---------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/akka-samples/akka-sample-camel/src/main/scala/Actors.scala b/akka-samples/akka-sample-camel/src/main/scala/Actors.scala index 275dc6b094..f3b50d9c6e 100644 --- a/akka-samples/akka-sample-camel/src/main/scala/Actors.scala +++ b/akka-samples/akka-sample-camel/src/main/scala/Actors.scala @@ -117,14 +117,18 @@ class HttpConsumer(producer: ActorRef) extends Actor with Consumer { def endpointUri = "jetty:http://0.0.0.0:8875/" protected def receive = { - // only keep Exchange.HTTP_PATH message header (which needed by bridge endpoint) - case msg: Message => producer forward msg.setHeaders(msg.headers(Set(Exchange.HTTP_PATH))) + case msg => producer forward msg } } class HttpProducer(transformer: ActorRef) extends Actor with Producer { def endpointUri = "jetty://http://akkasource.org/?bridgeEndpoint=true" + override protected def receiveBeforeProduce = { + // only keep Exchange.HTTP_PATH message header (which needed by bridge endpoint) + case msg: Message => msg.setHeaders(msg.headers(Set(Exchange.HTTP_PATH))) + } + override protected def receiveAfterProduce = { // do not reply but forward result to transformer case msg => transformer forward msg diff --git a/akka-samples/akka-sample-camel/src/main/scala/Boot.scala b/akka-samples/akka-sample-camel/src/main/scala/Boot.scala index 3894c24cca..b8a483b55f 100644 --- a/akka-samples/akka-sample-camel/src/main/scala/Boot.scala +++ b/akka-samples/akka-sample-camel/src/main/scala/Boot.scala @@ -16,16 +16,6 @@ import se.scalablesolutions.akka.config.ScalaConfig._ */ class Boot { - // ----------------------------------------------------------------------- - // Create CamelContext with Spring-based registry and custom route builder - // ----------------------------------------------------------------------- - - val context = new ClassPathXmlApplicationContext("/context-boot.xml", getClass) - val registry = new ApplicationContextRegistry(context) - - CamelContextManager.init(new DefaultCamelContext(registry)) - CamelContextManager.context.addRoutes(new CustomRouteBuilder) - // ----------------------------------------------------------------------- // Basic example // ----------------------------------------------------------------------- @@ -41,9 +31,17 @@ class Boot { // Supervise(actorOf[Consumer2], LifeCycle(Permanent)) :: Nil)) // ----------------------------------------------------------------------- - // Tranformer example + // Custom Camel route example // ----------------------------------------------------------------------- + // Create CamelContext and a Spring-based registry + val context = new ClassPathXmlApplicationContext("/context-boot.xml", getClass) + val registry = new ApplicationContextRegistry(context) + + // Use a custom Camel context and a custom touter builder + CamelContextManager.init(new DefaultCamelContext(registry)) + CamelContextManager.context.addRoutes(new CustomRouteBuilder) + val producer = actorOf[Producer1] val mediator = actorOf(new Transformer(producer)) val consumer = actorOf(new Consumer3(mediator)) @@ -52,12 +50,20 @@ class Boot { mediator.start consumer.start + // ----------------------------------------------------------------------- + // Non-blocking consumer-producer example (Akka homepage transformation) + // ----------------------------------------------------------------------- + + val httpTransformer = actorOf(new HttpTransformer).start + val httpProducer = actorOf(new HttpProducer(httpTransformer)).start + val httpConsumer = actorOf(new HttpConsumer(httpProducer)).start + // ----------------------------------------------------------------------- // Publish subscribe examples // ----------------------------------------------------------------------- // - // Cometd example commented out because camel-cometd is broken in Camel 2.3 + // Cometd example commented out because camel-cometd is broken since Camel 2.3 // //val cometdUri = "cometd://localhost:8111/test/abc?baseResource=file:target" @@ -79,14 +85,6 @@ class Boot { actorOf[Consumer4].start // POSTing "stop" to http://0.0.0.0:8877/camel/stop stops and unpublishes this actor actorOf[Consumer5].start // POSTing any msg to http://0.0.0.0:8877/camel/start starts and published Consumer4 again. - // ----------------------------------------------------------------------- - // Non-blocking consumer-producer example (Akka homepage transformation) - // ----------------------------------------------------------------------- - - val nbResponder = actorOf(new HttpTransformer).start - val nbProducer = actorOf(new HttpProducer(nbResponder)).start - val nbConsumer = actorOf(new HttpConsumer(nbProducer)).start - // ----------------------------------------------------------------------- // Active object example // ----------------------------------------------------------------------- From 9f4045888d0a2a83f507ebf4613200eaf03bdae3 Mon Sep 17 00:00:00 2001 From: Heiko Seeberger Date: Tue, 20 Jul 2010 12:01:02 +0200 Subject: [PATCH 035/188] closes #31: Some fixes to the O-S-G-i settings in SBT project file; also deleted superfluous bnd4sbt.jar in project/build/lib directory. --- project/build/AkkaProject.scala | 151 +++++++++++++++++++------------- project/build/lib/bnd4sbt.jar | Bin 8092 -> 0 bytes 2 files changed, 91 insertions(+), 60 deletions(-) delete mode 100644 project/build/lib/bnd4sbt.jar diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index d1e125f07d..b24f477d75 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -16,6 +16,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // Compile settings // ------------------------------------------------------------------------------------------------------------------- + override def compileOptions = super.compileOptions ++ Seq("-deprecation", "-Xmigration", @@ -29,6 +30,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // Deploy/dist settings // ------------------------------------------------------------------------------------------------------------------- + lazy val deployPath = info.projectPath / "deploy" lazy val distPath = info.projectPath / "dist" def distName = "%s_%s-%s.zip".format(name, buildScalaVersion, version) @@ -37,6 +39,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // All repositories *must* go here! See ModuleConigurations below. // ------------------------------------------------------------------------------------------------------------------- + object Repositories { lazy val AkkaRepo = MavenRepository("Akka Repository", "http://scalablesolutions.se/akka/repository") lazy val CodehausSnapshotRepo = MavenRepository("Codehaus Snapshots", "http://snapshots.repository.codehaus.org") @@ -54,6 +57,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // must be resolved from a ModuleConfiguration. This will result in a significant acceleration of the update action. // Therefore, if repositories are defined, this must happen as def, not as val. // ------------------------------------------------------------------------------------------------------------------- + import Repositories._ lazy val atmosphereModuleConfig = ModuleConfiguration("org.atmosphere", SonatypeSnapshotRepo) lazy val grizzlyModuleConfig = ModuleConfiguration("com.sun.grizzly", JavaNetRepo) @@ -74,6 +78,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // Versions // ------------------------------------------------------------------------------------------------------------------- + lazy val ATMO_VERSION = "0.6" lazy val CAMEL_VERSION = "2.4.0" lazy val CASSANDRA_VERSION = "0.6.1" @@ -90,6 +95,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // Dependencies // ------------------------------------------------------------------------------------------------------------------- + object Dependencies { // Compile @@ -149,16 +155,16 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val jsr311 = "javax.ws.rs" % "jsr311-api" % "1.1" % "compile" - lazy val jta_1_1 = "org.apache.geronimo.specs" % "geronimo-jta_1.1_spec" % "1.1.1" % "compile" intransitive() + lazy val jta_1_1 = "org.apache.geronimo.specs" % "geronimo-jta_1.1_spec" % "1.1.1" % "compile" intransitive - lazy val lift = "net.liftweb" % "lift-webkit" % LIFT_VERSION % "compile" - lazy val lift_util = "net.liftweb" % "lift-util" % LIFT_VERSION % "compile" + lazy val lift_util = "net.liftweb" % "lift-util" % LIFT_VERSION % "compile" + lazy val lift_webkit = "net.liftweb" % "lift-webkit" % LIFT_VERSION % "compile" lazy val log4j = "log4j" % "log4j" % "1.2.15" % "compile" lazy val mongo = "org.mongodb" % "mongo-java-driver" % "1.4" % "compile" - lazy val multiverse = "org.multiverse" % "multiverse-alpha" % MULTIVERSE_VERSION % "compile" intransitive() + lazy val multiverse = "org.multiverse" % "multiverse-alpha" % MULTIVERSE_VERSION % "compile" intransitive lazy val netty = "org.jboss.netty" % "netty" % "3.2.1.Final" % "compile" @@ -203,6 +209,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // Subprojects // ------------------------------------------------------------------------------------------------------------------- + lazy val akka_core = project("akka-core", "akka-core", new AkkaCoreProject(_)) lazy val akka_amqp = project("akka-amqp", "akka-amqp", new AkkaAMQPProject(_), akka_core) lazy val akka_http = project("akka-http", "akka-http", new AkkaHttpProject(_), akka_core, akka_camel) @@ -212,10 +219,13 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val akka_jta = project("akka-jta", "akka-jta", new AkkaJTAProject(_), akka_core) lazy val akka_kernel = project("akka-kernel", "akka-kernel", new AkkaKernelProject(_), akka_core, akka_http, akka_spring, akka_camel, akka_persistence, akka_amqp) + lazy val akka_osgi = project("akka-osgi", "akka-osgi", new AkkaOSGiParentProject(_)) lazy val akka_samples = project("akka-samples", "akka-samples", new AkkaSamplesParentProject(_)) - // ------------------------------------------------------------ - // Run Akka microkernel using 'sbt run' + use for packaging executable JAR + // ------------------------------------------------------------------------------------------------------------------- + // Miscellaneous + // ------------------------------------------------------------------------------------------------------------------- + override def mainClass = Some("se.scalablesolutions.akka.kernel.Main") override def packageOptions = @@ -303,6 +313,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-core subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaCoreProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val aopalliance = Dependencies.aopalliance val commons_codec = Dependencies.commons_codec @@ -333,6 +344,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-amqp subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaAMQPProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val commons_io = Dependencies.commons_io val rabbit = Dependencies.rabbit @@ -346,6 +358,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-http subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaHttpProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val annotation = Dependencies.annotation val atmo = Dependencies.atmo @@ -374,6 +387,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-camel subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaCamelProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val camel_core = Dependencies.camel_core } @@ -381,6 +395,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-persistence subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaPersistenceParentProject(info: ProjectInfo) extends ParentProject(info) { lazy val akka_persistence_common = project("akka-persistence-common", "akka-persistence-common", new AkkaPersistenceCommonProject(_), akka_core) @@ -403,6 +418,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-persistence-redis subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaRedisProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val commons_codec = Dependencies.commons_codec val redis = Dependencies.redis @@ -413,6 +429,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-persistence-mongo subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaMongoProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val mongo = Dependencies.mongo @@ -422,6 +439,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-persistence-cassandra subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaCassandraProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val cassandra = Dependencies.cassandra val log4j = Dependencies.log4j @@ -440,11 +458,13 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-kernel subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaKernelProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) // ------------------------------------------------------------------------------------------------------------------- // akka-spring subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaSpringProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val spring_beans = Dependencies.spring_beans val spring_context = Dependencies.spring_context @@ -458,6 +478,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-jta subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaJTAProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val atomikos_transactions = Dependencies.atomikos_transactions val atomikos_transactions_api = Dependencies.atomikos_transactions_api @@ -466,7 +487,19 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { //val atomikos_transactions_util = "com.atomikos" % "transactions-util" % "3.2.3" % "compile" } - // ================= OSGi Packaging ================== + // ------------------------------------------------------------------------------------------------------------------- + // OSGi stuff + // ------------------------------------------------------------------------------------------------------------------- + + class AkkaOSGiParentProject(info: ProjectInfo) extends ParentProject(info) { + lazy val akka_osgi_dependencies_bundle = project("akka-osgi-dependencies-bundle", "akka-osgi-dependencies-bundle", + new AkkaOSGiDependenciesBundleProject(_), akka_kernel, akka_jta) // akka_kernel does not depend on akka_jta (why?) therefore we list akka_jta here + lazy val akka_osgi_assembly = project("akka-osgi-assembly", "akka-osgi-assembly", + new AkkaOSGiAssemblyProject(_), akka_osgi_dependencies_bundle, akka_core, akka_amqp, akka_http, + akka_camel, akka_spring, akka_jta, akka_persistence.akka_persistence_common, + akka_persistence.akka_persistence_redis, akka_persistence.akka_persistence_mongo, + akka_persistence.akka_persistence_cassandra) + } class AkkaOSGiDependenciesBundleProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with BNDPlugin { override def bndClasspath = compileClasspath @@ -497,73 +530,69 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { class AkkaOSGiAssemblyProject(info: ProjectInfo) extends DefaultProject(info) { // Scala bundle - val scala_bundle = "com.weiglewilczek.scala-lang-osgi" % "scala-library_2.8.0.RC3" % "1.0" % "compile" intransitive() + val scala_bundle = "com.weiglewilczek.scala-lang-osgi" % "scala-library" % buildScalaVersion % "compile" intransitive // Lift bundles - val lift_actor = "net.liftweb" % "lift-actor" % LIFT_VERSION % "compile" intransitive() - val lift_common = "net.liftweb" % "lift-common" % LIFT_VERSION % "compile" intransitive() - val lift_json = "net.liftweb" % "lift-json" % LIFT_VERSION % "compile" intransitive() - val lift_util = "net.liftweb" % "lift-util" % LIFT_VERSION % "compile" intransitive() - //val lift_webkit = "net.liftweb" % "lift-webkit" % LIFT_VERSION % "compile" intransitive() - //val lift_testkit = "net.liftweb" % "lift-testkit" % LIFT_VERSION % "compile" intransitive() +// val lift_util = Dependencies.lift_util.intransitive +// val lift_actor = "net.liftweb" % "lift-actor" % LIFT_VERSION % "compile" intransitive +// val lift_common = "net.liftweb" % "lift-common" % LIFT_VERSION % "compile" intransitive +// val lift_json = "net.liftweb" % "lift-json" % LIFT_VERSION % "compile" intransitive // Camel bundles - val camel_core = "org.apache.camel" % "camel-core" % "2.3.0" % "compile" intransitive() - val fusesource_commonman = "org.fusesource.commonman" % "commons-management" % "1.0" intransitive() + val camel_core = Dependencies.camel_core.intransitive + val fusesource_commonman = "org.fusesource.commonman" % "commons-management" % "1.0" intransitive // Spring bundles - val spring_beans = "org.springframework" % "spring-beans" % "3.0.2.RELEASE" % "compile" intransitive() - val spring_context = "org.springframework" % "spring-context" % "3.0.2.RELEASE" % "compile" intransitive() - val spring_jms = "org.springframework" % "spring-jms" % "3.0.2.RELEASE" % "compile" intransitive() - val spring_aop = "org.springframework" % "spring-aop" % "3.0.2.RELEASE" % "compile" intransitive() - val spring_asm = "org.springframework" % "spring-asm" % "3.0.2.RELEASE" % "compile" intransitive() - val spring_core = "org.springframework" % "spring-core" % "3.0.2.RELEASE" % "compile" intransitive() - val spring_expression = "org.springframework" % "spring-expression" % "3.0.2.RELEASE" % "compile" intransitive() - val spring_tx = "org.springframework" % "spring-tx" % "3.0.2.RELEASE" % "compile" intransitive() + val spring_beans = Dependencies.spring_beans.intransitive + val spring_context = Dependencies.spring_context.intransitive + val spring_aop = "org.springframework" % "spring-aop" % SPRING_VERSION % "compile" intransitive + val spring_asm = "org.springframework" % "spring-asm" % SPRING_VERSION % "compile" intransitive + val spring_core = "org.springframework" % "spring-core" % SPRING_VERSION % "compile" intransitive + val spring_expression = "org.springframework" % "spring-expression" % SPRING_VERSION % "compile" intransitive + val spring_jms = "org.springframework" % "spring-jms" % SPRING_VERSION % "compile" intransitive + val spring_tx = "org.springframework" % "spring-tx" % SPRING_VERSION % "compile" intransitive - val commons_io = "commons-io" % "commons-io" % "1.4" % "compile" intransitive() - val commons_pool = "commons-pool" % "commons-pool" % "1.5.4" % "compile" intransitive() - val commons_codec = "commons-codec" % "commons-codec" % "1.4" % "compile" intransitive() - val commons_fileupload = "commons-fileupload" % "commons-fileupload" % "1.2.1" % "compile" intransitive() - val jackson_core = "org.codehaus.jackson" % "jackson-core-asl" % "1.2.1" % "compile" intransitive() - val jackson = "org.codehaus.jackson" % "jackson-mapper-asl" % "1.2.1" % "compile" intransitive() - val netty = "org.jboss.netty" % "netty" % "3.2.0.CR1" % "compile" intransitive() - val guicey = "org.guiceyfruit" % "guice-all" % "2.0" % "compile" intransitive() - val joda = "joda-time" % "joda-time" % "1.6" intransitive() + val commons_codec = Dependencies.commons_codec.intransitive + val commons_io = Dependencies.commons_io.intransitive + val commons_pool = Dependencies.commons_pool.intransitive + val guicey = Dependencies.guicey.intransitive + val jackson = Dependencies.jackson.intransitive + val jackson_core = Dependencies.jackson_core.intransitive + val jsr311 = Dependencies.jsr311.intransitive + val jta_1_1 = Dependencies.jta_1_1.intransitive + val netty = Dependencies.netty.intransitive + val commons_fileupload = "commons-fileupload" % "commons-fileupload" % "1.2.1" % "compile" intransitive + val jms_1_1 = "org.apache.geronimo.specs" % "geronimo-jms_1.1_spec" % "1.1.1" % "compile" intransitive + val joda = "joda-time" % "joda-time" % "1.6" intransitive - val jta_1_1 = "org.apache.geronimo.specs" % "geronimo-jta_1.1_spec" % "1.1.1" % "compile" intransitive() - val jms_1_1 = "org.apache.geronimo.specs" % "geronimo-jms_1.1_spec" % "1.1.1" % "compile" intransitive() - val jsr311 = "javax.ws.rs" % "jsr311-api" % "1.1" % "compile" intransitive() + override def packageAction = + task { + val libs: Seq[Path] = managedClasspath(config("compile")).get.toSeq + val prjs: Seq[Path] = info.dependencies.toSeq.asInstanceOf[Seq[DefaultProject]] map { _.jarPath } + val all = libs ++ prjs + val destination = outputPath / "bundles" + FileUtilities.copyFlat(all, destination, log) + log info "Copied %s bundles to %s".format(all.size, destination) + None + } - override def packageAction = { - val libs: Seq[Path] = managedClasspath(config("compile")).get.toSeq - val prjs: Seq[Path] = info.dependencies.toSeq.asInstanceOf[Seq[DefaultProject]].map(_.jarPath) - val all = libs ++ prjs - FileUtilities.copyFlat(all, outputPath / "bundles", log) - super.packageAction - } + override def artifacts = Set.empty } - class AkkaOSGiParentProject(info: ProjectInfo) extends ParentProject(info) { - lazy val akka_osgi_dependencies_bundle = project("akka-osgi-dependencies-bundle", "akka-osgi-dependencies-bundle", - new AkkaOSGiDependenciesBundleProject(_), akka_kernel, - akka_jta // akka_kernel does not depend on akka_jta (why?) therefore we list akka_jta here - ) - lazy val akka_osgi_assembly = project("akka-osgi-assembly", "akka-osgi-assembly", - new AkkaOSGiAssemblyProject(_), akka_osgi_dependencies_bundle, akka_core, akka_amqp, akka_http, - akka_camel, akka_spring, akka_jta, akka_persistence.akka_persistence_common, - akka_persistence.akka_persistence_redis, akka_persistence.akka_persistence_mongo, - akka_persistence.akka_persistence_cassandra) - } + // ------------------------------------------------------------------------------------------------------------------- + // Test + // ------------------------------------------------------------------------------------------------------------------- - // ================= TEST ================== class AkkaActiveObjectTestProject(info: ProjectInfo) extends DefaultProject(info) { // testing val junit = "junit" % "junit" % "4.5" % "test" val jmock = "org.jmock" % "jmock" % "2.4.0" % "test" } - // ================= EXAMPLES ================== + // ------------------------------------------------------------------------------------------------------------------- + // Examples + // ------------------------------------------------------------------------------------------------------------------- + class AkkaSampleAntsProject(info: ProjectInfo) extends DefaultSpdeProject(info) with CodeFellowPlugin { // val scalaToolsSnapshots = ScalaToolsSnapshots override def spdeSourcePath = mainSourcePath / "spde" @@ -574,8 +603,8 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { class AkkaSampleLiftProject(info: ProjectInfo) extends DefaultWebProject(info) with DeployProject with CodeFellowPlugin { val commons_logging = Dependencies.commons_logging - val lift = Dependencies.lift val lift_util = Dependencies.lift_util + val lift_webkit = Dependencies.lift_webkit val servlet = Dependencies.servlet // testing @@ -649,8 +678,10 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { new AkkaSampleOSGiProject(_), akka_core) } - // ------------------------------------------------------------ - // helper functions + // ------------------------------------------------------------------------------------------------------------------- + // Helpers + // ------------------------------------------------------------------------------------------------------------------- + def removeDupEntries(paths: PathFinder) = Path.lazyPathFinder { val mapped = paths.get map { p => (p.relativePath, p) } @@ -675,7 +706,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { ) } - def akkaArtifacts = descendents(info.projectPath / "dist", "*" + buildScalaVersion + "_osgi-" + version + ".jar") + def akkaArtifacts = descendents(info.projectPath / "dist", "*" + buildScalaVersion + "-" + version + ".jar") // ------------------------------------------------------------ class AkkaDefaultProject(info: ProjectInfo, val deployPath: Path) extends DefaultProject(info) with DeployProject with OSGiProject diff --git a/project/build/lib/bnd4sbt.jar b/project/build/lib/bnd4sbt.jar deleted file mode 100644 index 5906b493003a67283602179ffdf24d15acdeb0b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8092 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 Date: Wed, 21 Jul 2010 08:33:20 +0200 Subject: [PATCH 036/188] Remove misleading term 'non-blocking' from comments. --- akka-samples/akka-sample-camel/src/main/scala/Boot.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/akka-samples/akka-sample-camel/src/main/scala/Boot.scala b/akka-samples/akka-sample-camel/src/main/scala/Boot.scala index b8a483b55f..b3b428c01a 100644 --- a/akka-samples/akka-sample-camel/src/main/scala/Boot.scala +++ b/akka-samples/akka-sample-camel/src/main/scala/Boot.scala @@ -51,7 +51,7 @@ class Boot { consumer.start // ----------------------------------------------------------------------- - // Non-blocking consumer-producer example (Akka homepage transformation) + // Asynchronous consumer-producer example (Akka homepage transformation) // ----------------------------------------------------------------------- val httpTransformer = actorOf(new HttpTransformer).start From 2e453dd7c0a0e3439ae76618866f1000e73778b9 Mon Sep 17 00:00:00 2001 From: Debasish Ghosh Date: Wed, 21 Jul 2010 12:53:50 +0530 Subject: [PATCH 037/188] fix for idle client closing issues by redis server #338 and #340 --- .../src/main/scala/RedisStorageBackend.scala | 8 +++++++- .../2.8.0-1.4/redisclient-2.8.0-1.4.jar | Bin 175418 -> 177997 bytes 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/akka-persistence/akka-persistence-redis/src/main/scala/RedisStorageBackend.scala b/akka-persistence/akka-persistence-redis/src/main/scala/RedisStorageBackend.scala index 33b1c04a73..eef60784a0 100644 --- a/akka-persistence/akka-persistence-redis/src/main/scala/RedisStorageBackend.scala +++ b/akka-persistence/akka-persistence-redis/src/main/scala/RedisStorageBackend.scala @@ -72,7 +72,7 @@ private [akka] object RedisStorageBackend extends // need an explicit definition in akka-conf val nodes = config.getList("akka.storage.redis.cluster") - val db = + def connect() = nodes match { case Seq() => // no cluster defined @@ -89,6 +89,8 @@ private [akka] object RedisStorageBackend extends } } + var db = connect() + /** * Map storage in Redis. *

@@ -411,6 +413,10 @@ private [akka] object RedisStorageBackend extends try { body } catch { + case e: RedisConnectionException => { + db = connect() + body + } case e: java.lang.NullPointerException => throw new StorageException("Could not connect to Redis server") case e => diff --git a/embedded-repo/com/redis/redisclient/2.8.0-1.4/redisclient-2.8.0-1.4.jar b/embedded-repo/com/redis/redisclient/2.8.0-1.4/redisclient-2.8.0-1.4.jar index a5c824b19ea6113c9671cd7a49978886599a359b..b811e6ab926b5b6fe094d5a4989abbb61b3aec5e 100644 GIT binary patch delta 38960 zcmdmWi|gz=F5UodW)=|!4h9Z}H>qDI^2RY=O8q+BP?bq~`kY24p^dXcnZP26s~DZ8 z^ENTDZ?<99WCjUs&S2AJ2Qy~yE(0st>?ptqW=s}HQr=u3bcO{aJv}gkQDx#3kq&n~S9*c$ft(frH# z|7y;inUG>Gz3QZXdfK_l`_F67Ra>k7|8;(LJ==xWdX5#&Wj8fn)V8hUzBBoHcU$$X zjkfi>6K1pDZA!~x>RK#b^4RG5_iazP$~514tSpI}Z?s+}^Zd`Cmj^Y^Z&<6$G_fak zNk;Lx4PP3IGJVS1wi$}|S^RZX-vNMA>t6g%QmmDGNp48!# z>!du3<=a};2QxP6dh2^^-g}w#?)LQwn-6@u+Ujy~WBu}FUy>d@IOt}=Z6af;bJ*H% z=C-ffZn-DjXcH5SF6ck-EFpe*W`MlE)(t=RFZ}Z?CcpMQbvJa)q-TD6^t)s`f&;bv zr<9!L4q)AtJ(KI}%T(ipS!P~KH>ul-p5pP_*>bn_u2$lEVUIPJCCav(-u2jPuH)(j z+BXjKR+XJAuxG$$0i?52`@duc3dxL z@&f(^zDF6iaBpE-;CJ&=&!lEeIP(ri9O)?()C-i7)PiYIkG3p#uywe?4VVG8rd{!7xf=|#(vPOu*O z%XD$$rb^9}q8I-Yg~alCnk{q>&KIa(@!o#2^todOA`32uMth}RHm-U%qa#s8z|LF$ z+q2JxJ#34fd$hF+5kY=kgArU5{`0l|NeYR#nQ-^LSPcQ&`}GjI|=s@#?0zmu$rgJ#QJY zmes46m@8IyE}Y5f{!7`g?C53bM8kHQ-+p|)j#IhjFR`C|Z^=WhoM>?|wo6~66HfnP z;OxlUcK7?5l$ANbX)eV)meSi|N=+|{)XX{-&YRM_C-j4)(7a1B;m^;o)lSU(U}>}X z(dHjE#`o6W2$u4v~|VoL%dx@5Ov`mizJU3Qx7W+h4f0`J~L`IM$MC{pHNL zQ|ClBoO=D3YoGpx=X&qt416Y4|FmsVT3U0+zT=VTpMayGJAJ2~eY8foc;fEdsY|pY zpY$G5k@Yw_|H1P5O>fT^bow=1O?dDTSzc<-GTD!tO zo{l;iw)T2)>V>3Nf4mm#-NmkEdV1Tj(_x!7>8k7&`4goOy7+I-gHHzHb&DUd)txpo zKF5&RdNL(*$%K;SPc((IzD?DgpE`a0N2xrshgNavKVK}1TctC9>gE^q-z${8p8tRN z&T*>gl7z<2j8nzB`xHad0)oP7FD>8tPS50!l{}Z8??#>9^CwSaZ+&;oYVYcpwGYIm z*4A^E{CUq9`a%5L?Wz8g?i&~|MX$D9^5Ff%y>A}Aclc-WVbfMl!3i7+^PWa4r{8}Y z;pC%m{U@K9e)8#z)7Mzt$suv`gS8gwOAR6O+_gLdQ4;!QYKG&KD z6RUoft=OGd{a1$X{Nooq+e(i}Px~+|nI~79M?O zz+dm4Rq(pBgtNjS|7nGUuSL__Jz{T;6fXH$+jPFprtNc${PD*he$=#`tC@Fx`pU0b z^VcgjZ`Z7B<>2?;{wQ|Gl$M+{jmJj0F^?6c_xzpw?!U;gg%9p$aNiH9bmVY4^jyu0 z@$Bh}sx8HW@exNhbN{$?R&*7w2+MkoOLzJlOia}8*YERFe&h6sOOQ#9n{lyS0`H1D zQY&6?g_N*%iMI*7(ptDA&g+xaw%vJb7cKV~bldLkFTby zo*&KnFoY@ZsBnhkyy^E9-yApapLo!e&u8rgk5-eY3tjIY>{i*(-RpABb%prR??1x) zk4zMuWGtgx^DVS~qRpP3)r*UNTx6=VIj|?~+P|FdHfi~fe;MWVlr0hauv_)aRYxKJ zy^TL_N32QMe}4Ux;w`1~-pp6(=blqNNk{KNpqjh>^(TBnPdr|0Tfg8g-@q*!acFi- z@1y@>CpXoUgVYGJd zwKG?3pTFDu-SYW8>;HdWZ9dQV<9FV zJno6bo3yLr_ODp(d)Tvo*W_BMq>k-Lx>2InROb9la$T64YSHQ&*}dl6i?YC^AB{=d z9u_a*+I6kIWpeCfDYK->2lB!?eu?qcmsb`?pWNN(E^>QC=Dk$~f2T>Eos@TOsk`j% zjB^v8mzA7&B>P1>dYicV;)il~v@h>ov3Y-n*j#tfZECZxr|&wKaijU1#jS}7iTdi7 zIUiec-k2ix@m~Aira38o+HJ;Jy`thgt4|%6xTJfU)Aj{lE551oF0NSoN%qnByx!;8z(`3^gNt{i-F)!wB^dXsp%}$>c zU#vd1w>si!y_N@4`Y)kOT3vY#4w=-s( zO!Ck<%ym0Iymm>JmCp5#rz;n~5z#g7TAug0)b`l3+}D#zHl0sb=?j(!y^(O`T93rk ztdlQ81McK!e^OnYlp%3^!V3G-FV^(6dCE+B5&UM+RV|UDmkVu_-z{9^+19wmtmDcD zosz~`6OYWvRV(_h#a@3<^4m4l-7h3A_nF4te%3C%XO_A1HQSU+>Z{V?K2+N-XgjIV zHD&Ge(@V9vemAW=eRj_CvUjhu=3OdaTpBiq-C85)f^6)$zGWYL+CrDjQj_X=zAEs= zpZ!uxvJ&6htlSi9t8rVqy6V8L91*|ICLNE2X3mj2*Hg%y^8SI#t?&;uJoVE*GI?Kl z6Ow3t@>%~Q)puVdUw@imnh^QMDfry1lL>NvDwXy%g+H#4T(9|tN6S;Ca;_l zvl3?Q*M0l^$VaPvmnXcip6-2E=AOXY{33SGMZ#|`Z+)|)DTafqTFN?gtMJ#{5|8zN z7wo*wr@4je#)6|JCq%DA^q7oE!4c0hE4nz28roBh{u>QyFo#&sG{+^NhI=m?Lp6~C@yH9sNUmJ9?Ab3*T z3ad@iFPpkM{SkYAl=I`hL+jMO8%FQXxFH%j$@sI*oA)#KwsOxC;H{ss`WgR^$vM?0 z8TuQ1>We2;IJJM?bvAF_Bg^ZPCfrt6d^%$yv+v>fi@Kt_+@=J+54vu&hvV(RNpUMB zu54PkQG7>q*cY!jo5edEuOC}0cJ#jT?n2@J4S$YScDD;MI)A(#xKH%{>tOE-BLA8* zerPF8%$~!wu=Tvy^*xNQe_pW(U*jx&-|*bE1h$$Pxh*#r)ql`4D=65`vqxO<6QJMYi6cU_CJONGGf4*?5KS-%RMcX&_#+^1R}^Iv~#(L2bK_{Yt8{TKF0H=iv& zal+~5*6j~1Z^Q^Xv-b7d9NxOf_t(QkTN2->#qHrb`}$P+ zVHOJ%->s{ebJR}kM9?ZZ%hvZhCnnp7?0;W>yn6PVmiYCj?pZF1KP;cNdp-Z!H#_#; zi09vbx0bKCuEY57o2@c$mq+ZF=%7^f+SU7k?DTVWLiNYhzbXH@q5e(sxA#5us~2QD zOaD}#JuKKCTdi`ZklS8K_^HN+$j)m^#P#NcZo>u`WM23V`E@w;zg??Z5W_n^3^Xw)3qir32dJ1HJJ@mD}p+mklJ#yf1n-*NN96IWGV}| ztE(W+C_TNlgNc1JS6nlslAVxH%LtO&ERZw-EHYWaS$gxn6kTu~3+f9?Pv*=}ua6BE z4i~w5U4=)|jrGc{j!^IAQcem>uSPLO|IA5tW@2$#ytYI_&%k0P=V!(Y`+x2HcAukG zwrpDy_B-hMEBRN^;pgYN2rxxmo3(Rt_4m8a=hU9FoxcD7-?#h>wm&91p1Zwo@#nz9 zPk5HA{oM1g&w5+>>uopRzM8et(B#|eWr>pa>X-8@tZ;8sv`INHyzA!EzJ)Vc-|cA2 z^{pHth^!m))kERkl1EeI5j#`lx$e<6}r(-ptqcRN@s}T(pI!?CDo_=j>x@^SPul z9n+YixkO~d1Gi3;XSYz@b6CML=J~Nz0*3bjyEVhVc^tE26)#-LDgHrEb@{GI+r48B zRde}0SdvgX|KS@!D~}yc4+|zwZ%ICVYt=L()9j6G3ZM8?7S(qwp8POrYLigzC83#q zl1nGO=lmZmdHAbJiD66?v&Ym4iwcev9lktMaOy(a&&zn9IP=@}JYueK(OkLcxTpL+ zhnVXw_r9HF{qQ=lrpMpoU1{58l^cqMUl;keb=3uZd9aFQ)g8C<=c@Y>b>&i4oD({% z%X8ufPjg7e->pUV!t2ei)&~X{^av*AOz}H&x2mN@Ut)@>yLPY>n~eM7MQ{4$ncl1r zf4wxsc+2iH&ztW)xt&|1IhjSWP5R?6-^zVO64&b4d2Nu+`m%Enj z6U$Y9AaU8IHuFefj{6~7$<0dA$HP{-$Jq5Otm}Gs=by1j#`@y&OWT+66y7Sas@-Rr zzTW?4=4tCg>$foVu}Xf95P8M+_Q(qBIZYLHv$VVp)mqKDeDh04t@>@&i8`tgfipHp z?s`EZ8Z zazfd>JoXALGj^~wJPW&M(L6CqHa1Z3P>XB7I$M z2j@lgYnzOd{z^n0&5vS#_fTf<{Z&dCHqvkM58O_fW7WNbH_PV#go|ua=0g63|H8Kz z_o)7F`NiREQW$CDKe49o-5a%ad5_$Fl&?5?fp2d{(Ao!Stj@Q8*!-7y$#qOi;{B?G zEbf!MPs{>+zO{AhFF14LQ2oOrYb;Q5}Rd({w=++f@U1fN+$jjW)zzW=3PA! zA~bh@!pf$nzEkR}dY7Eio9&d->2N7=&6OKPEu0r`T>Hu7YhBQN`@?)ytL+7L6YnfK zuzlmdT{T!>9WnTuLe?pET-cVPJT~fmTX_ zhVJY(OXPY$M(wsKt4=;3!&R@BoRe5wyw`@aL^^zH{zZ>#5u0@1e-b;r@v-f?Jt}dR zwoH1g(zX4D-y@5{NquiOEtG7lbZR`>9NWZZEx>LyDeJ+ zG+L+0o(fuUfZguH`?->un@l!6z3{)k|BqY#yWQXS?cQ&m|K)0Z?LS4Qj>-R`pPt-c z{viL;uNv;e%%rfqSD)JsHLNK%ouOMhnK3@NUf^cVr5UbYVxto`R35Q@JpB;2;|xw~ zsU=HP*eZhNhFtd3EGfD1dOqWiZK8SWU5-m|`N&OAJhyFM@};LiljHf!do^MUCbNq@ z@Y`2)TslK4hU2_$i~AwR$WI4zpM4DulGyt?ZpOT6ji)x~_?~p!V{hu{d8@_z&E#iV z`iop<%$QrxeJ1cy;Nw8{vtIvZsyVa=dx%`?u(=<)x|IK1qIlK{YXerLlW#u%dfLc( zzeVOw^QR?C-u#gX+}2!N6mZCJ;i;36nj%IMlf2xreob;Ljn(iL3v%#s4RSiwu=7Kp zzJ&YEKE0$~!DSO$)7US4{o(%PWJ5id+sDVBlp=DKq#MNZ>RST@ckw)2z;Ne=I_q8y zZeN9Cl9o12vvSv7oEhch-?ZfPd4DHXPmxSn)!oUiQvA!E(?So41vyK(1o=xHOwgO2 zCZ3@6$gEON!`~~hk}E`h(&6gAn~OBA6tk`ncoH=C77KsCrN8rws}DHMS;8ur!zx+* zce11Tirl??-1Ar_#?^0f`}9#lCq+2Z{gSMJ!h|hvnC;ojmZhW|cG|XLyFMH9XVs3A zag&cMa5Tu(E}oV$r!~eY#^XZovueu=2CS<8rzD+-H08XkZ{@FaaavixCdFx;5}!DO zUMR{WU{_4`4OP9(^`Lc2B>^yv1JkXt@7ml3YYBxb7m+Prp3>(S9$Dow2n22ef{If z`!rksaz78#XOyiBeL9gNLos~P>O!vT8k?`36twcm_4Bm(btJC)NE|z#LhF?{jfSN9 z39dd5d8bU#TRiE-;p-F4JD>DEIs2e1=)`0G=o4SF&POX+c`BAG7-)Of^|YV<*l_T^ z!@a(S_YA=koFe)nPVBz2@qO3^$8Xyvd|zQ}u4$`h|H5MXvas{oG9P=?4n&+d`$Wv; zTOH4pPfOnHjp-|H-g)!ri97Zp{X+R_=l(Z837c47Gvf~1Ht|pY+qW(Mniu~;yVmb0 zchZ+jvJc-TPm$?)y7srdfxGM?u_EiAEgp7$?;4cMWDY#Ckn_0jSE_ztlh*QIGIu&< z?znpTx!gaU^?B3OY#-sB$DKZPUi5jV`n@nhAvQ~KrV97|c}$DLG~a!#{(Emj_^j3x z%dK~{&-;C4X|89KsGc?HSE~8xxt@Pt$f?gA3XXgl_YZO0`ytBZ_dAMv ztw8WWBSWkAU=?1-wspWge6Cuiahj^{^&1d2oV&kzpf(Ptf8o0ouJda zv2vB)ys%Xwr8;Rf3`U2Y4)C{iy5@bWd|Sn)9QNPV;7CODCmyZDCy}4#cIbz_I=T<@5vLid-}`%hrInabJKyTOCNmGY<*m7_2hs-y<=VLh5c<_ ze_Sp|PwQ`Cc30{?an0g~NN)XK^C#OoK9wtUX=?JEE@?aM;^?^k%C*%Bt}^v1^-ePD z8%{Q=Eib6`@N~8LU&Z!A{8PBh&-+uBJU;R6KvVohN4XWQ`tOf?Ud*1VSg-!SIpRO( z=NT?NQ$$>}A3eRzCw8clF{kO0X=SXt)Kf7fjb|>cTY2u51WK7U{&k$Y&z~K$|7`D>x__H(@Zbko#JL3P`9;nqD9_!mX#@y9#V$NQ{R{dG9G*q zv?;YzOZ#p2l!G5c&0;3(FXG;@S@h@T^{xBQ=4Nh@SUr6z$C@LvUbJUbRV&=+KE0;u zZkA{LhSpgp%LISuwkwFOE)ZVJ&_BPis5z{D()Z31+qF#_W}V^i*&?;zaE7Jmt}D~S zIkrr@w)C=8RR6`8oyI~RPO9DFc(j=HgrBhL7cTBnrI)>1DsMU&#u=z_oz4^9V71^4 z^V%>SH!b;Hoq1xJ(z*URze69+$WZ^W|I~el1Nz~!UWh4NvEPxKAMdZKdTrl~>V|yn zy+?fXm(@?#J6)}1D%|>XL*Tsl32Dw^yLx@Px6J;=u%K&UJeR**=x3d~6H|IwKfVck zCHT^>D?27LE6as1PLJKuZ*HcD*bb+Rylc|e?*Ck2yF$3{g~DCl$Z32BeL~F2nmL|i z&UnW0Zkg`u;APvd`+N`ZU<}JlWGk0ciriDoI`wr`REl}MB1^{i%Z7p%4he0_x+++E z?{R|aV}qLo46n1QX4p*if3GGww?>Q{oORv%-gd!j;G6Ecavjg;95}!qs>>^V-7hjv`IWN zPhrjRW;F#v3LKsJ-srOR%k;wB=I`Hh z&N2XT;{#G(MfN>vLECt~o1rb(t|ee&4KA%VDc(DF5mSr@(LJ315OwX|DRS zKVez_CH<}s{7s3ehb;K>Hn zk^S12(hL9GVq<#vzWa-%tDoad{htdQG#9@%SoB9gW!d)B{6+c^FFr4^oV(8>@o65< znN|D|J#{}@iY6|rSNi14`L|f~jrgf&P8?S_?@iOHf5kB8)_T`pLPZf4`srKi3=ZGFJl*w|^{@7=#>|g?P4 zJuZo?zOiiga{g=o^W7Yrd8YlU@nSo?J>z5iPx6YH>)XSy8P$^~H+-Nj$(y=LD)fcxLb)Q)CC0C-z@yQ#D6RuugKhDl$ z^7G}~VRIxTIq~L>FEtaN25idw`lEiG{5{9T#c?*R3-`aUNJ#v-hM`l$EkS(hR5m}> z?X0$(v+Wu`1WI%t_g!^f`Oa&8-7^ng3Rh~q`ehsLbL!QvIa8a=e=$G&q!CbgAYN~3 zwwFipYnQOL-%FQjuiSL$NW$Fxd9J0}na!cIZdQef-c`M^*}z=ee0D_XomHO30m7?U z>n{j9X68lAySC}`G%48wqB^-EZs$)1pUN=US#^z}RN$~N!v%Y84s*5Ys<}7TM&%0c z_GpQ8n7JcUS2gEI>4lnTmup=c(`%VH@5D`MI{iuQ_LOsGi|0;XqY^Ltdcl*$tF4}P zU0dI8d2`xD*05baW`rJk?yRY9!Q#F$R%g@N>{C7UryLB{d%HdhGJ1TZ$II$z$wEGd zN4H(BHCtS>5;^f+;HIDI<(59ZmgP+9f3jETC^=7Pjhpy&?Mj_aJ~lNr7qgCLU14L# z$eRq)nJ#A=JiL*3;>?B+-g5?!(G@T#aTA@fb=kDE-^fAGDHIe=ec z&xTK(GU^9BP3qT7xKm;vS;M&G+Kx*XrS>LXa{7@WvvEhmdSfo7Zz%%ui5~?1_1|pl zvFA-r3KlctY!#b)b4zQOQ&;2a#jhH*C2|svd+3(QE>C&RDzn#XQag(Sud3YV)l-%+?zT_+;`-jA&)(2gT z?>#lw(enDTtZBMxWou8wt=2QxqT8pn_iJv_)#GvJ*Lg3$zR`S5W6bK#y`CxgZbhP= z&Fk3P9b;JBQ>k@-!Si};bTe7 z{IudB+KyU_xwRAS?z;BV;mxm(6M61tE8hP}a~0a>c%*oe`1i@z)~|E7k$Qcc zcZGEP)hx54wyQ-CwM^Sl>&4?88>1NdcfR1wx!GQKPB~2YobFm?KILb?zXPl40_yh% zbQi3@Hp%MF>+|gWvn6Z2-b6bGg|k1H^G^KcO4F;%w*qEd&73&*;KD<1?l`@8v57tD z^m)G7H!Qh-+Z=n!exsQ|-lc-OI^u05iwINGhv*yP1`2iu_Hh``;yq-exHI&X>&=$r z`EO3YF_igfv8-`Ji~E(GMJ(?sxDLnL?iNaWSihTJKIL^#>(UF?Z<m~`4tXc{fR`1HZz}}P7df=2RqC#k$}i!W_0M1PW+7vL*(94c ziT2_*&)=xm*AU$MPw=Gr>htltC#^XZHb9{Q!MdRtH7>(TtB8k4GAQ|goIk4^VY;mkU^f716vrr-HC zyY|IsseSvt!~Mp^RT1t{zHjO;-L$`9zi`{!DSw_a{(qBHnNU<;q!{sTuHO8Hplveo z!W!Q_i=RGpsN_%!@8iB@@-06hRmp($X)~v_lg6zF(`@H+`nN z20e%CQ(Y}t16M07+c7Qqv4*(L9fqUE=0(D)^ZswBh-%fTQrXVZtI(0{52Tu(@UI{Cw?zjeCfvzB|MJ9Iw(ni^&Q z^v_y8hr+OcOVx^xe5yKr2gYfB`nrefhW)xO?*0JHcVFK9U+*L!qxQ6B?z&S-^(?Ck z4c=_q>KP!}nzTl|(z)c^*@>2qT{8~8KkEDXO6g)Ahb4X!&D|$%bD6MB;XK!wS(SG7 zTo?1jDyv0mvsr4jZ{3|zUR9-guJc33r=*Gby^C_X7vvmv_T^Y)IH%~Fr9H>Q^6r{w zk)O*rKKafN51r2u`NQvOsLd1^-^989SIw*!*q0#u@wDC4);f;)>Qg=9q=ZjS&3(C} zV&CmU>^pVm@_$S``dm~}GPI<_h4a*J0}cLp44)w2K)^Be7l=CEX#pI~ewdzZzRF!OwQ1#0<=y+bqf8=^c%_M(C`BR+A48@x7 z+t;bet&jR6eTyp{+CPtFVc0o@@`?ly~&Hcj%4Vu0iMRrQEIGspg7)daR`R zaDK$R+9yZM_x)7Y)QohC@H_G~b7Fm0ecPn3+G(3Oj_rOFr+I<#>W6!}pU!`({xIW5 zZg#|RC(RF*6Yu-qPgBe^;nvOI?7wB-8lIkHwrBEshpWjO{(M%-ef<1D>Bsu-d`_pF zr(9Wmu{NN*N8w9Hx!T7m;ZOR0y=I9x?XT0O*qRzHz4EM;<8Dp!;)8j`oOj->ynnG` zL-Fk!`zFoxb)EaN>1yKSJ7@PjW}f={w|Am!nmPYYzO5&enX4DfmnzGdd)Fs6$!hIZ z-!sIT8+IyXM2Y$u!k3UhAxOtNo@o z`@(yPbqiudzFEoeg_*y-88GSETOsb^GkV**m+{J-%(GCG%i=8M|2|hj;yufcg*n@` zodvSQSs&yd+Wl~qWc|vS;rbOa>rBqc{(YT2tLt|Ex?=MX^P9W-WM77Suq-*3Wyf(`0?wZ!;U`&E8x+{Q!He+4Cp&zD+RSUsPNh zcs)b=a?DpIsebaL(5oI|t!aok)%6Wd|-m^}_$DyHr*`t^3 z5nWfQTpDbCrR%ERJ6ofGoAYiSex>%i+%o1`%{=q@d+%4(uSjM3aDEBr8r=(tn{y=u zcB~JZk`ecOi~9bp2YkJ)S$Eg|ez0)cfrPofw_M4YuPv88uH?2J+eA~_R&E*_h zuBp!G*?PtP-p&U_B{y8^tsGtLrnpBQpJQ`pg6`89KRY&Ge|X~T^JS|p^!eo7@LhRP zxi?_(7SrsRV*-)GK!X>k4)vw@!d{Am4W)`9EzKG*D+ zx7qOEo04m?J1X+aZ*Hp$XMCGx*|hjvs$A4|#Vf@%?_Hf=?p}8%WPYsqtbMENqZhSa zIaqY;Q;gHwcXQ5to!uvXEpPp^VI5=Nze7 zvfsk=Pb|LmHfvht)bx_a71y1%TbSNDfAdRR;)$2qH{ZNIyF%y7^ex>^nR%wESC6N) z@rnld&(^pSW~H+3M)K~;J-NRwd@$>rrXVj;za#fs@00d&7O&iAXZV^Azk9LFy~oU| zKx3|F-tLfKuE(}J`A)4?OVcX)%ziBT>@`K^v&9bEw(VNw80RKmJY(r$lfM_Pox1q% z;kN+Cy8GwyZf(mr{rS!Ll1pKEu9i*n82jSfj=sy;vj3d$-rZWWWvB0S_&x7rw?*}n zsDLK{?<;QCH=WJfw)>iAiCclyY>@-GpZPiijm@hM@Gw2_nCJdn?c6KF|rD(0)fRylURnI|p|iJYW+(mw{Qh^0D6X!xO{KduJ}p z&$)agp>BS#)q_opbFRRh%nmD0$aT>b54 zj&o+(;f{jRZ!M>v-pGDeP;vZr?cQS>G7r6t^3QeZD^@rCZf?FMU9RNUF|7lWU9@(v z#+#Lv$JiP5{3v#mdz2(vZ`x92t-Dyd`;zY;ug#Us%JM(no-gd``t!`#D=MveqP*t( zuZ;FruL!)bwdv#Xd^~&R>1Tzeh3&cZ|94!ze|u+c`u5vf`{I>mO?+?Lbmr|kr32*} z$I}>V9t1dtJy~pW{b-b0y4jnX_cK!7%s8EA{O&eGK`z^r%X1#cY?905u4b>-y36M- z#%(ocTlbPA@z>?d_ft=lyZ3gV+-%|Z(Yn2g<%jv+mF=vw$}d}TefzC9^A0W4nW`Uc_UY=3=SACfyrhf1NB6RA3(aVr zp)$kiSdimfcmI2Pd>660J;;weZWwv-GFyG?e5)*u?`GyX+omn$-lJL@$kP6NcJ)EO ztXHjp?56$a z?oCV=TlJ}(>r7^i$=w{w7e=D9&)$pMFu8k^?q|NUjnbCsYmaT?owT~jX;s0^oZGR7 zuOxg6+EOpQ>{jp2`$m^TSbpuAw0PgC9e2wPm7l0wB>wi$x|^=$%fJ69c* zT2VkgkN>9E*>60z-acRzo4$BQ?K6&^`TEB`7BxP3_oY-m!=m0WV9AMWoo4Pg8w%H- zd{=b#<0aSNWwRn?$?jeEQ)cx|yBX(r_H5SYebF+p@2!C-UtVtLmynbk9T_cW+owxc zR_)qRutMZ(O7Yj*iT8}z=6s)eCr$3GPB!z-QYP{x4+jm zeLEVp`{r(6ug9Vf*mujS9p#VVJJuai{ajkX?u&<#ad@lw_vuW3C+6_G|FSlzsb?3h zX$`n|=EvK)lNA@_pDwuFD%o1M&uxE%1nUn$t-g|JA?C6-dK%?kq%_s0_lE}QeNTJx zj^%%*@Vby=Q!^gREa?C0$8TEs$$J(1alLb!xk9Hprrs54;^f_Pq>iyP z+;8~cyxXBZmDk#+mu=teJNxT2WFI{U=(}03ArUdH!1M(B7tOHDkBe6wV*BX9WMjtt z;`p1>3*Vi6crQ`a?!#fe>B;vVFz4O-5v|47i?TfFUTOPA@+uOcH*Jf(%PL|{1 zc^yz2^{m3Xd+imoG^X7md|i{0Wxg;LazESZXTfx|Gvq{n;N-(?MY9t%w(HGPpE--K zyeiao%E$W2U2qsjYvP#y<1eygo}q`t5zYEAf|@?yna+Fu$^Od zW4TflyN&Fh4AvLxugEg|eY)$;+=a5zuelZKJ|{n7I~5d;r!&v~l}USxw>;k29m(`OyyKIf+fG-DiPqC1 zA1-ohKD+z2>-TlrXWEtq?Uu~B_)ur^ijyqd?HkK1pOoENCVNI(rhS)l(pRUc#qS?f zd_Kf+Bv$qROzF#0{-ozFR^WFQGid^;=?)j-<@-{wAy9;yzjl1?ANa&LOp=Xb%+=AK^jw>H2)c~5QNv`@V3F?=h$?`-X} zabLap`qOh8Z)KaO7&({LrAqynpBTR6-Ug>RK~MG`n7IFRi($RG&K|L<@tcpuP70G3MFoh5zonU1u1o{lVH~_Y3FU8{RIQHZykGOr8_Q>_^*P`E=B`@yH)D zb>1h%&-0Y$Y0&92ai{rKXW4&y+-Kz+%X(_5+g9h5=K|P1Y*@ha{svd6bWiq)`UnA$ z`kdge{AF8b@YUtd@+seWt<+CG0uYA_zyLH)wb!=9f z?07W3=WEArjqUtf*^h_X3$93J2827+-rL9U`9s1VqugyC z2K}AR6YO^~KDiyb=|y>o#4@9AT4g)!Cy5*J%?z=t&He0EQ*7DJw=hkc4 z%$KmZGHH7H-m2#UA}gNB9G4KSh|S&Rka%~(G5x|Dnf(j>UWmRG$hgpF8yR)S?%58P zuhA=S6$m{)&U(0{jpyq;>m2P;ouCQbm3u2stUa}K*GG@~=T|1i@>=iOx%*fQuUkl> z(5VCSH)-*3$yp_e7!}w)PWm_TT<(XvB7g7MZtUIEY4YdYrmq2yZ?xTP>M>esw{f<{ zM*h|81>Y;3?{!AreEOaJ(5rWns$%{3_1UME|NOA?#IDe9FMR);{*gR$;`%8a&&@9< z?cZ{=F0=RVB_Z2oGoEa%_YwYI^~IM%^vIF_-ILZ-Sa=yt+yCFmGwn{`&X##k4U9Pr zj6WK@O8nX~FV*1H>@-eWzbBUOc0Svr_f>{Tbz2Mjw$s11u)o<@JJGq=s`m5)rS`X_ zzos2@jr)J;CG(CqN3QdKwPG}Kf8Mh<@4eBD&+9o~ebZ~U{eNw9UjF7h{e%t{OHEN8_C{Np1ihaj4xCER%oZn>go4OeedR+GoQ>;4jg%O=kk&Nd)_Q~@+qBN z?O*tX6|X!`nQi*kEcqv&jeY0zvdJd@#Q)v@;;OcpeaA%pkNbruraV6XSb%A*LyuSX zrCTORYEza7|4CGB*({L#rJAkA$a7jzZgX}0jb{^LmYxkhw)?~LjSFgJdo&eVKiucL zU&gGvWLjAGoeLFhYj(R!2D1F`WpMN`UfK4)REtMbozH2?YOc3+Qjz{zi7auU6L}9< ztC}tms}iW@uQ{I1v~1U}Hsh4VcAttwRl4phS+L|(=;Wq9N=xSpsrOuPzEk$RzN13; z=A4clPwIJI##kSZWvG<imSfTF)n|1p@cDZQ?C) zU3{bJMA=z6uZ2eoo$g9rs_ri`7L!!1WjH0|z%Jydyo0@zokvyPz{jm*>z@3#M$X+f z`kMnc**m5kO+RrkB-L!)o&E%C7rxhLymuMD+@qG@uxLX4av}BrrOBDLZ{_@_UXFa! z{qTxE6X(6S{(Ex!!o}kkZP(8b>izodv}ykL$-+|KQuoZea(wQI)m^hEX`c-J6|+z6 z>WnQy)59laf89~D*Y4eun7HMyHS;fip7OfX@%}RQs^)c>dxFoK+*{iH)y;Oz`-`l# z>*ZdYeNt<+K>h;r-vxU0*ZN;H-t)6t)!653B)mX0aB10L$xoiOpEE)iE@~2A>?OL` zOVo7fqpQnLEI-II;ZnMZ*XiVA>0eK(9P4S#IO8ydXPxoMyHZ};lN?(@uH5yvn_m0h z^iNn)>*=L|f6C8W7NzO@{_Oo^;^imZ{O+w276xRn)r6h6pwXj0Q9t`f*28)^zawGc z^<6qwS4OP2b+s#B-^Y{t#4y%Ou7ATvmQ5dBPUX~0t?}*eRSz+f^FQXs_j8w?^!<(v zAAM6E&(_@hQTNjlIqCZ$H-ESpnSDADyep^1`p_}s6UU6pmz_FRexh9XhK8N%yuh13 z%8bnBUHy9f`PV;R+jlL{f6=&a1@|vu+xiRhUp4)U;r}B3WV+P?{g=M4%{}+L_`b60 z;^{#BU(L^4>#v;WtM@at-m~WD-Tf2VOVU1??_Ke^{8K;6qzTXdPt98Ke|ypVM>ExI zqm46`x!u(G7p!B~F7+jsx7$qn$V$BzqF-{uJ02J-**%`Cwa=usCfcMXnn$Gm&V-Do z_M#6@)r%b6?|V4D^G9(;RZEkoW`rr%%wHmRCYY?pe?vG97-$i9K+C4kO@l5GR%#uXCi^uP*PJDOOpgHrw`qLRfJA$JIm99bfq--QVG|{l1ft;GVeFUC(9iT3#!d_03LZ>q@Q%tqvQbIi7lRZh4x*u<1%( zL2FOZVTpy(4U0&@J)OsmTkx=fwNg^2tUlI{eq;m&{wK><4GRU%bfX z{8`AhVp^Qr$xN%AF3aoBTTfn*AkP~2?f8xi-zibNa|2f_oml!s6u!86~2UCw5snt*uKT+ zk%O$pqr)qX-_BD^3%DWsWKvtB+k~@1e{V$o%4|Dg&0FTo<1q8?2MJ9pck{lRyx%YG z-t72rzO}c%@q~wxuJg;9`<#|HE|xq|=YG=dQR}BC8ZQ~X@;Lp^+hG^qF4uAH34`tG zGb;Thm(Cydv2f_RHPvc)vBDSjMT~o*>opTNR$gzZ>$7W_RP)2`*HYDAslGS*=P&k8 zcprZL(*GnCyEDHTADV|d{7~Vm)slO7`Nr=aJ*No$3-8x7e2A3!wYQ?>eByil62Wtf zhn`P;krVzW?5ti`$m9N3(&sMCFA&Cg8Fa6J7XjeQxpZ@Z`g{AZVol9rjUly6b zCKYdZV8KyW)+y^FN@i@C;JRt%92N1yQK{-NtG9j9Pk4M^XHtjWRiRm~bMHqUi#YUU zT_>mUv=?7=CK?>BD5dM|bc?~HSOZ4E4fPmF}--@LzX5l6_H$_CTpWj%&X`@V7-7HJFKIh-(B=RmV&bYkwEnAzt`_i+uKAR7%`t@64 z$;!Zg3acwyuIg^=^)h102|YTAuV2|3rmR|&vg(2UuGJ?N_#{S8`fYo= zOGK~pbM>=BaogA3ua^)gTi>vOy*;nreTQ(h?Jkad)|TC24maAJe?J!FOR9gL7u&L( z@z6q1fxZV9Y(H{*Pkg^Z?@&L(p}#pk&O73?^B;YYw|-D2QIMd^oDkT{{yA9wgQ0}M zIliTNljQxACcWAxbTpjRBt`CQVVJ|WPKoWEu409=OH!Mq?mjb8TYB!X>@S;5oVw?H z)y{L}s9oIoKI-hwt-8rw`x_?fh*b*LCtpkt?r}Z7X!f(tH|IXFY$;!UVx1SmmNxq( zlSAZ+J3sAE53PK_|4C)CyGEeg_hkzG1_`kp@8+l{%5-R?<|jB%fe2urM=j{GOzMq+Y{Rh6@7cfoUgn-x5?aS zX+(N`{;~J@JNx(6cJ6iNO?eYLmq}%kYFY5|i+XdC&HJz3>|K8I_xVk?C04%oxm>V} z@m%qnvaiqFr>|wqduejh*U)sEtLA#&(_Bnj`|OxazgR}>v*Y02=YBHoljJL(w&^Y-(+#(_8|n+sujqUc ztgy)6eSWV@TS1@H>eb=Piu&$$I_=Od`L(|Tk2qs(~+?`_^?vVWS=+4JikT;x}+`m#Of+l%&ahd&ugkJN+R{Lv9=gcLBPgWk0_;hB~Bl-SL#rteb{+rV$`7HXV z^E>a6%D&CFR7|)kT2~$Ov^l+Rx{Id6eIe1cG+BI zcC_b@Q_&iGzazi)ifsI+GV6J2?)2rm_`E6~I(|AJv0h%%*raEL>R-!mn>X(I)pq&K z^yN465yq_XA%Du8`qckSni^jv)la`NE_MCw9OPB!5_OVWVc+x4 z?mrf82WtcCeowj4_vc&TsyC9;C#jt~r~ltVLinGD*QQ4u%T=q6tiKi{QyB5@0sm4J z)dWwK53fyyH>jDa&6}CwqrWuG$EN$X$(rH`sezkJJ$pKzFEBKn_w47dYhQLtygia5 z{)wqR*UfZKK=q%n!*8G8?H6YhKYH?c*er|f(}TNT{aCDVa*}|)zmHSBhbd>FdkJ%j zjE#VLOjx-60x|2}h}R#!c0K;c`)g5^YFkj`lpx9V*EFVnlv)}S$Qr^e@;YqkjRiqD zSC;>{t|DUYrfD{JdB<qpOa81Kw} z>s6quwdP&a9`Oy|RF7Lt=(su~$v~=yZSjsCe$M88m6V!UJEM+0uii3Y^1<)NTIbYi zA9?+k^W&_vwPG?N^-LQ-R^==`DdRJzC-DY$38dziq)DH@CB zgu0q+tZ`L$=I`hrc0#0^EzDjjpnc}`O#o2OAm!|ZohhD9- zbL&NO@XBny-o{Jn2s^2U3qAqq#{)KvGUA5oBYC(IB+@JEwWlHUD9q|sGqLjqBZkJe8 z?i+c1<PRs|9Sh>xew(Bp5Ohjlhf{f^Lh3MpA&!7u-M5rpO^ix zQ`qkNwTr=1G}*&>D)N^0&0pm9boGLovk$+|U3AUrtw+P9rJ?`-)UEjUbLG>k|21bV zK6tBM? z?}dMizrH*EcF%BM@K<=t+6()fa{hCJwv8V?ddED#kbxn(4Q;c>=GcXgA^X<^k}Rhi z^fR$d_w8ol*xa>b14LNCS$cYJHxu9HwB?oHZE@50@G?qo{<}V2koi*T*Xakt7^Nrk zF>_2V5aQh2eegAS)5zw^BSPTQWF|L6N>BeVg^^>rLMs#Z<~_&DA*P=B0@K8?Iq}q1 zA&^nv{pyhojJ%s2@5Vrs1**wRf9J<2JUzjQk#+Nx`%}QCgYBGdo65+udD0_xusxgS zJe>~FlJ`M*a)FT0=Ij^jte{&M8sJx762862RKV;4$q zU#r1b&INW)q79?;b|+&-OGXeEw5@RaOcO>nu*0@5GG|-@7M~6}xo3N~CF5m?4T(04 z*T7a!2E}8-5=OS^7p5?AY;Uw@TnkZQ=)^b=;$!}6jMCfR`Y}Q__<;5*T5c~4WDEuC zpKj>HC_OoDiTrf;X-tCKMM4-?LG&LCV{`y}80;kZD8_WKL$-HDGadswZo2(uM(OFf z@r+#cx#71wMCMtaWNBK|%OTdi%`qS-KEtI?-op{GrJ^KiizYGjr$8KR>VM?^kXKnZhoz%4)CQ-8-A~ zd>tGYZ@RMfvNu=9{}&~(4v!^MpURa`-eQS{mUY4V z4Q?6~d2jPIkN(=+BmK&M{<1UMo_}X{woGvI>wo$F{wrPe=$AXgZKvyIToN8te<)fQiuJ#FeA`~1tdD{02|^FH*| zbKhJ$FScCwc-Y@1aew(AU7jz0PBw9A**PI?yU)5uSCys(Z@->6-T%)S2G{ycJ;!;C zmLKa&H9j@r`zmYO+xFcW*7N3zdTx02^jH{!iS3Ea$!7XDU){Vt^WUu=@2q{#)|tY%92VwZ_4w$+r{FlEU)OfmJ;%4I1CnHaK% z@yXl=aqnLl9P+Fd-YtJc;Ag7;HLsb!W=AAdPkCUds()%1-{TmQxQL$h*OV4bx?=k9 z>$VFsGJ5snr?>|lOv#jR@sqw>@Z?X5S^d{JIR}^Mbe$Aw7tRd4r@jCD_a&O#*{j43 zm@i^G&U)QS;I_@dPv2&#oRw&~ZQ{ap@#`|d=$RUhDbtQTj-EPsPjIEq$=NL|+6t}T zCoL!ts;RRK?J3NhGsRQKMeO*b5O3?SqFjFlF2!}S7rkDG-}dIdeN(qWse6ObcE;0z zfww&Bvu?H5{<~<)9I$jE?9G;UA zqhDAtnfv0m$1jt9C)pqTHg&bE`t=nrp6?c0y7Z9x>)Sr{rG;4?r%zTzuRD`)hV_l{rS(~HuX}EemI|xujZ{Oo%=kiLa@QVJAmyRhv8qB`27rfc2=&= zum0ugug@t{|LWyaqxuhS9nU94q?Ri9o%r?X>d9Y+vVJ(9o1-4&aQ%pz%arFOz1RKc zoAQZ2W-Zh>mpy6OqmGRmZh48w?C&eMcm47u2YcTZ^9Zr0KWc`IWqmp z*+=VlZgJ6OX+OlSciOzZbW`Z9=5|)z`qa{@CEva*QM#YJ?|Rdv@2Pfwl$Ey3u9?Bs z`C;nQ<+kh>dwBEPU^nf=T;D#`YZQ%zWMfta~L$brwJ|) z{iZJQFf!fE#)*ehsD@|3f_^2gpB61`wLFUj<=rpZ%Bz|@OHNrJ?H(wfoN?&*Z{{BU zg6N_K{(wWrHBHWLsyMRgzzap`(;6?2r?dTB5-{uR$DYTA2D4I62!8uK!`4~H=J-4x zam|c*tWG%_PLzFP@vLVCRoE^k|KBuYWng&7j#gn$KJ!I-yKO3?Ah;~v9+<&+MhH|< zOm`G!a@w9$&FBp&t~b;&c7qG_$rBQ!w?{TG-T_xO(*s^IN>Bc~o_%{%C*wPakm7Pi z%k3?b82!LHK~?th4^tSyob8{dG0udr`e!nlfb9gk;NcubXYjFY+trsaeut<~T+V0< zt_ij$u40r1tKD9|7Rs8wp_b8c`@Ic}aS+A!n;BWaia{0D_WEs%S#Z}**Xdy5-7d0| z(VP`jXM)=Wf909@wwLc?i~;iQG% zbaUmUI9CSkTISVSG0Q?sLQU=!>&p38#RIyp@V{^m-J86eQOJ90R`$B|cSYysR{weZ zy?;JKS)%cjT}FH|<>!U3#PD=L zPs*&b8$vcOGvqn*aNDW5%iGlT7B4^ zkg?S#r?#Eahtn?1{c?_{`!erD7j?alqUUyW#I9PG7C+gsTgAE3i?LPfy&F3l3j12$ugLoG zr&mcTwLwfd`nc82^i0;U0(HkVNut@Fd%AXSxjgBv?HzTwtS*<*}z!KXZI-+PAf1UUUo4pft_4@ynREOyS%%S%lz z$;{7ltw>HS05Mb`d!2hH=lWj`5IO#T`-Z7y!feUHHBJc$yET_~_)E?bXc1p#^tgmm zfA^&`lh(%G>U*I6X)QmecT7@E`lEKEdAH5DIVPIEthISwe(vY}>iYjb|1mf8rSlZs zef@LV-sf9#+x|q?|GvO^??>E=$hd0V4QIBURM@v}Z%zK2X%b;Pr(b8-nO{=6EPK8* zSG&Zf{QHqjyK4eg8TsTy<{mFSB+irEbt^&Q{ztyf{WeXzJ2>0Eggu$p+Ovg+Q}WcJ z=dA_%*aV9^lHbY>scSCB%UgWsosA*^VUD>%_mQvJtFpdUUqQ(4VlBHkI#6S zb{n4YnBg`rrOW(P+;OqMgos^M%!1c7U-!wfq;)r))ml}UA~!qgc1d)U?HAeYu8PkJ zosY@n8Hr3W{=M~?;KNl}&E5skZi3|=M?W+RPgtV9w6yJ#hLXV<3AxmJ2DRZ2(H+shz(^F+ruNU{b*Y8U>u%Rk)qWE-)qW@OiD^davaqZ{hmuN};Thp=d zxl>I@-Fe=*eQR^gn=hEJEm;5D&Gm&+iKO(2507Q1cWm=)y7G9n-CP;t{Nx24>XvhR z%p8g?+MnP1;^UGG-By#e9VVxP&)XL=tn7ayZujgv=j6_V+C{=E^uy{Le|6pTpCMDf zpd!HX=vq55yUTqInpu|xJ&qe~@3k#3=Q`ou9l@lmcXC3(eD#>jhMmn`@~8d>ToOw8Ly5ixsQg+ z|FDA6rnuz)7H1{~hRMijlZ64)fdZAj(0LmtspZ7KSwjb;fe|25J2;+}xs_=Uevj9b0hv3gcHj>-T+n=Mz^GAa`k% zvET1S#{UB6&f6_L*_Y$o2_DPx?{n@Sw|#!^@AISY>zQU8O6Ms$xF$-qE?U31Ex2;u z+S}RFUd~Y6Tys<}GqpF-VKaB%QfX_R=k-EaC)a39(+K`l?0Ho;uxNK*o>VcTARAFRH5N^E=At!W8zpAP=W`#F)N({WQp=j-Yza(*R&t^!Rm#~2Q!Ts$puhHJXP zi33?Yi&-ibyv_8AG%lNR=NfZd5r;`jqGVu?K(h7gnbQlp7XEL`dvVUU?Q-Yh4^OIC zmKVC!3+y>0@GT_VxB0kg&&1nP@2stU6*MO?;OkS5uR3wuifzR_>W|Ke@6y%!lbd9* za#l;kb)DEPi*HUAo;BB0rfuRj;i_lWcP1H}6!`42X4S(NqU&^KnC3lS?G`AWyTc=Q zrBrm<+KgQ?w%;fBJ`fTzy5}%S@l*arfdq@mCw^JqsPV6#?fH05_H(hbUarR5a$kMA zy+v@V`?0qlzY5$tsN)>}&hPu5y_~^UdG}}sUp?FRv-<6X4|Zqg+poz={XL^@;$c>u zQ!|e1YF*6<-M(_`<9jmoFPx^V?BZL#C|oPl{Y-$MsE}PjdgOx;n-`+%FS7l3zGX50 z(bN|e&)>Q7KI99NVA9LjRQjvBE1=im=>|37SMTbrg^mhw9lEG@*SKxwk-&FM^%mEi zH)Uj2-`T{<|MKqPT|G+gcF&$|-jTKF_c!@W#jUz}c@ckJbVjPrYYO1;yHGDUqy2~U zf@nDhfhmjBFUMXk*ZeB2#FO>QauNHE33Y8RPCaGwTbDL3`3r+`y~3`Em2DT*E4KFi zbKdihyYbfr|NVyFw>K3^%ve&DgD`F(|RmP;IJownnu$ozK#`)?@9 z*&kS;{ZC}&@*PEM_PPEsdl~H!xQDBquYTXt%k%SIYESw4rCxzu4sFw2Iy^r)aNSb>zI7FxKVGP>eTlWmdsda(fqz}?zLR;&AQ^!H*$8(Sfo)j>G>kxoA3Ai zJIFrW=0|}~&4*bZvP15=8`hY8m~1WcKf$JJR=?7nq7R04nL$fl#y`2SKK6iqt;02z zZ#(^+J_i?Gj$;CqR8M#JynfBh!0;KV;mOLua5?oWbQokl6Yq3>878*rYu+;Q*GF+z zh=hyUnXl)Z&8gDJpvc0+awDfffFnRC&Qsy-v?&hLnp(rGZpxlGkXCl{X6v$TORt4* zjmo{cYOB}PUm32gw;UGSYVTi_TYJTQYt;O&o#z*YuHO1}j`il#Y2R{gwAR(^Hm-iR z^Z(EDJD=aH_Op|#|9Qok;erwqlTD+ClGv5{-Mt(17Ub;RXTMN?Q&UugaDa)x#z#!6 zs=j5hZ+W&M?Oi6{k>s|W%Vm!*nkdo7xxe91?XL+9LfS%imM>m$Da`z9MX^Iyz;1&{ z2PU5U)*+br&iBaTPK&0Ow-orqC6+a;TzT=_k#~2ieE7eLV{Lu)W3!f*T`d=0a@w}7%=hB?_Il&m zDErohRuYmqZcJ@g@3`ORJ-8t)lFLVE!^zu^rJnda^KokBn(?MFYerMaBjz^Mgt}Rc z6Ox_vyu)u?I9uV|oaT0>O^m0zsjFGabboTlHs(g1Q4pV8XT-SV zz?suWJ!jY0PMqJWEhEEo^2MBbgB>QfzpiSt4i0R!G?*SULw)bLl1a*2m6m__a7^mt z4F1iLn{!q+aOE#PyxrU@=Au)oRGraJG0qjzsXOkP`nIxexWRmO$NGg4oByQ6v@YGY zB=msA*;hR-hjz6^uf1@)en<10KDXNo4;Ag`xDuY^mKoNcsOYr2cY{|FTgj9)8&$KH zE;)Q;ul>o{?{f41$MINI8J_kvcXn^(d!e-9>x{F8wkxFB@7&gxlJjzVkYujHo94Dq z`j6ZW7Cl#c-Oo&uFHI~{_tDIrcw0HQbl0RiW}G)>o?H8x>C+U$RZjdl-yG`oa}HiM zkXsmhZS4_tgVzTx6&pR3%u!~$&FbT`?)wVox;($<)0k$Y3ol5KdDEiJ{ZULSbfL(x zi|1o!Jlyv1wC`b)M{Qze>#jQAZIk26?KrAr$oe5HOTsi_|7^G0uP*DY+xDwF%1g0> z^W8UZ#xv_KRjBOz?Djl2Yx=uJM*cT!%=P65wT!m9wbmM3X8tR1?DwU8&&y0-{N_|p z<`cQU(lh3JsQbUL6%QJXKAE?9_KPp(4SoD{xxl?GCN|ffdUSl%S`pyaaa|$x@D|4G zy*Hl;sK_za&D!nP`te)RorYrPzu)dCt)D;T7_0KK&d!yO^;TK!-u3TZ%C-HB!iKif z|LpxFQNNS(-jhc2L$d`L&A0Y0Jal&3m$jcB6{T#yv1xm9Oktf@&1&5`^_7n%ioWLa zJa${6c*czF2X}k^wyl^d-y>OA8*Z~nJF<7nt}n%BzFI%1W%*gh#=iXgqG5LwqtAV&rhtc@QrITW(cuhjaRrFe}p5Vus7?SQ{*49_QF#O8Z>SAV^&YA z@lC!X->N@(>-q_c+axcopLlZW$~h08zxvaYy5pxr&0L;(X4&F5Vy(Kj4#b_anLlUl z&%y`B?>&Er3H~$_?06~hAk|W+zPbM`?jZ+i4 zd8$(U;Q@)3^Wvec&mWi{`L#X5|46T+tbWdZ$pz86Eq}uVzwHwX{j8`HoODHZv#qFF zdhE1U8kGhAJP#}?`L}q=ra6}7>juYb#= z_1=7FJg1KFpC`wEr|TRC+iEY0{c|t-|8N7B{>`TU6JXHgR?3rf209M|mGL2|s4hE0}s_iq1K$MSatL z^rt4Z&9MA+-gxD5H^BAGQllSb{WH{`JwBGJ@LuXz+?3o^ z86tL3O={tvU)`F!?U~b^^d!N3C#(E)%C@eE?YkxP#_33XP-IQ|m!_aZ$!+yXm1)h| z>?;q7Y8$5o3+HQZNp9B*OTE9L?1sojHscxx(bpRy1+rb)|8=ce#Jz5D{Ec&~UW(3C z+O_gpY@nK+*z|x8A4D#0{4>9@Z|lJjz8m%3!G9y9j_-Q0X2Jf?8h+-jd)>Az&{`zU zoix3_>jsnVj0K+;2-IIr-u&Y5z13Z1?Aw?^r+oah^2B}CE7MP^f7AZd8QWIVH@!;s z%CU!=dCRL+l>IshJ)0VipO}Qt_x_j3w=h(xm);$if zUNAZE?tztMn^#C%UX|N%CUCFNz`miyxN&fV8%$MH8jq_ywxJz;|%1zH@Bm$vG5g!lcP+?42a+NK)!TBuk^P4i8zHX>;A|*dYZTCwMP9us(rvC=r-*o; zY)TANuGjkX-1C>d;qCL+<=bc|TS?1b4f4!gJTgqX20vmGxN&t$x5 z<D%-z8=WU_ds#algr>&5yt~D>{{7i?DHr;3IJeKg zFFz^FIDg;!Ip+Ck-;Dijzc@O1NLRC|_Fc>{dUpL+lVYz>{qqhnj$?ZlE)es~>HB?k zf>&p%m6U%#kWqn`?c!~1S5Aby&QKET@hNq_?_`=_Xqwquk6=4 z_6N(0UKCopcn>F==S7t-AuntXX1oqCGMwzguxwe|!r83KQ`Y!>|E8j@zIBF}#KkKO zVu$}R7--JmP&@R>=Wo3!!}C0*KCyfg1}+hP7Uf$BMm7tN@~skH5wz1@DzA58)Y|ST znIee+BlJ^Cd${7_xi3<9ibi;VMkMuIoFwL9d$)s^d4PgC>`nS`FYa0 zuaj@w-g+-(=en=aR$LyYs@lf9>B`xT%`PGT-92aSKA98Kx<*}(J<`2C>);&g2@mxG zj^(Q5NQHaYW)@7)y2SDB%H4uZakE($@8~z_4NmG;SAX;`qJZhlM&|~D1+U-qw>izS z7wmD1a^HG0Bs<>d(Cu5h1Xn$pWXfOQ_VwQcss7t1+`QQCGSA$5H~gTF;@OnV%{fYI z7kDIDNi0vf+Hhf}fQZ@uEmEBsiuD^-e-t?`ApEIGU{+5;M%t$%3jI#EcSvz3eUK1b zvgEA!qIpY~sHSr-I#?Fh8hC+i?h@(T4b77drKC)hSA2E6(q_hm!Yg`3vVET(2+O}` z6?RN%Y5JJyW!7OLa70vf?oLnro|AEx`sd7N+tl`0;OVqVQ-K9b^wpm+c^r0gHqMZ* z{}6gt^`x63cV=UtuA#}|qaknlmp>}9SG|>_%Cf|A$%5h$w(1BOUbL*dng>=M=i!9lYsi@0yS>ek#>8NWOit13iJsjoKORYYS1A17xsHSD z_0gLNNmU}gJj`9C)pA~@fkt2N8?8CHZu=kmn^#k=MGCoZZnEqyDfT%dDg5(6QSZi< zX3x(*>OJc}pDqkNAz8$CbCTKn3`&2dM1Fr!8hJQ|0 z+E-Y6)qgO3a@+gccZGuyle5StvAr+XdYqcgb7}j_xB2euEKQRqb5$`j=n(Ti?OOsj{G4=L(ba1}fLYPhgjx{8nC3-f0hibD{IGSuy$@eDlwX zaPIz;l*1Ho!u{m&iC@((tZ`sry{2WDK7&2?rxEkx+O8V5kM`ZGSd|%hH>K3i?P&De zJol%evF5kRPp&C{R0GaD$mTp+82najqqzT{d4Ey_+RuldxE?TJ{bGhaO}Xa-8+^KX zVz-*iH2bCY)2!>8?1qW-AT z!Td?bC!9TRaQes}o6czFl{t2Tk6wo?kFH-3)z?}4#fV8?JXCSN(tfv<_0A_xxfrZ* zoy-}Z67tzynbBjh5dW^P-JeX4o29Q-*Z8P+^0j1%<@43|C)-<{kUufM;k(GEdsEd{ zdG6moVZYLY`v)W$PJFd2_&O=AsB+RD=AD0npEIqVwkkICh#E&Ca|;$1=H zMWKnsT=l6jfm)6)d3BQ~P7v$=K970*F;T78wPCF?&o5nOI&gJ+#*{bbf~$hd7V<@P zEZ{oB&f@!a#fP2gehZIQefOGS&v;foIHOa~Mf2F^W8XWs#4KNFFstB3*4~vuZLK?B z^F7OcHiv0i*u|_T!Ob;0thMh(y2(9!`Krh$MRNIt(krb#^;w0^^=f_6m4|bAtK5}+ zrf)czpSO2&=k+rYZhBEq*%vdOHOYVBwqmt-_l_xD-ItuqtzW3!;&SrwQC#D6`^z%j zfNBOGr{`NQ<(`r_JH7ebme*!gx=ne#uB>7MSy7 ze$h+ADj7w8h7^+}+?l-@=|7zt&#@@iJE?zuJY{|d`*TG;)7TlF_e@UBUiNjFf=Omg zSc>INyF>oL#ioWHm9yFeCAP0-w0R?YCieB6Pp5e1y0RJ0yW|wbG{y6UujdE(lr7E0 z#uv)MzQ40v_rOPhpIxiPR54?RVS2sf#yd+sf3b18KcUIZ{fMcE)cMbrk7ns~)co=N za?|3UrA7144YtBudn5Dru$Ii=aeUYut}*pyl7K_r((~@W#FxAfd~CM&Z5hL}+$@bH z7sOxp>U)}2ZTOg4_4u@*rMqG1-k|F*LoXQ2=1~**B{i4HY_gc?%o$-XWOpUUAD`NK zwVq>Y@8`>F=I)f;m15g)e$RhT-}mNeF8uG$JWn`U6XE}UNq*S{^NZUb)Vi3+g#FBv zvER~>e&%P+osucrl}}kKocQ~YLA>~9P-os-zklvu#bRPFR=?OC&{|%+mi1(i!j*4x z&M2pq*&9{!A6X#fe|M#&c;nKTI>qFxcvEft)JcoGQ$NSKT6F0Ny0{=JmR+s?-Z}? zGo%(?(`h=jBWyZ{A}g1slD5Fd@EYX>%wan>_d0rMLPn|Xd9R|tT+2$y<_Po?jWV&O+qr9 zv$s0Qyga&Ca7&$~h0By0%Uj z(EZa9Gf!SPwyt!;TOPBvYgIL=i{ldKR^^nYu91v;_t0+}a}ew8lj-|4EsLA(PUyc` z`b@OF{F}qS^tj6zF*c=5aS@V{_fxxU{l1#4*gK>CJ=g94zn%PLemM=3N~hlqdcCE2 z18dCR|&Q7&f^Ljf~*!D`%g6)-$zb)EYw$hc?$~H_pd+O|4i`s7=s=w#9ytsd=rgWIb z-`V`T|0auG{d+WS<*qB5)vs2jKF_%B@c+Uor?8lpfv;89PyTv(bG6NYQ^G$eN(*d8cVyK3gef% z9i~?qu{PU(sq?p^G4tj{hPdonh zirPt8xBBH*ro9T6idwzvd34JBqpvmJ=xvqftFX;^|8b)2malCwQ>J~=K*uIYO z%QwrnU(ZA?@yV5YY4iAQQ2gp?CRR@k{VV&ICr*ud?Blj-yMNX0Z)aAWvpS}7JEu|Q z{q?6)*q8dAdu<+?CwtetVqg7-BiD*no(*>YzAMpYZT*XnCTl0%)>?nReoyVAg2xB1 z{?^{^FE%|qY{RZwh9_T2ara%ddb;SDr&jKjxAuDiH(5vD^5?f+qZ@6tH)vtbUAwUK z^0itizFXzCZam~2nOS*Q|V`G7rf_Om%lMb zUuOMg>)5#IS_iR4% zbmNZn8qw!ZubIXQA3XLsc%szqCvRj6Dzj!hxfTCBZ|$oYao0B&I%lWWe_uH{Rz^QE zE5E2ZL|&n0F}Uz${XVRL(^$I^Xf)3w&tPtwvn^8DJ#zr9n}@vd5WK`lQ>RU$qtF0I_G zGG*ljyEDf(%cZZ)nmdI%H{rij+V?s41NMZKdEB0DW)XY%%0kPwmxUAhzplvoA2#!( zdBq-Ex#d^#^CzXG-4B0VXk|MuDQly7;QH3J(ht3@6ibr$ywicpK_pOWF|_TizP3mXjkC_WMh`#w;VY z8xaE2R4!H}Cof;P=f-6^RL$5#pRdw+-QIh2`o290amG11 zoU3!5z0NZ$6U%a|HGQz!A#34$WxW-A+k~yHk2>ibs!xmPQN1Bq)^~O?Q&5wt(3PXA z5ef(O4~P5w)DQXpN4%^2AGfOcf8A##ay6QwbCERf+$XlCSck8iTq5~m?+1C+ZH&K|Zfdf{ub;f+U~Xo?Y(~G6dYf)H ztZ9sYGkLbSN59AR*vK94BkjJ&T~crP@|1t4_&k9kc}aolgdh84>TL}seLJ9W{K)d= z4=r*M%8#8I`MVFEW$ItTYL~%LqcZ!z@lWDEc6dGzezK(T9;@w*^xV8i1>vMOTyvFr zb4@pBeoPOHIUWDe)A^&OQLcmE;fOiMxU}LjHK&W8$TWPXH&?HB^^!tSA)_hb9y7H2 z{RM@dJ_|a*BjL(+DpJUJhg^O0f1^KECF{6VG@tGCUGDX{WJ#sfB^%kyd3??4s_7?g z=FEBa`T3U~ljWZ?{mdt%fBGlA+2Z-mpVrUQ4qI+dY1~u#bHaJ?_D8ut+aA5WsdmP@ zXs&_2um6ncOV!VuJ=RjWGvZYEGwr9VPpocbt9iTkwAlmMC#6m&tUrH08SBPWms~G) z!dzeelWwHK`#8HNw>LTLOa3|G{TZgp_n#E+Pi6g7Kb^mFzJO`P%?@=1KPU8eZ2jx8?^fNEnlp1UR%MHwQ2!i1)7fFA`YZ#R#6>?ver}QY zTby+Ev-5wOpG`N{T;+ap`X~G2#WHgyt)H--i>1D8&+pzptaT>31zPXxCf9iP{JZ<7 z_phz+ukS|{KOU}ee&n7s2Q+wjS?BcY^Tnm-^)J2qxm57$ex?4|JQ1y@ALSRDK6u|# zcX!GzMnmC+jP>(VXZ@@EdHIWeQuIID_-MPCN2mRds$2O<#KFi|MeRwdW6-JFnyE>~ zL8mvJ^+;`~7de>~t(M{ycEhLRkMrBgU+q>$R(6Oz&Gp&k6y4uAeh$7+4lzH_TLzu5CEt8|^vb={J;n_i3U>RTs1bEBWkBsJqpRRcf+(Vo|hLH3s;@pd!!`I>2}MKXxAmTGj`WEYkoY#=YsQUw*$-d#9DTLAl^zLY&3RJ7v===Jh|b zIRDZyd0szfZrR=wY3-T27amBuv{>y@$qd=ko5JRtG2D20`EvC=S!+avBNdoWw_j-y zn;{gL5S7swd{ehzR+~#)SN*dWpG(ZTxrJgC^`P0vETjZ(TyqfP9e(zd( zrbuh@{3+ir{B{Z2XMR0ZMfEB3A(dZtfkL$&9>3}YU$VD2epCz$sEO$K6)5=Xc*~Oc z0u$>d)pfm51L3y3m#mcAxMzFc+!eI#pJUkcmm=mh>;1bg9{nt&xRrl% z+hP7qyl2HDFS~AAIc4i1^FNu<3AZ1-RLVX-MKFHCige96(Twc2*V!lcg_?%PCzzh) z-^8~e-Mpsk;Bn^pwjW;Rx1W#u@uvMe7Z|H_Mfu*z@DX&9dzZ__M>V{(wv~h)sriaNN@kA&-4{+1HueB zW2O@D7NN<@%&oScH)q-bnF|2xUTVb@4_Vzll8Jr$C4Z(Quvrj41O+j%f&DNYv^{5gSv1p2um;Fw;Q#cQ*tfUDF=aqP z;(a31UWi`B<&0L_U#2j90W04AAf0J5m<77_TYCG(EGA_(uyZ=28KtM6TFu10{ci!2 zI9TuGhDe#oxoSew71l7ZZTBu_S_TeW@Ybj8{FO}cU{%`-tC{-2EO2nj)iFueX9iym z5V7rFyQTL6Q&WV77VB<>t?!~zG8aZH51Q*F`!sl#or2G-l1&Of+W%;2rCyQzI@|c4 z#_``y?57u2CuaHd8+R>x zwaWJN1-ag-l2)7CrYbOY&tA1=>dwrSZTqIx$EPHOq=gt}c}@-w)t;&ErnD*Vg>;`> zW%4Ss{v|dqrd?p|7mxcPu}i5fxp?xzmd+Yd*vm zdd@IwPH2AKt+d4?V_E9VXKqb9RvGxXMT_W#ZR>QfDl=25S8Q0&f8u_UMA6!bCbDmQ|Ma>O49q`)Jp;N%2cBiu_|-R_+^zVs#QfYZ zM<44y=DQwc+$wgydNRU$H`n^xDgOLvs%JVZ&m_)ku{oK$FzM#9H8(8X!&zqK%=)OP zJz?(B#lZ?sGfmRMChOLF|4=T7`YqNzzw#`Pe8(-0f2{V(KfGTq-|X}+t!nnAw_DnTKl)2#JSbug7vk;N?|k04 z%csVz>ETnmg^hN*94ZRsOZJ~T)bCn#exdy7C)arLc3ECD>e0MY@VnKpw_YXU0qa*^ z)8FTW-4-mVc*O1|wc{@%|9$!J_eH;Tw}edYTkToVV)9h-?1RG1Q5$!52Ru^$6L0wa zl>qns$DPbRN0##$2-qKa^sm0Fy|24HM)&1~9TJX(Cwrg2c)xhY^m7-Cn(7%qrPzLd z>6H(e7#Q9luLfqg#FYAV`rb2)xYwmam!*f@4VH=&v)`^Sp5w4VHOZmy5{FjPCXb#j z&$QWn@-9~zI^7l*MrCZ|E#WqqnNqg>TjsxxJ#SBk#XU33JH{X2Wx zH-R8Q)BJy?S<;bemQ7;Th|yUqw3WYA%aXdr+?_nXa##`ZXdm^sGnM0n;!4 zx(p8gj}Kw*$P;+bCVa>s>+7$|H?D@$r|~j<7M|XjJb$9jmc0FIU(TwWe&9f;%zfz3 zILW)dgL%z9NuSDp^}-!xYwtc$HKiF|o> zab=d{ca9BSmbpvccm;mDQ^5W%YEg~nfx8gZYMZg*_$_Xx>;I>B*>31!+m*3$;mjFX=Z}8c9CPNV9(&{c@4t7>sgDbb&)Ih7 z?Bg{TFP%Qi|0-*)!-qu&A|JQjdc*am!MEhWiHeUGPP|+e75Gv5OZ=AWbC3IoEO^nv zzQJ|D`{Z(&4;-b2y?sr2H#T}zO3PU%GC#_TXt{mu1Lv<#|IQ{IpU+=oTW~0NHQ!so z)hWv1sgke1Y6q-Y|B-`tTXw4VY5@t$`t?d*Z~WRZ`MLJ4q-|1KtB&@?&B~g5q5gJf z+2j_^;})kXdLJ_d)~5v6bIg}b5h~v6pMIY2&!;~j1q-*9UY9xVC9|0M(Bpf1Ba0i3 zvbfH&tbU}Zc}g(uj%wn>ZxtD96tu1!{HR&(%71I8qFUGG#@p_8|CY{B{c~-z&y!zY z>Z*3uzw@-%BUT?K@M2SQ_pu*WR=AuMt*$KSD*C6fe|FWj*{e>L*FL^nZLB--x%6U@ zzmLUF+&Z}D*BRlL4_CBr*rBZMA$QJt_6%dbAoc9qds33`bZk-J_@uQs{#ivUPfB0$ zzuC=^o)W2z2R=PJxMriJ=9Tw`$DVf__;T9X@>2xy(Tu{bDw@ANN^ zcNzFq-Fls)A3JgTY3+Nz8ST%Cx}VH4aO6JmTJqzCyNgy-IL&!K(enClmDqb9-2>iF z=s))3)Ukgx-g?jW-@B1s|K;`Fy2O%{eK8;S&-=1pw*K_@&x2q8&TLf3G83BCG1+XL zpjCAUC;xVv>X(eaq@ScOnrs*!F>z6w*t8&&5Jw*FH0gf4?wi`RUIy z^yYk4nYQfvvp)W=i5s5Gezf=Ej(7plPtk!wcV+)y<~($&NX>9U&8$^Nf83Z9z3s05 zZAp2BWJ9-CWs#5efBKjbqsCXvTl(tm{J-^6-{`!*vT2*p;XC3>CH1CuulKP%dB^(9 z4C}229=%LdJ9w__a%t|H>!SRR)ruWGCv==CT+G~hOKADJbk8u(dt9Pvm75%QUe<^f zn5_JH?b>M0HS43Lq8}~ZdLb$Jn~Pu44E65xUDIz~Z{^VE+r4Az2dBH6)1P+6iEm!H z%jojD*=_X(0T!Q@czAHIhAnsLEOaf8m6>TDwCU+VJL~Uz=J9fT>bQQAZ(ZxsH!jER zXVxt);xke!)GrotSGaK3b=%fuZR``4ylz_=v77VVU#E2MjC|JTx2Lr2{@kj2l=1wB z2YK(kW=*^k^wDH>*8Pa~nao)Vk0d{c=vyuiV3jR!-qe@2r+#;(VnS?fLEFO@QUy1d zU;I?wp?2Tl{r7~wtZTY2T?#Ia-SiaYG=Aq{Sv!5hq zyf7*`vgn=i2i7|~j{Id)3NPdiclgheJbl3lD?Z`a7qTG@ho}9QJhc1c_6Zvv++lsD zV)s{8z~^9zb;ds3g{e=)>vM05UG4q;>5h}U@%`9`%JURszijW=maOf2te&6yWz;=engzwXtGXKvtrk`sQkeh1r6 zJ-yyXLERNE&Kdlb{j$aQyK&ANzP}v&_Yb^_zVZ9DD9b17iECV<>NZ=fDn1z&zrXbG zOQ+`o88?3^EOz3~Zz3UG=_cZ?HzxwNj+&$UdDn^qczU`U(Q9dC@==DQ^ z)0@Av`(J7K9_w4N+tkte)`R++LYE)e9-PmuzC84gtog!E@u0SX!_A80x7ZmNY{8cq zGct)Vh%j(4a4@_{{W@K@k;xg{$0=@PatAZ^HZmoH8OlvekzhuB6H^hG@ui8$6U=aE zW=aGzmNYZDf*Eg`nWDh0dCwN6crasi3zH*Q>U|57KbYaz$`k^Yn$gPS$ag9AtIboM zRlk|o85mgjray0GvX;M``qgHtF!#DyObiT3tPBjM49H-|bjLO(7X^?;soR=ItXLQr zoH-d7RFKs$Y_*y`@h+p(^!;s25@5@2wJ}LEIoeO3(8we{ov)oqQ~_kmYNQLEB~T17 za-OX3EHyp0oe6T(K~6i9G_#u*!*uxxOw!XW7BWHh%I<1sl4fEL1RFcqKag#D-y|j; zum^0^ZYGGcFfjb!W?)c8F*Y$CXK} z%nS^LEDQ{&er%i`*U6*~4hTi0J6!cq>^PG?`ER=6^vX6S9!^k@wQcV;Q=jhN!X(PL zV>)9OlQUR9^06SOG2xgGa+AXJsol^Zo7u%A&GdKyNK|Y3gDxgnko%`~Gf6X@TnrI3 z=!YC0A_9)&DXX}r$8#_+%;ZCN|KVlR8@rj*!122ZWI)FH$sgBCPnTTA!~-&P`bUu9 z(*qz=ML@@jOxNy#I>MocNt)^ZVMx5qKf*P=t_P~87bGKc9Hd8V`hgxMX|PH6K%#q2 zf2~5(=Eu4(gFNQJ7O#d~3Nd_DO zk`tMvnVonUr=Q_vl$stf7aBKnSntS z#i9R%r$3y?WSjs>#c7LOX1(NKV0g-hp7EB6F)}3Q=js=Mw)E-;LwZU9-iY!Nly7ea zoLk4t!NAbS%fKLsV#zsq#_5huj3U!JCP9vnsz#xrc#9E{2ij$c%!NKA?nMsvzyz+i@=`GDQ@z}ZX&pu=HA6hV%;`{2O_OCAP>T0I5^D-@;M9l>E@ zJ>6j{v^4df$|TJk;RhC$pWZW-Nf_+ZeWktzCQJ+r@0iik%f0}RQ?;hQoXR8&P8k2E zGD$P}2ZP+84LV>(7VHMbHgDrEObiUJYzz#FC~j~M11Bw|>6yK-axpOBkUb*W2ImEhYwr&&=o%6q>@lSvgUPyiArp9s;seI}Cx z*!D^%+4*M~85j(i(d#M3DIldH(|=516a;5Iu=?OQp1D3u3=GQ53=B#rAs{~uqF!t| zqks;2QhgYHPpmu0#J~{3ik|#duK_95f}~WC^Nf`C&b4J?V31>BU@%AV z&dK!Yd4l4r#YLdy`G~Hz`lLAX~d5yu>eqo`$=UN?_P4eYLvTK)?@Yzzz&1Q{6AP!xF{oh~U04W4#?ZqQR~Ak=a9==Tn8yk51b3l_<{48q?!CKf}&Y_`po%E z;$UaiEzWA5#mvB9#){rX`fz#rh51a{;0*W=r1$D|P&J@1-R>GAJGfZ`mI_?JB+XQN z3u^2FCTVc-XOvL?<{Bdd!+d521{oCJYuufFWdV~GSTEy3CTS**`_ttXLK|bgAOWSv z@OWdNK6@dwp4$kLTK{zVxrNXGp4z!X&4!7AL5PKc!34#MiWd+A>=rReaDoyYct`E@ z_(e>j%wn$@rzgB*l$hSXh=~Ur0>~Q-v{B4)dk+c$N%&q{zUf>Op_<}aCY{k_Vqka+ z3OW=`X}_SBFJ_Vg7p=$>CaCq*=Re?rPHcMrVkRN5Tek1rA#2aXz@Wr}UZN$4Oh34o z$qgKATuYdwnOMcAt1n?v1`GIt1l*)RD!|17&-4XLpc!`k5+-S8Hd&_W7w0ocfPBKk zk6glBO8q)*DU&o4qvCYgrA$U(2QS^zb5);_f#Dn@dfWx5F@Z{E+3CGYp~lYvX+Ehw zedkgpd2lkm4H957oNl;^Nq9QXz47#NsX(JS>{Ux+bWE1BfL#%Ql( zl4e>G01@5i5A{hrDB*q&jtqXv!N8!#kKWn}3uZ!UZTVuhwm^l4m)6r`*h|o=nCTx^ zLQBw>E3=O{gYqdmdVDv=gW?gASL0SONi*>!Pp@9ZqySEI^FRXUQX$R;*FkSnnAoR# zErKMCX{$jUg$$51q)E*@5t@@DK{8vjr!s+`~Gbw{h57VWe3VT=? z7@lKv0nJLLGp=DW1PAf$jmJaHm>3xJSkT*&!d26Q)-b7qomsPnNt$Uw4agl@(?8r` zUcjrSA@xOvktQ*Ge~rE z2AeKBNO3xv+FfaUGQt0BS;tc;eMzez4)0_mR~!^kK- z`9Y4{<|{IOVEM^fdeWO6XZ3QLkA|+1@XUP!!1x{_7|&U;pX+OMbh3>1hpbT0;&`o_X_g?fu_- zpYNXg`TYMqKgAmC{`fk`ZrAn;lsEK=ebCnwXLP6DxbN*v*V}vU>t-!eTVPQYXfCE< ze`Bupt*2X*w_akcy|>5a!sO3eFC~ATml(~=G*NN4%hhjl5?}uGs*EaE+mgw7FD`kN zgJ4E!$y$|A)^~5-os7LAwq?u8$jvVc&l|3}*(k9n;P!bdk9?oIMpRoP&PxoP9TG z%j#=2Un@l3JBwf4dMYP!`<{kb4$F4Wd!J?@VK>=Da?+MSy>J`JrhxREd#Z2h?yMF1 zCfDdP_h`#v-4}h@xyRNlTBo3R;n7XY!%xrgm)^hB9-{PTuf>(N<_GoP`0qPeo(#Rs zHIM6E@~3BBC->b7>G6$UqUyN&;^IdJRjj+10+uILx<&f)-|F5Ky&^*R&%y^9mjgF0 zdwZ0#I>WD+Luej9s%hn2-KuRD6v6nDp5TQli2OYMY+ zooqt(zWnYV1%5?J-Tc!MukdBU!TN?%S0C$a`LtBwkKvptqNM`;LTi?(Om+<}j%DrV zKEiYQa(e0Uc<~pj*Z-M2**iTvrC7rq`v%J zU|3@jV1G7)XWrSleTgOk=Qe*@uKjH3gp(Wpw|m~0YB=YhyGn&)!u1z7@3@$?bu#>2 zQ-9#?)2^42&9n8AEW|bJPipXqa~aOz579T!y*;l@yn9#wx(CU39u^)p+B4a7=e-nT z$-~D#a*FylK7O)qSJRqz{Rg`erdVt2H)dbB({g8O{lb}??rv&^wKp$ECvKc&Q@wfC zvxQ#G{zjWT^UoEqTD=lFGG*4kp4V&m`x+viq|~0DH|>~Nsha8W39BE5gl_ltJGlHs z&22}s6$z~K)gD%!Ei7I4W`d&Fk@Sz2qVo?vkNjQtzU>*0OZm5Fg#zo0!_GhI-c-MT zi*x($nbm$rjVtEW&n&TZ+Iq6kKBYM4g=*&1T#HZpyVjrF_)p3CuuX@~=Ik?3+YZ0I z7iwF<6wX@fcF>!NJx}oPp2VVtn%}lcx?BGwe!8o%ulfDTipZjHOYU=)n-1(~)$`mn z%k`kfIYTXz8d3WR!GBHPtzFpFB+qG5xy_+UdYR&6Cgnxyo5L=y*->v(-T7BoXXOvW zx?3xnv);1l_eZX2pU?f}O5ctpX*aL=9Q6t-uifN-P@g4;ciCw^MSkHuYaVIUozyfs z%#wL@XG-O!870r3DhfsQh3L#rouB_P`_D4o@DI`7TJl~!eKqffRaRZUy^G|Z?CpN5 za(Gy^*XRYyMSqlCxv6Q=rm2(d>eueFKBF?b+-Ap{Bb)XlS~!1_xp3F5z1Vk!=pN5x z`+H1#|5rPS{%I|)eXV}-{S1l5yITc=KKMORaQ_mo_k{r?43&vE{+spF%JPCAp)sC!4?Ofyk&8S!@%4-9 z`i$v+sthh~O25t}7kRW(wdBjO=xZNm94PJ4d0e7#B8;=>bcKRQPblZH>4N;Mlf5(U zi}}QIPq*LIQsGg|?C;ykl|7@*TJEIA=?u@*DYKtQYxu5B+;%y_)pFg3iN^K4?p9QOJkd!9K5F4x$f?moEvM;&kfrbWLu zHXZ-KZ_{_$r6Ryh?ERtEoexWd*Ql%#cqkl_7p!^2LkZ)=$ zUWkR1aCe0_)eF25b@JRj9%{dA4n}E%q+#?mPF%9=Iab8{)Be^1(lB`#hO`UwF9QHA6gANi1XGsns4H zMV;q6dIES){^Q+av$ZMw+K0b3uV;n+KKys}kDI(PHxFE0dGCr;ecjf+`=*XU{(Bp* z=RfEVee?e7?58rdww~XfpM1=8ec6deOmc35ho_vBRXGv(EWMar`61u8h2r@S{HM5W zJXOVeL+)YyOqP#TzF~bo6E-?XG@1V1KkG;N-S)We*=uG77ctl8bw1MFcVF#KXwcrq zzW+=C-s~JFYjyWMW@BL3&&$BafT*%Tb@V|CCacZ=%@2U<&B=cG(wpyE<*_h}biAMJ zC?LH#)BZ9uh%;T#gi(5Ol(Rtn&vN1GqW|VCQBdKJJ5ZYAv*I9A%1swTMbFN=DmNMz zxNYjZeq+hf3ao ztSGy5KBDx^1a=0usy z+LqKEnfF_6RC_gkY)tvQtu5{g=Lbio=eehiKCKH3c#*{tckROCXt`xelUcT{QPa(; zKjdj>)3i9rVub*2nTgEj>wTL&cx4uOY--3Z>-={&w9EDGu1RT1zOT6~ml^1sQ{HlW zgY5q~J#Fd}>!&?kF7bFr=FE58T(&3E{-3$f)D~P})u%W|Ezw?ny6~~tMG3)PM}9@x zsGoShu)(YC_o~F4Il8m1M?Uc=iu^YJ_>2X;*&NDx#&WVtH`H9%my(^^`P|z=`-Je4 zTf43W?(u1P6*qUms@u;+<<dc>tU)9SeFSFRwCdru<#uaB$^1SAtwqW_QjSAM?A>SA8Ix|K0dW`wGyJw`O z*JVZr>exPd9eHN0r6whr;DstEtqz5#m_~tMkX}^+(NeR zC%p?}?NE|;XWYfI+`M^imSX*H)>mKKl6M_Ty}mCdcgbbmu(Oj+SA|FYs=0ZJ`=3Um z3U7#~`(Zy3*H72Y&APVl`Tb7t%9m52W#?`Le4fO{T_$~Pqobo(N%(Z>m7UD_qO;jz zePb%-iBCH8;6Ja+rTP>3cV}Oj%m4JpS8x9t=Dmk(r1iV_C!YKhlGb z-IIS9*twaSNKe)1w*1%mNH}M==KoOP;TJ{9^ku z^B-@l9p5ZGV3RN2-8OyBm#Ujnzxjmoa(*=aW8>Emufbz7^StG+(!-jar?*T^@2o#+ zvo8KK^Th)9`gh;sADdq~If=2XbeW~+p52El?=D=Y@4HEkbLS`Fpc$h7`?^&2&i*I& z&U>G{K+d)LjTek+I4mc-?hP@L2ufdUal_8~$Yk-;8rw2%-KY)>QF8ylC+B4M`^P2$ zHx`>y)jJjQ`!0sC&Qju6XtDis_pxsI2kwl0oUykpkFDriC-$!XeOB4~oR{~Sk4NwL zZoa#GYl(e}I@5RK#%lJv_t$>#cR5@x(0M1f!7_mTa$vLMii18Z276l)bMLvStE;C7 z^$O_U>9`)-em(lIb=cwG=5G(l^nR$wl6LlXv0ix~UM!dUd`N*Bi~WNWYWHS;I+_3I zD3{vKjlIR*w<}Ut?)tM&xBkhtf{jf(1(Y8DEib-P5t}G|+FLog;=g@G2FK=_j8M;c zN~R0?U+;~1>1@w8DaPKdbX^PX*sBWaVEY==0FaAzLn+ajoV$?^wR2R~CITe(S5Y zS~%@v-PC*3$7#}=2eFg|JGd8LCN1Gfd4vT4@bOcr=N_21P8cW$R>+PH_7eV?rTW7m~W zvu{4E-Z^)bb(^rMl&xGs-|I=sWLEkV{!fZEa?5V@eh@7;Rk(wFv&6pM_bf}~j1(mG zSKL{*r2g0cZ#O;*&X0^&xwF6Xy}sQ6|KB(K_pf=doonaB>fl3PQ+i)p#H}c_J#(Ao z%DxQiBOB$rpZu`8e|CCC`N_vMx1I-h-)H^9xBvTuV+GUaI3MX|-^{4=hp}Gey~Mwe z$&Z2*jvoB4cr;{3lYRTFRg&rf($A$Dzh7NhWUxT^+rQQyf3>^a->sk5pJe-eQ&8-G zR#5F)9t%2lM}{p9#B(wpHY@HOq1h0=b zuT0T})Xom9jMCG^Co`$m_l8A>3x|vR>r>&8bYs18t0UBV`K%TPuhmHi-#pWhRvwNQ8U)qPjC{%Zeq?P{%>p@-9!HKxUC&ugCFuCA}1 zU;E?t{rmqIE;P$aKH2j0rls8~={XOtn8aV2>v_9q?VQvSYs<42Bxe08Zp*8G_3k+j z@5GEYMS~Pw!CglmZd)fQnPSe2+S0*JD_CCLp zxzDF#L70L@rMM@Ty8p70$^F$oUGvUo)ORcGdTi%#_PLSgRZR_x*07m6^OxzqTlLPM zB<%Lu_f|KPt!zEpwoP%hOEtOFbmqr45e*ByMOo_ht1MLa99Ot$bNnl>VvpiIT^2=1seY&%SUu4b!&x5}d58t%1^4Q_@u%P*QYjXCjwrK_?#Y=e< zK55h^DY{%ZS+LQ?vC}N0(?|VF&AsB*|D99b?GV}}p|_WHiI+!!MY8bW%_{|`E>!-y zjrWN&za8I0qL{B`jTK5l;< zU5V+Q-#N8-rxr~6`D=FK4~|z_egBhFxh@;+nwXZM*LYlaa&TU{=G~Ro)Bc<}*E-># zxr$}{cay^_m4C|Cvz8m^Z`!PItM9zwvYk7x3f|t9!&#nsNBE}2Hb>h>p8|Qd2J<}U zo4?R8yW9HmJj=!1m!~bh{CsBjwQD_7P3~INsfrfpoQ^ou6>vRYz3S{kkt5!lLjr~5 zEwoS_*(R=zl#_>f4mKRUAi6TMwbXh+MwK{Ujm&qRI+0l${YO0!_HAY#XJ2cqoU{15wJJ+*`rp6371Miy z(*?IX&U`L!bj#y$*&E4o|GW6wHvX6&AfMc!rq}&k@{#@p+kMTet#=6ikj>hbI6uy0 zrC8zSj)k^0GwT{t1e0BT%0vw}cmFU`E1S^!oo$o;!ZWSR^$(Aj<+U-p*8G;Z&KF$& zolX1B%pB%i>jZ9g?-Kv-h5FL>5C45W)xr9L%X?O?Cwj7OBL2KQ z<1as`pwx&+EAD4uV0grVTu=&iya$i%ZGMoG4KDm9`{kR}*KpR%PW}6%_=)eV?Vh*4 z_`NTATeaT1f9>023NLr*z23U*_O5qNa({0-drc*G@}^P)7m<7sQIS0kf*%=JrpWpw zXed46?0D3;=uu-=m-xMZ`|p3RoxJqqY_qw4>gU()Qm?%C{`21T&nxen`~P`f%rEFP zhfP@ZQ9(jtUCg~_b0=!npOl%TzUSb%nXL&P^Ww#2rl+ZR@my|9=$JGo?rHVoKTY;e zzMky;%WZ5dI{U$=oCG<&V1CtYbD8J;i#^<4UdAgc_fG28WmA{V%$j4`znvYuWTcut z9yrruBln5zPjB4(d_|SsvnP7@-b>(^P`ZX?^UiXc2ibGn&7@7!1phA6-B5qS=FQws z-V0kRC$#vU4-OJxwOPk?bw@0hAAjZFV21m<&OCkkLZZ3x<6@%|Ij?P%Viiq)Jq>ug z!H8A7GJ$d3lU3n+8jm%$UU=h_VPT^0ZMWmho;t5j%HempCr>sCkesxXvr=xoe^1~f zqi4K7m)z|7I)x+IcynW<*R9pIuNFz3thc|)@gkt5B9-@a@$9TEFB>E0IB}Pnh#mBoiHF{O4OZV)~%Oy8i6+Yi0q7%n67j{>;Y?}LqL04gK!+LkNht*ea+Fdz*W5f5B97X0=SNvREjf*&HR{EZg zoOIguFXxZlFU}a&yOb$b?^g6?OKrKs#d$g4tz)-{io!F;t^E@MV>l9;uG=fhvmf<$ z%A0xY>mI4;w}oE{g~_Y57k+)}5El7#*369)3`>h-0$9_RXg_K6)R=s6mz0DxlZ@6q zp{d!w6=jc07k5oMmccg7DfiOhEJdS_T`99<82OmG+M2vCFJ$AAs^>aY=fN^vMf4k| z&qnqo-7C8ipQR`3tc~%}vQ$}=s#s^FKgqI5kg20q=u>{krf37Vvkz@HtEc@_Jr^Nq{c3#zXXpaxAJ;EGyV(Jr>u7a&fTm5=3BxWTCy}GFWElQuU|oI44!Rw)%Mgdm59>Czv~GcscglrzqwJrr+bb>B+T=xluCmQ?gx5 z7rV^As!wGsHS9Z@M2?glak{s1UG4NH-c{RM@2og?XUUlze-a+Qc_p=XMZpmxDfVQ= z_o~|!HhoWAH0^lmd(k2vi8JSP+EV`~=y>gs(ErbVVy)6oft|cH`Y-;=*ZR+{zq{>0 z__H})A}%+V8lSoCu6a}bZ1nU05BjWJbe||cNmkm~e23FFN2B3vq0WST^IvgY*rT-k zm&~13nLECoVK?r1SACxJwAx2_=XIx|&Wk?pl)o3>P>4-ae5t~`-;Tj=ZP1;!-+%2@ zTyMgBv?ytI_`I1fX3gh6aO?7vE4n))%sRvCtxrAr9wM8%_I2=y$bt_MJAIzWutaDG z@NHOHC(U_`{iL(fPn$}KMG3}1cajwQCnPIbI`3ncJAaq0WsKr^#U=~e1$CbfS0tBf zXnZpjOH!Vx@$GR$xR^=Ex2(Ua9qSdi;?K-uGYCpjj8u^}taHv}2yJP-+IdaEYsE>q zh|>wV^?g~B^R;8Uc8O`*F)VdHEO(YCWIwmrH=dT-|J8=A2aPvqHvSR&r1P`UW1oMW zho_Xn_aBQ3!qtxm9^T*jr{j;rMjL)k-tQu}+Ac2aS2$%M_9^(2am-JqH7&7y@{9Pa zE27_cooL;!u;1lGe4@8{_6D&}*`?piy>4E478mrqj=laI<7?&1^#RM{!^&Q6GTEQ& z6!=?Cwn!khUa8*k#r~#i{b#G4KRpb1P*9TCr$S+Sw7GW-|56jRbLbj)2Hxht`j z>ui%k)7fKsoSVFB&(taZx}ZEqp<3jIZ}gNi6Ot6wrsn-y^&-z>A?u3$vwjo_6|=O2 z80o0A&Y0+Ra@C54q*EF<_ZUrm%2)1{@Y86y+lly@tVNSVf3A+KesqT`|bp<=ofA}o~NchZ16X`SQa23+x(`%=gW@PxTYo6FQ%#P zz8i6L#*5Sm%NnlMJvGQ)+Gl=eUwxqYTalIBdA;{{uQ+9RF<0QfR{dYb{V|D)ZZ`(p zKXC2t-dNEo5!H*=G47Mya@@yuOS$LAu$412>{+JUY*#qTqFbUqQ{*LsEQ^Dv^L!Dh z`C+qJt>z>w=J@$Wa98w_-7n;FTGiFsp8nK+Qh6cRolCZLiqM?7AKSk4=VyI;y>#*4 z`Y#MyxV|WOEZVeDI7Gp}X-4};kAjnPl;))@n;v{aIC^QTri~Wob|u-TxexQ0;AxEQOHgi>r%~Y?wUo=#A?s9kQx>Td|cG-q>gT_l2 zTy;vsL|-l{u1Hv&Inmd-^5mt9!Xo@U>*SuE*-%=)by8OQb+xnU8v`#i@;mQ-_I#=9 z)x^^*>$e#i(D+tkONTWVzM7*=N4= zemOf~;W5?y)d%aXjW_1nG5Ch}&eL0-vft*tZ2p@bCRUaFrTM~)C%o2(2&+)QvTBQ|x z(ADS5;tCskVTsiZLPwt|`lRcr`IxWg5oj;r{Z$RtH}tI0);8a4+Gq`#<74}SSq#B7&q)Osy{rIcj#yoJA1_Lm2RF-d*fsk--c zqsGCSYd+^MoPQ|Cw*GC@oYq-;?QSKUn#B>lYX-x`=P#R;6skCuaI;Q1BB?s}pVHkK zHvaMlQ+~3(FcYeYE6!=CCux@$%`Sb#x-I$DN5gyTi`AsHZgHL2A20Y)SfXC@ zutp32LM7&sIF@JQpaP2E4mByB@ zxfAW0CrKQhw_#v*+NJMybRL=1oQIqrj7$39vA=kWi-;M|T#q$@ie~*|k zab`o|G^U4=+gyG<0Um|+x#BEQ=eSZ zmYX}Da-F()@d9zpo7Ek=SS>7-AAA$=?roj=;M!-^Ft3wsQ$O#nt77jySM@Pa=&vvP zj4gB4Ix2}K-f&G_-ni(&&1LHEE~pF4YTNqbjL%ipmfe33wno;pxXtTmsk{EMF!JvF z%~Bn1^$HpM#Wi+*=G?p*Wzb+TVcO3B2zdiS)aeNYR(#L9OtFk5co+lbKA5V5A} zuU%{WSN0?aYrR}@x^)*r=X;Tx3XdY*1}WIM?-%IT-yqQ-Rm&*~RChrB1W3Ql|* z8yYPX$>Z}z_-0*9j^ylF)2A{QXd3L~67Q>zYda$&bTjctc_BxGqGw8SSJ;Bxd@Iv5 zJM2&Fn{e4@U&DQAE(iOB4~NdF|M6kr3f%8gc==$;2i6Huhl|d$zto*9=5*QcNRrUL zb6O{EJpNq4-OT>+{|ey~H{7dya;_a>x{$Ha(ky@B>xD-SET8b}iiFO#4cZ>OezJ>G ze!JS(Ppe~2hlJEA|Z{fV`Nu{ULgsW$tSQlAinp%U@Ts z?^c|8@4&sCTt&KS-|{Bj?RauZSS^-c=OBMT_5YtY=ywa((vMH+$cRP24N~ zJ*7`neC7@I1HU#L=64j;iGJr2xVBn8X?xP$-MONi61j~hA1Qn7-*GAN!KN=$g*Cqg zPP}{W-GyxTLqVG9`EUI0*s(uL&8&&4-@oJdA-jWiGf&x_v)dX~sZf4bcT@EQ-dDQ| zA|^KE2Yg)f*v4!`k3*`?)a;DW+#nTr(S9a+fnPq=N%X8c=gY6*Rr(G z*62u%s(*7%oO7Ig-l{O%e!=|}tvkc3J!Rj0eR?qcS&yCS_qB^wtmY0__F1VqCG>B@ zHjyR27M+kgy7bVQH%-V{<6_M)=j4>l+;%>ILh# zf3v9_IeydJana1m3Bp~`t#Q+OtIMX^o}71Rs(-R1hv$zuw&C+0ThBW3Dg6BU7Rev) z4olzM6_Tj^Md!ENr=PV`0xEZ1I#k!8`M>bnoVv=WWs6*{+8yqBbm3|h$CvFl&u^Zu zaCQEpTa`DL*BiU%=dO7cpJ4CqvVTF!@uLYI^$|)R3+uS61HX2}A3n0j=wo#0Bh{K| z%xWg*v;D4BDraB#`rpCxyX&1>o&}rR{|2V$Z?+Fqs``6)l7HCy{dry+w7u6E{BQj$ z$}bjoa9(wtj9J`_;9#{T#ka|qp6^4nJXO6H(ul#eintydG!+h>Y6mwf&5`CSKE$r|4R4uRVURlhi>8yW@ zyHguKer)||^giXL#FkB|Kh`NkJj$(UEEc7D;3&-P~L zy&vgvL>@R)9QvfvqVeOgw*vVFfeoFZck^<*-zlD%YQ(PE>zV(5g24|3{e>xCLOE}+ zD4sd(5_d}W$DHO*o2HAUrWJG+9GN+Vef7u7|H57QJKrcWT(CLfHg(nitOrUjcz>nT zXrDZky|Cy|j%?oPJ#|a#ulw(+Tg@FX_qE2$of4&LH9~&{_r*Qwm6@U}6MD6^KS1;0 zmv#SFy9qFXj15?!tmM*REy;M7Cz#(fG8ji99T2!IrnOT+T|yfyq3IQlhgmG0LII^L9W zyV=EWs@QR?;L_FShm>6G6h6%rd?J15gn2@2NU~DK!`)W`Zu*`q5&Hcn{A}w7-Gv1) z??NLbTEA2}oqTdMaAu6!5{_5Gf*|5Q|cCMqi#TGHX-c`A9v6#k-`+Gj0g zd`k15TA{f9$SvuHAesI4H9@fr<}?R#hUs%*R{A+$0SR*HnNI*vz-6WKI!Mx+k#70-;(3xb~<_G zzrN(7Ep>DB7hUrY`1I#L@7X0+#qK>?x8lf?D?MG?R&~imUrEZieza?kOJ|{#?aB3S zbN8{;%Xc0!pR&{6s_(bmdj9tlmml3`;lEERCg#n-1OLURZ`&aGtl5^czPVL4(f#A) z**ZD1DnDM1*2(EQ`Qv4-nAys@s@<)=E9U2I*q{~GJO5s);+&`tmwQj|vFhSw{khqL z{YSN8VaS8ahegHex<8fJ*2kZT_MgjfKL4S-z)9IZ&8O-kBk#O+@m&LMO}W#8sD`-lx3! z&^_fzR{vf~+%n9cwR*z$&Lti9_iy=i;^X?YpU(#cZE4vc)Bk$P3Hb-hH6u6YsB$OU zNPqTfb=B%@VdC%pW3%_BQ&5Ir)dlenfxnl3xV$)!{a$DJ zf>+5K{uoZ&^<%nX$wznTrc=ICp6tG8d!d|1`OAiKt$&*9KZt%+7uzshKAOjo^Yj{{ zpxLE8WkGq*n(jUm+Hp7d`rQrtlV87>x9DvztL)0AtBI5E`0iW$SG4+fS8u(|)jYWp z*_>(ZzsnEWn3m+vyy+2}q_uWq?^?s9(@UT3s9b(JLt8|p{dTI?b2H8L?;X6g_8)mu z^tN2?bxii=LT2NsUAx_CzWJIhJZ~7{w^QRynT5=nvP+w{X)L|0`Ye5BY@WEUq{W=b zdLNq`GH+yF*58Z(jSxeJ5Pm%Vc@-rOCG^JzsWIw(0J^+y@ES2@9^Nl`iKx zmV6~~nf1!djYd*!4<3`3#>w00+fWtFx*E_O0FTH8%(Rxrf;e2k% z>cekdu6dYqJ8!e|D&3neHs8F>8ueJn=a|$h`wJT%6m7ZfV&&#)H^Vvd_Zpj!`I@OS ze{R@({NagnPnVraD7P|yv*gN)iES$bZ%x{3dsk=4nnbhL36`?YzFnNyc4^nfM%%P> ztrL-(`L8{FR`go6#`@LO#QJ&MR}0OwX3RZzt9JUEcRDw%o}XGgSI4{H%C0lbOS79} z-OJa@``j&j+P3S=t%+A;=L(%&&Nt0;)?=Zpvb54QHw#Smr$s-#+FEU6`SrHe%<6Mf z*RPqsx?EDt?fNzUrLwP1JiT(^$%gF}j`E>-;gip3+bX~2%ZYj+qVD#~V)h+fo_ecV zSLs^YOwphJ7MTTVoLjeO&8rhvCM=A3l_lCbi>v*JXnl^ce8yZGi!GsxTu-pG=FP4- zymR3@hmB|F+{-JtAv^cWhKp{$`Ii};%$>ffJ8`f2ZO6)|H$p1Q^8Po9Z7#jwP%Kl^ z7abeAK!0(+<(W&0v#JWbk9yn>h&IsQUS6$UpBua7X~nl?)|uSf7s(ww$KbBNJSko6 zSN!pf^JGPR`%cFu)SmxQb?#g|bDPW?%L}^_HqU;$E~wLw(=UB7(~i<}iiTOw()f2c zGB9N-YuJP&8~0nOY(A^A{noL zKJ@s3gD&;=HXMFgu;j|eq*?E!?;4m*xcz#{x1Bi*&r6qcY3?~5<2)6L0n`dgDE`HvVmKgCOYt^fiHA~fsFC@O^DDz|5&o?nNc=F{d znF+EANlT}kyYyCAx$#lh&g}lPW;2q^c(~P#kH_d8&nw=2xVnD9+3U$XGmqU_XL>~~ z#d3RaaeQ!X^sl<*`CDX^JeM>@e@G1~|1Emhxx-%ii=tjwkn@J+hmAI^Q@DC$y~*tB zRz;2X_vtKO@giSu?TX4}>^~P|w|5)fzO{bv<$Foa z-Fq*~rhf8vHU6~Md&17Uq4f+u_|k6bH1IQJUFfP2N#7mu`Nx%8vDMN&J+g&2bC20( zGp@VZP&G?*PV=?HYZdeBTW>!+k?@&sdG6kj7fH2w4|cQs%v)b(xO4f+q%#jSQq)=I zAAGy7rPZYNDpxI=^;YJ6lez5Da^`1i+}L9MV%_^^dDCYv|D@)g72AFG-AVZ~^#MOO zr7FeqTI!X5UbMxmdi~Xmgy@#A6P`_)89HJimb;3cHZ%B#$Eur~?x$**%-(DJK>f9`ZZV&3 zgS17u?y+lIC#}x%(JH^0b34ZQO2W6GFVf3?_3k`xbTxwE+pbBA_j>KPTXv@WLggCv zzlYZSbWLyn{vzP0VZEpHiJ8exdvn_kJ=K0OgXhhQw|RG-&w1f% z@2#)Q(dMY%#879x_QzejS)1y)RUSF#I!152InT{n*5>@9B9U#rvTa|BTX)2rn|w!h z-?`ea$A58))b=hbY?L*6XLd7oU1Z#z46kr*@5zggn@&$Pz0Dppv$6ckGKRSVmo~~S zI`mIhw`(p}5AV-r)r{qHM6UWxf5I=ecy7)*JL?m+sSZ2WKdCqS>`~>Z{UY?-Oy~c+ zQD-D2mY4mGo4+^t689h8X^QpgpH;|B{pDSn|&^FRCwRj zOx)wNl5KxrqyKZuZ+ovzs^4~0YWL0Epk3s<<->#i-Od>f8SEpMM?v(q({dGYio5v`}{yBs&~ zW_q-`O3$@Z|M-HFv2MJJnGURX{c%t>VgICG?@AUozBl>4R??@{#$raQ85i3$#W^g0 z8*Gny>DGr#yR9Ja*>F6K@%N0{$SZpduNW_R!d`dcVbPh$J72FP7>Dn?(X;;kgR(C- zezvSWw(V@-1*6c+@-vRjiLz_FJ?$^t$wPb?U|HSA$6n#$F_&~oCZ zpMqIMHv;m5dA@GzeD1OAn6qr$RX)`}ElKTTg~DzA12M%Y8AY*t0aFK3~@KN1L^l z+nS{T>OPU(wtZ}yL(hF%;`GO1&g^QLQmsA7vWK=`4}LfMRQ=i;e6j^A19f5HtPo6pVW-qVn$_tsP*S>iA?%6K$MR)D>FL%%A2Y-HkXP=cd=`^8vWm%Mzx`~%xm&hD+LyjYiSF7~cE;Ul^UtLNLTeyEJy=55U`nK$8Y_!|Chihb9Y@O{@Vn-ll{bnIZL zT-^|v>w25{@LBbSKJ&R{T!#|77w_4S8~(iQ*GgsAvy)5BW>+qMd`V{W&h=-H1+hNN z_?Fam;Adgry>lAdIgW2~zkE9OO2&rD@?9_9nVM~09+qX?tZy|(RmgN^!efJ5^=j;Q z{cbO5u54X=q1g4UVeit&vKb5FG=7xzxz(+!~3-7W;XUVIx;=i@|fc3i#Qf3yn<`&<+b905e zd;0M=7iC?Q?OgNAez&MF)fM)=%jT;z{VTQhsL#grp~vh_ZHQb^$mTZJk^jc|Ywz_~ ze{VfIQ{=a0ZrXM8DfL-ZwOv|G-lI88zjG)J7jP*o!&Zy^pqdIlb-aS|KPlZ;IPZJH-52HMGe22f zJePO%+&Y=boza?4_=7dSiRbZ`-}t`n_Vz-Vr_b}sx32VRe1GlFBJsb6wsl7>D~nim zX~DTS;;&asc`mm?JNxJ9nTuVSERXRy{e8lA;r+5juKO3?HJG?9`s3-n4|h!{yRhWb%j~(q zpJt!7thivy{NuLt!g$*~ic-FDJM@|SJ-iLf^jOBRTKmioLP`l@&6 z;fH;lhpk`jw%)n>Rt&3ONS=_F!aSo>yj*ftX(E>j>>nrnd)T-3!(EY|_bj(f-Lz5U z&$~^ffsbF@nz?6-&{F%2vo$vIujGI5?jzgYWaCYz-}ARzxoqsEQ!lqaeqQ*!r-y$l zE!CcLarTeNKf32XTtB5lobU3Y{af7XGdurXlBx7DJeWOG?O)ClUk=eDNA~-By6MQM zW_sVRU#MdHEO6(JnM)0V3k`xd8oWCEs?gXw;fnd$M`?3T6rZU*s~Y^Om}AO~M|n5& zW?s(Q;C{YUe%9rg(M;lXH{#Os>N#V6eAS<8*>Jk2{%=6OkizDYc^j|Kjb*BSXzF

*LZ5YW+_R|1bNoO*lhw>y%rEezh4d`4X4v%J?Urg~Mrk(nMoDf`Qgnz?rGj>PPXGY`5~zeZd${~~McY`GU- zcdaXIo|nBRSp46E&-{_~K#D7A_1fx&Ijcf9#(ie^d8XFNYRkmqB{zQ*&FEdPARX^Ht5^L* z_}3dhx=tONF1&G~>%L{Dk6k~UQzLxyN7|*Fnr@qw$B&tZn(dp{(JS+5ik`H8`_1|a zwwo2t)}`G1!S^#yM!J=MLVAeVJijByHVZCxIewtH%J9SDjz^0e>ld;Ay4-QxwfSER z{}=IHoR3}iwtUQvy>S0kwHk*|anyF6~R%otRkSvq6WLdq%q}KEmGg8(rTzRUri$C@yfLvUc5%Q8|AV}tx4EjN&Ce{mptP31>tKY;v4}1SZ&O)| zFNS5A61z>}>Q6sh)w=HD@fg8ld&CUaUo{ASo&4^i!S{?A*#~}Y-QsuoQ0y(gcMfkg zZxwWz&0Vfrnw}}GT>G{ELSM887roCS!*H;F7pSO6o+iU;J6Wf*TLizRxyx8`6VST+;)5e}J&NJ_D zTF+&?wZ&gYyzh6fCUEDr@sd-V+yn6+G`_i|3Guiu8=dXhD z^A~G>Jl$q+;w?wf@x6vUvMj~2T}fwz6VEu?FEdC}o&93&hKp&lJni|4r!sir{%NOD963%U*>5&Bc0({`Jw0By&v{GB?Vfqw~-E$1Izl0T|cBbQ#ksJmXkOy|q;(+V|=)Bo9sJ=8D!7QTxk zo$+C}SMNsc!qs8o+Os~Imwruu`QEbgZp>NNpPiiXa+!5f>86L@1n-2+TV(CD_Z@O^`shB#B@Nzkf$>RbF>)7oYQ9q1R=HHK$#Tzg;lv>B>zv0;e@?UK21ewRwWF z%Mwrb%%T?VM=N|pG&I&X{`>oN$-F(1We4*Wr4=^sIGMfZ&{E?=^%3b$_ACgt*7s1? zUGu_ehk?eAAE&*fE*ENPB&%%Ow7)h|bVY=0!`3-#FP6_)w0Vuuy~2A7-&+VWuE|+j z&R#XQ+~AL`j_M7ETPlULg2syO>#74E(Z1=XS_f>CW z*8Fnhi0$jcH|y^1_%EO!6T$XSK~J{Jbq9BP`D>*;q5|(C*&fElSV?sk*q@WT;94QA zV6%hg(BU0lK1H-7TUf8_{&2XVpy{O4A=9X8;pG1>Smhg8C$ElV*j-g)tnianzO|n9 z@|oFtyzfmspnA1gx9h!D#tECK2RhAfk^>Wkdv#>YR-WRtY&*;IS@rzmxxZ|T_D_4x z)VZ38`xyK8yV|VV%hG&5s#gd-UDWy`ro?~J&KF%LR@U0=K3*wv%U}KEIP>n6ZIEsYx3%1_t?FQpBVdP zA_pq_?k?EzU?wcVPlj&IX=yEW6(dBL}f=?mKJ*l%BFPdxmch+2G zj?o_^t}G4i656KGd)QY{^^Qp3A>XLv39jo>zi;~O5IOs##_svGY$6+`@@zVPXii}8 zMdk&If+x;4ZdaJQ_-NK^k-&2sjaRg6zG$@JT=5&3b9Mi8stxwduCG!$^=_-+y{xU$ z7FuW98=f8R%(QE|v0uRZbKso6ll0E6SM&V5F;(eT=Z}tmVV4B|UQHFKx0U-i*;DzS z+oKu3!)nghPE9#udve~T4eu`I#V*M-46m71dt0FW`^yz>Cb~`Lx`*bf)W-y}(rGIv$pJ>Gqxq zE{7w(ZLUztUet-wn4e%}>_vzjm$O z@%iWHm*3<+&rH@iDDN_Jua?t>uD`Lt5u(43PvUEM`2K#z68lwi7k_ChzOvsy`fqh+ z-f^W*_XBV66fIk_lDAE!`JvgQ!21Q$xTnl{s+8gQ^8Aie&-!KWGU{ErPWF3pSIS-a zE>k#hzMJF@^F#UTC*7WSKQ1ryTu-;Bvj6T4e;?PsYdiyWlbp0NII+>jI{i`NYm8OA%~);l(~imXb0Tcpmfx1 zYSM1Iqv1jUZ#n|*lr$>MoBrXfcF>(gL3={xKe87J*rVfgQB-+xwQE;&Xjkknk^gfW z9&O_|`c6V}`+ASUcCU@@)0I>?HNLrNd^>vL#(t%vbG42-)^^#{Gag;YarB{tWVtHe zTHC^fuB}s@yZafg?d{z7uKReFkCEitewD>Dy82lk7sMQ0{!%-%rf%o7qDwnOCKnx> zcJjJ#;m=uVYo^GEFkSo^73Vi&Wkq6+_P0uPVJ_pjH)Px&ot-!{<)6*2p01jYTBo7{ zUH>g*=lWr7BE@L`AYk4^p4Igy@=gez`&5}MGj-02wQ*@JUTG~}YFiGknq{<5c3r@Z zlTRGwg65xm!u^LULoej2EVEqSXV>0#!?jCK?l^EbvTmusamTnT&3cl8d`3z#DJ~W# zItnH%EL?DDFV~BCPr~)xzt5`J^=;~lPuJUCe#%xZi9a4Mzpy&Ct^2G?9;?e;zk2(l z_a&+=raic~t;&L}qR+)|-(vY5o1^#F^k?jB|1;&VwS%Rv+SiEc>`7}@rgt}_dp&1d z9{lIm4db(F40Eqkay=5MZXSa<1)c^hPUGc|ngFm$*|K7Fi_dj(1?uT;y zKecTC&KE;X8VP6_c!1B8J_q=K=03N7XJ#(|5ATyZBOh!xS#cxw9?i; znzzo*H=FgdvPk~F*~X3a2Y>MNm>>EfE3v-)lu?Zd-k^!a`)_S z+9-HTJn`;ggMU)T+!Oxr_UumhqubMLu#ZK#@ndR1!{}_*{C)7x;d*A-C z-{4*AM}LF=Ha+!iA1x*RGd*5w@K5yE_X9t;dafV(Vct+Ld2BzkymjIq_L~3tJ^x$Y zM<@Of@5wdzC;jYr!XN&g_C$?8`aRPp{#Mv~>z_Pm>&T0bsU0f}85kC}BX1oM>3F~S z!-B`)T_fO4a+~>=>;vy)2k%$k{CZhC2Y9!fLKTzr<_YWL1wp*Y{~k(D=40lVTp+}` zS?=I#$c8$8Lni6Tnf83s?@nc6-)wW_5!lqtipL>4@<4m}pqe-~e>u5Th*=1-MSlA3 zX-p!UZ{G<88#6gjO=h$I{WV}mZ2tF9j~S$H`o;hzx6P$b1HrtC zE67396BaXCO%_Ibx&6O9qcR6bX!3^z(%T(07|Xdpwt}`VZog{8XvqlTZ5K3QR0Ny2 z-PD|M2_x7SpyPff>o9X}m$PKN3=X|%e;E~~pPS3Xvt7Z4aTPd#zz&*jFpr6EyNEsG zT8LOoFr)PL`;LswJYa*?`7lXuZ}4OE02?wLbPUjR|M^Vp+qnZ7{lH?|V}cpKg1rEW z%8Q z25Zam_qFG2%`Ja^UVp#Nox?MOb;ACXt+PXGFYma<`18u6nANLdvm0*ohn;3Knd0?6 zE^GdlGh5T*QoPD88|c?>D*1XX>r&_(uhk7Ux~r>}UcMdBpYy70*%LO+>-Qt=#J{#Z z{?4mh>(aZ%>?;5FFKtsbx4pf+%~$xge_a-5 zePQdYdrR!(4!^n4v+Q5@6RE3OQ=(Uw?8xydZ92$(w{DJ5K!aPz=fH-=jY0L>rDLud z`R>hnZMr>B-Q?1h-G;js*01|xy7;R`&D!jILF$@1Ax)l=O6x*tFPk-JO#P6SK;8d(Ibq6vn3U$3?3B^NrryDQKMR>32haj_%fT&ZB1CPgPf29Oag7`O$TN|Bbpr zZ{?3aR`Yrvs7w~{IO3niE<9__mYyT8_OY9McoHIBUS9b$ z?!0~G4(Iw^pKUU1 zRVpsC*uHJL^Z9=HpUZvwpB;a*@v;7X)@@skJ>oLvKA>i)!4UR0ME>oI^oIJY=2gGi z7SAvJvWI>1^S(F@hSk3!=On27k}+x9@+awT#Qb}F(>A|7*}SlP^ZV&L?fRz9-SxPz zN^jv*_gatB%wHJwgtr=6PpYk!v#^${@UyAzIgqLT;C|G0{bzp9Znqws=_v8^Lq$>e z1oyudCv5Mqo)gnbUBw?zdvP(>%*j7*f2zNAX47K*@-O@5&Es$87y2N$ymdw7zv;`Z z_ZU4rd*0>yqeXVUA!-X#UfL~5)cwCI)N01g*Z((sD*nFb@RFLnb0@RE`?+D4?34$L z#ozBK9BeL+FJlw^VdygHQsT#)eX&v77vGclcQj!Sui%Dx)-S$?iAXl6?@?(!e(UDl zQ$1fca;wzya6VgZU&s1wUZBX#fF?DjOi`Oh*RH(qn%iH@W|9Ac+b<~N@Rb9H3k!9k z!}*hV0~KN>yt!x|*(~JgZJr)^I^l)+qlR-*kKOEzqTHTFP4~UL$u#}JR)(*uORks| zUyoYts?O0BzE;{Q{RPjt6|R9-d`_>~?t4)-Z_yK1$yF6T^&gcuFKk|4Y4YXki7$&> z9ct41c79$h{_h@hhMcaV!|5-|GKnu&xa&BHaDLkH!qraP@=5td{;#_&8kqFhE*gth zn!HF_v0ByN6SrL@Pbi!`=N=9o?so56^|=V_n*ed zwcUCO<2y*Dr!$RlCRlR&i5ZM0;0kB^|JjUj?4Vj}d%|MI?_f7g2N^f{L5}it|D{aq z+vhK1`~lVla-HS$HA|TUwm)9UcnMsQfh)J|AJ;HGf+%@e!|1qOd;?<~L>5$QZJ)e} z@g>;c?e$w37egdK=L2ka*um%mZa{#J>Y1*o$i%mO!(PTHu+a3v4o2ze8iyJA>vR1t z2Z+?=nP0Q)GT?Ilz`Nv87CZ07{9yYXEk{!JojW67f47uZZgI`BF3T*%$s-ll}7Nh4TBA)2``x#xGamj9d0-hblX>+_%yfJWJCZ zB~gTwxQN5b3I zuGZcAR#vb+`SQFHNrR0h-L5*pE2qk^86Li~HPQG*TwQwG(UWZ+i<0O6@LC?T#4hyu zviQl4-YU+ePK>QuC$B#ZTyV^8&fm%PUUt5xrk`2tVv z+j{j8>#5&<$-iZeNs8@TyzJp+^RA33j8Q#nnoBqNf96{AAgnFou-3Ir6};Osm#6Nw z-r;SNRnGst(|=SCew>W3+!;2+e=8I#_Uv{7JtmD#|2c}Ky56d00 z-V)N&+k8`U#zgk^gs8Gh$}eiyO!&_L%3jCSckr_?F)&E8Ah)80I^J&&JIXj0d`!jk z#3m-`={j?mB(`gwVVnv{mCyt&w|&Y*#x!sO-2V46<0D9e6V#-ft}VjIzg_SKV;Mxl z+!`jQ>2a%=*tcK4#TXA3o0uoPJ>V`Q6IeSa!EP_O&$tJYiS!>cc7ankxY@q_`cuZ$ zU_IcRw0*$~#s&x%oTlwwGfLDyX=cz}J1J`7q+2y6z8gh!uV@8mZRB3)>BVZFHmzW3 z_w2nJb~`RPx5D@zXL8jre~g)Exie)Oct?#GXT6 zZN2!_cCT2(p(x`huat7}^c0t=+Aq=*e)Ak=xpD2=mN^S&M(;dy%xt{{i`0Px2}2&i zWb4;6!wdQre(%eBbuPB;^U22_u4IWkFLV^zQ-4I@W61Q@lfqnXC*B4`SY^F23N|Q&ewEDa~+d> zG_NDnSa$EJ;^L(Fw~x+>yp}4xE+9JVS=$YL?&*(@{C%=`M^}o(dgY@6f44_)8N_%z z`zxEXZ~57j`T}32O+1Qc=LsKrFiVsDisg^eO>e6wu8^3Ot36{uY;Nv7p8%OxE>D7A z2i`f7B9Z?Cex1XQka({-s;yT%ui1{ z@g}E()$eq?=XCwv`$+T_!~ZE|U-s?ck$rz>?+Qhm147ORSbMko{qIx?Q4VBX)57`n z!+zP5Nvx_bGuq!t9uE0rQQrCf+#H3-ZCh;fZcb|dB9~~|V5T3q^f-~w{|GZutE$1LGWs&;BbuV{M`NtZ_X8M_FqjStT8~2=- zQOxPnH|rbJbS%6t5PjP2_=ocqJNxb_@A;+NSardBf8qCX>BT>I9*e9GI&+oU;T%d z{@cD3Px<;~zcQO-x9l(OyT3MWQMU_qx2kTL$#!oh-@3n@FCI^PAm4G-&_F0B;h})n zhQ56cvIh_F$G(%%N#fVCJ1(>~T*Ge3jk55ZoxA_*(X4KOCod>qVBfve{W&JsQ5`lWCC1W|8F|c=Imr zdYiQCX%g>iUvXiPRKJfgTQsZhUcdkAK^MDx&uRWR;kxcs)f#SkZ2QXFAItZ+2YwE8 ziQ=<6;_lnU^Y^sO@0Hv?jq}+^hR^KCMHZ-kI(;H1 zqxAH=_l!#Q5u7z4>4Ni5em(R|&_f|cae_mG%oG8R^c|BNZcUxyAm*ePuvaC-d*{sW*Z(uVUvuAlv;Um>7di|kkL*~ctBdsi==tVw!J%H`R)$QUboU~={0rR^ zu8Vga6Y#R;tLm?iZi@Tt(5x=TIfH#xrjAV41&LjPMf{S?9IO{7yr1B>NXYxHNfNJ| zs?ys#0dw4zMJP80IH%i)^&RIp^Wod&0>1+;Gp5Pp_P)QL@4{0*{oz+>LAmeWl|;U= zCH=iu@HNRu&eX^L(5+eZC237Am6soIvo^Qsi*d~4m3v%JoNIn?OY5H}Ut0PaGIKh= zf0vs0_Ff#H^Gy9K_Z?W6F1G3Yi+{^qwK$MhO*v=f%K{!Rwasb^54+5G)MPZnt0bwm zQR7gP2y@--wy0^_5)K$7U%eV%K`R!!L6E{`FVOYPuYc=Gkw1*F5wKzmlkTCRzNM_WH|nr+BPA zp=GmaW0YB#`^`7KQ9&)8rd!SKpED>{py z36;on&uiMA-JaF;MZT-H&)v(e`QnM|)X90X`uKD&97~YaoUPn;o*sFh^*bEV;UBqt(wqZ}n7#E+g`{0L%TuQ0%mz)|qG^ui^}yDv7)ic|Ja+#{)3(RX^HpmynnL>uKe z|0&GNSR>*lXYx5;5`6G%r*w(NHnGQPvtGa7`s~@&9g&%b7?r1awXK`To&DyW&y#<6VBM_JyP1#ieUO0xLzxLC-3>5 zbo@N|(Qe(3)sa)r-SyZV-?}&2zcP74X z<~MrMo?-jFTwm0tbJA`Zo~gz`+N&qm&ozD_V)LZQ_=7=V$X7{Q-Uh?yNB>l6CarosUb(#W&;1PhQ_J>0?lXUM zdree)y~(n;Pt`Y7TS85pRE)l=@Ew{L$Pur#s-92((EOQS<5y^OvHs#+Wp!s+d%mf? zX>a9~1MWLjKL)QAeK;*Xhey*=+h|HfXY=Rz9Nj@b`vXoDc+G3B-~Ax|gFMR;Z7*dZ z*|s;Mxio#j+t zpX;=c=R50FwmuV!KE(Nln?-a!hp~I&<7*pPyd&#{c8Yf7z2ZO4<~Dy*^l_s(hk}=V z`g_c^x$m;>NgmlE#eOc+IWuE<_bd@ee>q`&m-U)6dFL)U%~{->c5~&qJilPYbLA;L zckdP+^EvxqP21KzNB(OZvRWhmQ#yE)xlKB+evycSQ?a6$e!a3319!+_w{=h7mp&AV z@si#?Ywv2g+Q40R+SIm0Zh3XZ?qViJDQ?(o$w%U)T=JbtnHcFxw)D_#$)t~xF; z-Qu;dwJIXV_x+`-58PhOEDXMt^H23q(2h&2sTHBmc(Yr5owFuw^gqt`s-nO+&iDQy ztFlAAe{!{(=0#1+ym54E{ktxuFAvK2&orqMLHA^@oS#y3Z1wVG`<@pRubg+K zWTpC6uUC<4zC`U1U-~?1L4Y&oU;U-|(V2SZ_13J8uQ+PpW4$uXXVHJwC5#*DdDAZb zxAJCRc9@6ZYnY!z{b*3z$s4cw2-OUhK)$eoj;mAW7* zZRdj{rw=llF-N$qL$KjiKkAF|T{X_YiS)Iead3N*Oel6Kw`+?tS{)3~-mmIZZ zRKM&qjsI}-&3mTKSuzhr=7=r+c=Mpn;)SY{@bkq|XFIm})0zG(&DneP z4TC*jeA|}a^=U^9Y$n#f{kvZE{r~k7mzDmnpL_4ef(oI1ii_)`zt!Zt@IP37>9AF? z#6JCCdEGVs+667?57?O!wc6`!$`1LfbADcA_%QvUy3w!m$K~EEH2L!U$&?>YBZ41Q zN{X^e?=QQypQGN3JHax1b^TehhWgFNgI8bOf4lywR%yqi z$N#5Jx4Zjsdd~6l-4-=7dO6txSN$~bxA%Y+`b`d5-o5JSrK>Y$?+J06Vq95f+AM1QbH3IpwTC%7=e$(f^D#uN zY@$iLUjHZIiqM{L(~O5_r+&0Co7cW%R{a@&?+0g-_f(qgXEnN4CY}HLh?qrxr(Vw9 zx&5xCU;7XJGu~m4er1V{ms+aeo|Y{KSjzO2BMwU(eDPjDZ`;AX+wLy@cQbPqwMKi+ zPy4lI>3OzaTP`l2Yxi!~uizc29NHmkXB=Ou(y(?JB=GY zJH0h@_5Nyo`^AZuO{yZFdPVg3MIFUYd{a63Ey4Unuq!aJlH_J!U{ytKRtt5!hs@9X6JTWDzWEoU7r0kG?JuKVeR)ju^{@M%+u3q< zwr`9uW6SAIW!%QOty6NFup;x+-h&MXKfZIWYRKWeuz|NU>~_z#m-F^7%e^$UZ^>WP z+&34NvI{<-wXXv+tO&gBP3Ms^wR&O^}+I zCF^^nY2wPfIkP*D74X$KtT8^>dGQI$KZ_pwM}hw}dDG|oTGcTvL-wij4v#Li!evhL zIo+b$Cw0zDVKOu|?YV3s!MMrF_V(mCbFL&sCAb7LNA;X#pWu1W#XvAD{ndIWi~4fm zqAeAR8ABFSC`epnoBWVdx6EN~g4WdEiyvN-2wq(}vB)fF*@US_vech0aZ)r3I1XIp$9bFEb8U3YyqV$5j0&}uhT;xVW>T{fzd6R&UyYrTBeHpdn8Z~fXX7ZJ z)XyJ7V%{+?(hYNRm?ixCG}n>|ds9w0vYo68`7y8b8%O3i@xAVnaqPS)kY)5fJo&}$sK8$*r(B-A ze~#M9zRBsvoEv^cJl|O_D*EU;tE*;Cln3|YZRwK@T^xn|^^I2?`MG4Cr>#ix(`Oqz z_uig2GvidWP^-^Gh0P~C#WFdkUQP7uW~untt7)HAnKc>bl4 zDv#n-HC5w&7T9`cmH(Y%Y-x*(9d>#PcIlGbb^h7oR-c zV4i-etyKQu@0$)Ka%X%z61TV|;Zf*`dhODiaYtV?eGIWZxv?*~yymUwuO}Ov;+*4- zyZq3f7T+|H?x3>RIH|OMjiI(>l+wXVhE`K<6hts?3 zbH6gwJ0E2cx}Yxdsjl{qn*#^6@5at#`a8$w+>Jj?sWWHH zS1-&~n0i*-X^&rN{Vvv3PiI)T>nnaJ3Kab${V7`Q>-&Z^J}if$OlE#?bu+Cu5jtR^ z^>IP;evSCzoZ@X&LLKFvapxDDwv7Kf@y|`ie=h%;_AHlpA6vO-)|cPXKdqVn$d|A& z71e%=-??OF%si$4DKY=TpErg2D*C^6{(o%O#^~9dnRTMOt;52$xIC#}!!$*kOK96Y z3nMYk%#RiCBfn(DFh$-?_HH-{esl=j=bvuBp$iIDh8W z3D?j%1E~u>zuC-^;`c@zSsD^EMeN3#2Hy)^PCh<{5v;eqEY!VGt>EMIeCws$Qxa#V zH=Wz^+HA+H#=Laivn57?9rHRhF03qm#k9!B=jayWjR{V{izjovxu9P5sk`aq3a0BX z>QApfDrY9s%d*ikXo0(Wl6k;K0WQh8XLcNynPt)0_IzH}-j+3sM7h2=**n*ZEpp!} z^l@qURkqBop8{UC3-oWYr<`?7OIy$LkuBV1qPN}-={DI7@@_Zw&YpEZPo!E$`Ze3n zs{zSk36t%QCCoV}lM>1;?tVDJL&Rc9|EBJ5GsNlx4@bFeo>+gXb#XzDqn!JR3=i>3 zQWwvC&}X$07W*k|HFJLM&(4YhxyJ#QTW3CTUR;wACC~L}!m)DKX|rD+{$pkuF1&ck za)mPuHw#S<=vA{9U$@%6$B21zk7LjBEfc0Wqze5C5c=CL`S!pap1!#k_f}8Swh&I4 z&MbOpo`C6{8TFfc*4%BWv^c(Cy}zTe`w>$$lilZ^cVur;`1IBMVDZgg&o|1Rnf`WO zzyq<`4`Ejljaqv7t6PF*>aqzwDXU;yT%XuAFY(U8{=E{7KW9jBX?_T*{gArSkzcx| z)$WJav^k4)Lia{pe`#uAFq=nBq++gLW4mYfEFT~3g5~dSm=~nhZAi+TqIg;Y%QO3})18Vn@9v+$c~b4{uX@IPZyNLuhDThN-+AbUu$@E96Y+en`fcl( zEjLA&y%%j+{K8SmhV6dI0rLmZ4jD>XeVz+9MC)r$opJlS#P;{hn!Z2FE`H8$z0rBt z@6<#0H+r4@FZr`i-%*QFJN!z-?b+m_RuQ3A#=mpE+IccBy`;M=Eg)OWG1Vq)I)@@F zm!^`o#H0Kljt=Z=iqfMGE2x%F?q3_bazcI5KNH!1Cw@0v`J67VtaWVH&IpM&7xZRb zHJ`%Oyg%)U$NhkEv#SsFKa{io;r-ySo#|lhMAsYd)<{Tx(*7XwXY#@ajc3pCFEDR0R8S$t_%4UoAF^)9f+aZTIZJ zjsss`Cf2*k>m@CjQIk}w|TbvKX3;T21=CEP^wm9H{X+c(>Lh|H|;j9YG6q8q)F&qFc#W$Jh9 zGpC+Pgf8Nmq}ku$wNNkWc))8>B|&aBo!pR)GtSd@U39Nk{Kmvk{dj4ES#rYqI;H6J z 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 Date: Wed, 21 Jul 2010 11:22:42 +0200 Subject: [PATCH 038/188] closes #342: Added parens to ActorRegistry.shutdownAll. --- akka-core/src/main/scala/actor/ActorRegistry.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/akka-core/src/main/scala/actor/ActorRegistry.scala b/akka-core/src/main/scala/actor/ActorRegistry.scala index 88113a30a0..57b27f08b0 100644 --- a/akka-core/src/main/scala/actor/ActorRegistry.scala +++ b/akka-core/src/main/scala/actor/ActorRegistry.scala @@ -159,7 +159,7 @@ object ActorRegistry extends ListenerManagement { /** * Shuts down and unregisters all actors in the system. */ - def shutdownAll = { + def shutdownAll() { log.info("Shutting down all actors in the system...") foreach(_.stop) actorsByUUID.clear From 22e6be9dee2258c2b3912dbd16365e71f4e67f27 Mon Sep 17 00:00:00 2001 From: Heiko Seeberger Date: Wed, 21 Jul 2010 11:17:43 +0200 Subject: [PATCH 039/188] closes #341: Fixed O-S-G-i example. --- .../src/main/scala/Activator.scala | 24 -------------- .../src/main/scala/Actor.scala | 12 ------- .../src/main/scala/osgiExample.scala | 33 +++++++++++++++++++ project/build/AkkaProject.scala | 12 +++---- 4 files changed, 38 insertions(+), 43 deletions(-) delete mode 100644 akka-samples/akka-sample-osgi/src/main/scala/Activator.scala delete mode 100644 akka-samples/akka-sample-osgi/src/main/scala/Actor.scala create mode 100644 akka-samples/akka-sample-osgi/src/main/scala/osgiExample.scala diff --git a/akka-samples/akka-sample-osgi/src/main/scala/Activator.scala b/akka-samples/akka-sample-osgi/src/main/scala/Activator.scala deleted file mode 100644 index 04c7f165b9..0000000000 --- a/akka-samples/akka-sample-osgi/src/main/scala/Activator.scala +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (C) 2009-2010 Scalable Solutions AB - */ - -package sample.osgi - -import org.osgi.framework.{BundleActivator, BundleContext} - - -class Activator extends BundleActivator { - - def start(context: BundleContext) { - println("Start") - val osgiActor = new OSGiActor - //osgiActor ! "Hello" - Unit - } - - def stop(context: BundleContext) { - println("stop") - } - -} - diff --git a/akka-samples/akka-sample-osgi/src/main/scala/Actor.scala b/akka-samples/akka-sample-osgi/src/main/scala/Actor.scala deleted file mode 100644 index 90bd521d7b..0000000000 --- a/akka-samples/akka-sample-osgi/src/main/scala/Actor.scala +++ /dev/null @@ -1,12 +0,0 @@ -package sample.osgi - -import se.scalablesolutions.akka.actor.Actor - - -class OSGiActor extends Actor { - def receive = { - case msg: String => - println("Got message: " + msg) - } -} - diff --git a/akka-samples/akka-sample-osgi/src/main/scala/osgiExample.scala b/akka-samples/akka-sample-osgi/src/main/scala/osgiExample.scala new file mode 100644 index 0000000000..0cef797c47 --- /dev/null +++ b/akka-samples/akka-sample-osgi/src/main/scala/osgiExample.scala @@ -0,0 +1,33 @@ +/** + * Copyright (C) 2009-2010 Scalable Solutions AB + */ + +package se.scalablesolutions.akka +package sample.osgi + +import actor.{ Actor, ActorRegistry } +import actor.Actor._ + +import org.osgi.framework.{ BundleActivator, BundleContext } + +class Activator extends BundleActivator { + + def start(context: BundleContext) { + println("Starting the OSGi example ...") + val echo = actorOf[EchoActor].start + val answer = (echo !! "OSGi example") + println(answer getOrElse "No answer!") + } + + def stop(context: BundleContext) { + ActorRegistry.shutdownAll() + println("Stopped the OSGi example.") + } +} + +class EchoActor extends Actor { + + override def receive = { + case x => self reply x + } +} diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index b24f477d75..6c770d4e54 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -170,6 +170,8 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val protobuf = "com.google.protobuf" % "protobuf-java" % "2.3.0" % "compile" + lazy val osgi_core = "org.osgi" % "org.osgi.core" % "4.2.0" + lazy val rabbit = "com.rabbitmq" % "amqp-client" % "1.8.1" % "compile" lazy val redis = "com.redis" % "redisclient" % "2.8.0-1.4" % "compile" @@ -646,13 +648,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { } class AkkaSampleOSGiProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with BNDPlugin { - override def bndClasspath = compileClasspath - - val osgi_core = "org.osgi" % "org.osgi.core" % "4.2.0" - - override def bndBundleActivator = Some("sample.osgi.Activator") - override def bndPrivatePackage = Nil - override def bndExportPackage = Seq("sample.osgi.*;version=0.9") + val osgi_core = Dependencies.osgi_core + override lazy val bndBundleActivator = Some("se.scalablesolutions.akka.sample.osgi.Activator") + override lazy val bndExportPackage = Nil // Necessary because of mixing-in AkkaDefaultProject which exports all ...akka.* packages! } class AkkaSamplesParentProject(info: ProjectInfo) extends ParentProject(info) { From 909bdfe58da342d3f465b93591d97e78a8d2d803 Mon Sep 17 00:00:00 2001 From: Martin Krasser Date: Wed, 21 Jul 2010 14:32:07 +0200 Subject: [PATCH 040/188] Closes #333 Allow applications to wait for endpoints being activated --- akka-camel/src/main/scala/CamelService.scala | 19 +++++++++- .../src/main/scala/ConsumerPublisher.scala | 38 +++++++++---------- .../test/scala/CamelServiceFeatureTest.scala | 20 +++++----- .../src/test/scala/RemoteConsumerTest.scala | 4 +- 4 files changed, 49 insertions(+), 32 deletions(-) diff --git a/akka-camel/src/main/scala/CamelService.scala b/akka-camel/src/main/scala/CamelService.scala index 65a6a44fe5..11f2907c4d 100644 --- a/akka-camel/src/main/scala/CamelService.scala +++ b/akka-camel/src/main/scala/CamelService.scala @@ -1,9 +1,10 @@ /** * Copyright (C) 2009-2010 Scalable Solutions AB */ - package se.scalablesolutions.akka.camel +import java.util.concurrent.CountDownLatch + import se.scalablesolutions.akka.actor.Actor._ import se.scalablesolutions.akka.actor.{AspectInitRegistry, ActorRegistry} import se.scalablesolutions.akka.util.{Bootable, Logging} @@ -77,6 +78,22 @@ trait CamelService extends Bootable with Logging { * @see onUnload */ def unload = onUnload + + /** + * Sets an expectation of the number of upcoming endpoint activations and returns + * a {@link CountDownLatch} that can be used to wait for the activations to occur. + * Endpoint activations that occurred in the past are not considered. + */ + def expectEndpointActivationCount(count: Int): CountDownLatch = + (consumerPublisher !! SetExpectedRegistrationCount(count)).as[CountDownLatch].get + + /** + * Sets an expectation of the number of upcoming endpoint de-activations and returns + * a {@link CountDownLatch} that can be used to wait for the de-activations to occur. + * Endpoint de-activations that occurred in the past are not considered. + */ + def expectEndpointDeactivationCount(count: Int): CountDownLatch = + (consumerPublisher !! SetExpectedUnregistrationCount(count)).as[CountDownLatch].get } /** diff --git a/akka-camel/src/main/scala/ConsumerPublisher.scala b/akka-camel/src/main/scala/ConsumerPublisher.scala index 298c70c2b7..e50c625639 100644 --- a/akka-camel/src/main/scala/ConsumerPublisher.scala +++ b/akka-camel/src/main/scala/ConsumerPublisher.scala @@ -65,50 +65,50 @@ private[camel] object ConsumerPublisher extends Logging { * Actor that publishes consumer actors and active object methods at Camel endpoints. * The Camel context used for publishing is CamelContextManager.context. This actor * accepts messages of type - * se.scalablesolutions.akka.camel.service.ConsumerRegistered, - * se.scalablesolutions.akka.camel.service.ConsumerMethodRegistered and - * se.scalablesolutions.akka.camel.service.ConsumerUnregistered. + * se.scalablesolutions.akka.camel.ConsumerRegistered, + * se.scalablesolutions.akka.camel.ConsumerUnregistered. + * se.scalablesolutions.akka.camel.ConsumerMethodRegistered and + * se.scalablesolutions.akka.camel.ConsumerMethodUnregistered. * * @author Martin Krasser */ private[camel] class ConsumerPublisher extends Actor { import ConsumerPublisher._ - @volatile private var latch = new CountDownLatch(0) + @volatile private var registrationLatch = new CountDownLatch(0) + @volatile private var unregistrationLatch = new CountDownLatch(0) - /** - * Adds a route to the actor identified by a Publish message to the global CamelContext. - */ protected def receive = { case r: ConsumerRegistered => { handleConsumerRegistered(r) - latch.countDown // needed for testing only. + registrationLatch.countDown } case u: ConsumerUnregistered => { handleConsumerUnregistered(u) - latch.countDown // needed for testing only. + unregistrationLatch.countDown } case mr: ConsumerMethodRegistered => { handleConsumerMethodRegistered(mr) - latch.countDown // needed for testing only. + registrationLatch.countDown } case mu: ConsumerMethodUnregistered => { handleConsumerMethodUnregistered(mu) - latch.countDown // needed for testing only. + unregistrationLatch.countDown } - case SetExpectedMessageCount(num) => { - // needed for testing only. - latch = new CountDownLatch(num) - self.reply(latch) + case SetExpectedRegistrationCount(num) => { + registrationLatch = new CountDownLatch(num) + self.reply(registrationLatch) + } + case SetExpectedUnregistrationCount(num) => { + unregistrationLatch = new CountDownLatch(num) + self.reply(unregistrationLatch) } case _ => { /* ignore */} } } -/** - * Command message used For testing-purposes only. - */ -private[camel] case class SetExpectedMessageCount(num: Int) +private[camel] case class SetExpectedRegistrationCount(num: Int) +private[camel] case class SetExpectedUnregistrationCount(num: Int) /** * Defines an abstract route to a target which is either an actor or an active object method.. diff --git a/akka-camel/src/test/scala/CamelServiceFeatureTest.scala b/akka-camel/src/test/scala/CamelServiceFeatureTest.scala index df42237a61..09d386c383 100644 --- a/akka-camel/src/test/scala/CamelServiceFeatureTest.scala +++ b/akka-camel/src/test/scala/CamelServiceFeatureTest.scala @@ -27,7 +27,7 @@ class CamelServiceFeatureTest extends FeatureSpec with BeforeAndAfterAll with Gi // count expectations in the next step (needed for testing only). service.consumerPublisher.start // set expectations on publish count - val latch = (service.consumerPublisher !! SetExpectedMessageCount(1)).as[CountDownLatch].get + val latch = service.expectEndpointActivationCount(1) // start the CamelService service.load // await publication of first test consumer @@ -44,7 +44,7 @@ class CamelServiceFeatureTest extends FeatureSpec with BeforeAndAfterAll with Gi scenario("access non-blocking consumer actors via Camel direct-endpoints") { given("two consumer actors registered before and after CamelService startup") - val latch = (service.consumerPublisher !! SetExpectedMessageCount(1)).as[CountDownLatch].get + val latch = service.expectEndpointActivationCount(1) actorOf(new TestConsumer("direct:publish-test-2")).start assert(latch.await(5000, TimeUnit.MILLISECONDS)) @@ -60,7 +60,7 @@ class CamelServiceFeatureTest extends FeatureSpec with BeforeAndAfterAll with Gi scenario("access blocking, non-responding consumer actor via a Camel direct-endpoint") { given("a consumer actor registered after CamelService startup") - val latch = (service.consumerPublisher !! SetExpectedMessageCount(1)).as[CountDownLatch].get + val latch = service.expectEndpointActivationCount(1) actorOf(new TestBlocker("direct:publish-test-3")).start assert(latch.await(5000, TimeUnit.MILLISECONDS)) @@ -84,13 +84,13 @@ class CamelServiceFeatureTest extends FeatureSpec with BeforeAndAfterAll with Gi given("a consumer actor registered after CamelService startup") assert(CamelContextManager.context.hasEndpoint(endpointUri) eq null) - var latch = (service.consumerPublisher !! SetExpectedMessageCount(1)).as[CountDownLatch].get + var latch = service.expectEndpointActivationCount(1) val consumer = actorOf(new TestConsumer(endpointUri)).start assert(latch.await(5000, TimeUnit.MILLISECONDS)) assert(CamelContextManager.context.hasEndpoint(endpointUri) ne null) when("the actor is stopped") - latch = (service.consumerPublisher !! SetExpectedMessageCount(1)).as[CountDownLatch].get + latch = service.expectEndpointDeactivationCount(1) consumer.stop assert(latch.await(5000, TimeUnit.MILLISECONDS)) @@ -121,7 +121,7 @@ class CamelServiceFeatureTest extends FeatureSpec with BeforeAndAfterAll with Gi scenario("access active object methods via Camel direct-endpoints") { given("an active object registered after CamelService startup") - var latch = (service.consumerPublisher !! SetExpectedMessageCount(3)).as[CountDownLatch].get + var latch = service.expectEndpointActivationCount(3) val obj = ActiveObject.newInstance(classOf[PojoBase]) assert(latch.await(5000, TimeUnit.MILLISECONDS)) @@ -136,7 +136,7 @@ class CamelServiceFeatureTest extends FeatureSpec with BeforeAndAfterAll with Gi assert(response3 === "m4base: x y") // cleanup to avoid conflicts with next test (i.e. avoid multiple consumers on direct-endpoints) - latch = (service.consumerPublisher !! SetExpectedMessageCount(3)).as[CountDownLatch].get + latch = service.expectEndpointDeactivationCount(3) ActiveObject.stop(obj) assert(latch.await(5000, TimeUnit.MILLISECONDS)) } @@ -144,15 +144,15 @@ class CamelServiceFeatureTest extends FeatureSpec with BeforeAndAfterAll with Gi feature("Unpublish active object method from the global CamelContext") { - scenario("access to unregistered active object methof via Camel direct-endpoint fails") { + scenario("access to unregistered active object method via Camel direct-endpoint fails") { given("an active object registered after CamelService startup") - var latch = (service.consumerPublisher !! SetExpectedMessageCount(3)).as[CountDownLatch].get + var latch = service.expectEndpointActivationCount(3) val obj = ActiveObject.newInstance(classOf[PojoBase]) assert(latch.await(5000, TimeUnit.MILLISECONDS)) when("the active object is stopped") - latch = (service.consumerPublisher !! SetExpectedMessageCount(3)).as[CountDownLatch].get + latch = service.expectEndpointDeactivationCount(3) ActiveObject.stop(obj) assert(latch.await(5000, TimeUnit.MILLISECONDS)) diff --git a/akka-camel/src/test/scala/RemoteConsumerTest.scala b/akka-camel/src/test/scala/RemoteConsumerTest.scala index 7e3b666590..25c6d6b975 100644 --- a/akka-camel/src/test/scala/RemoteConsumerTest.scala +++ b/akka-camel/src/test/scala/RemoteConsumerTest.scala @@ -45,7 +45,7 @@ class RemoteConsumerTest extends FeatureSpec with BeforeAndAfterAll with GivenWh val consumer = actorOf[RemoteConsumer].start when("remote consumer publication is triggered") - val latch = (service.consumerPublisher !! SetExpectedMessageCount(1)).as[CountDownLatch].get + var latch = service.expectEndpointActivationCount(1) consumer !! "init" assert(latch.await(5000, TimeUnit.MILLISECONDS)) @@ -61,7 +61,7 @@ class RemoteConsumerTest extends FeatureSpec with BeforeAndAfterAll with GivenWh val consumer = ActiveObject.newRemoteInstance(classOf[PojoRemote], host, port) when("remote consumer publication is triggered") - val latch = (service.consumerPublisher !! SetExpectedMessageCount(1)).as[CountDownLatch].get + var latch = service.expectEndpointActivationCount(1) consumer.foo("init") assert(latch.await(5000, TimeUnit.MILLISECONDS)) From a63a2e3d9033eb978de789b650901b669e1ceac2 Mon Sep 17 00:00:00 2001 From: Martin Krasser Date: Wed, 21 Jul 2010 15:37:37 +0200 Subject: [PATCH 041/188] Added example how to use JMS endpoints in standalone applications. --- .../{context-boot.xml => context-jms.xml} | 0 .../src/main/scala/Boot.scala | 2 +- .../main/scala/StandaloneApplication.scala | 45 ++++++++++++++++++- 3 files changed, 44 insertions(+), 3 deletions(-) rename akka-samples/akka-sample-camel/src/main/resources/{context-boot.xml => context-jms.xml} (100%) diff --git a/akka-samples/akka-sample-camel/src/main/resources/context-boot.xml b/akka-samples/akka-sample-camel/src/main/resources/context-jms.xml similarity index 100% rename from akka-samples/akka-sample-camel/src/main/resources/context-boot.xml rename to akka-samples/akka-sample-camel/src/main/resources/context-jms.xml diff --git a/akka-samples/akka-sample-camel/src/main/scala/Boot.scala b/akka-samples/akka-sample-camel/src/main/scala/Boot.scala index b3b428c01a..bcb884d186 100644 --- a/akka-samples/akka-sample-camel/src/main/scala/Boot.scala +++ b/akka-samples/akka-sample-camel/src/main/scala/Boot.scala @@ -35,7 +35,7 @@ class Boot { // ----------------------------------------------------------------------- // Create CamelContext and a Spring-based registry - val context = new ClassPathXmlApplicationContext("/context-boot.xml", getClass) + val context = new ClassPathXmlApplicationContext("/context-jms.xml", getClass) val registry = new ApplicationContextRegistry(context) // Use a custom Camel context and a custom touter builder diff --git a/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala b/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala index 0a7304ba0e..941da479b3 100644 --- a/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala +++ b/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala @@ -5,8 +5,9 @@ import org.apache.camel.builder.RouteBuilder import org.apache.camel.spring.spi.ApplicationContextRegistry import org.springframework.context.support.ClassPathXmlApplicationContext -import se.scalablesolutions.akka.camel.{CamelService, CamelContextManager} -import se.scalablesolutions.akka.actor.{ActorRegistry, ActiveObject} +import se.scalablesolutions.akka.actor.{Actor, ActorRegistry, ActiveObject} +import se.scalablesolutions.akka.camel._ +import se.scalablesolutions.akka.util.Logging /** * @author Martin Krasser @@ -81,3 +82,43 @@ class StandaloneSpringApplicationRoute extends RouteBuilder { from("direct:test3").to("active-object:pojo3?method=foo") } } + +object StandaloneJmsApplication { + def main(args: Array[String]) = { + val context = new ClassPathXmlApplicationContext("/context-jms.xml") + val registry = new ApplicationContextRegistry(context) + + // Init CamelContextManager with custom CamelContext + CamelContextManager.init(new DefaultCamelContext(registry)) + + // Create new instance of CamelService and start it + val service = CamelService.newInstance.load + // Expect two consumer endpoints to be activated + val completion = service.expectEndpointActivationCount(2) + + val jmsUri = "jms:topic:test" + // Wire publisher and consumer using a JMS topic + val jmsSubscriber1 = Actor.actorOf(new Subscriber("jms-subscriber-1", jmsUri)).start + val jmsSubscriber2 = Actor.actorOf(new Subscriber("jms-subscriber-2", jmsUri)).start + val jmsPublisher = Actor.actorOf(new Publisher("jms-publisher", jmsUri)).start + + // wait for the consumer (subscriber) endpoint being activated + completion.await + + // Send 10 messages to via publisher actor + for(i <- 1 to 10) { + jmsPublisher ! ("Akka rocks (%d)" format i) + } + + // Send 10 messages to JMS topic directly + for(i <- 1 to 10) { + CamelContextManager.template.sendBody(jmsUri, "Camel rocks (%d)" format i) + } + + // Graceful shutdown of all endpoints/routes + service.unload + + // Shutdown example actors + ActorRegistry.shutdownAll + } +} From e7cedd0d8347a2bd423f979f17ed127b8fc80789 Mon Sep 17 00:00:00 2001 From: Martin Krasser Date: Wed, 21 Jul 2010 20:06:46 +0200 Subject: [PATCH 042/188] HTTP Producer/Consumer concurrency test (ignored by default) --- .../src/test/scala/HttpConcurrencyTest.scala | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 akka-samples/akka-sample-camel/src/test/scala/HttpConcurrencyTest.scala diff --git a/akka-samples/akka-sample-camel/src/test/scala/HttpConcurrencyTest.scala b/akka-samples/akka-sample-camel/src/test/scala/HttpConcurrencyTest.scala new file mode 100644 index 0000000000..8372304afd --- /dev/null +++ b/akka-samples/akka-sample-camel/src/test/scala/HttpConcurrencyTest.scala @@ -0,0 +1,104 @@ +package sample.camel + +import collection.mutable.Set + +import java.util.concurrent.CountDownLatch + +import org.junit._ + +import se.scalablesolutions.akka.actor.Actor._ +import se.scalablesolutions.akka.actor.{ActorRegistry, ActorRef, Actor} +import se.scalablesolutions.akka.camel.{CamelService, Message, Producer, Consumer} +import se.scalablesolutions.akka.routing.CyclicIterator +import se.scalablesolutions.akka.routing.Routing._ +import org.scalatest.junit.JUnitSuite + +/** + * @author Martin Krasser + */ +@Ignore +class HttpConcurrencyTest extends JUnitSuite { + import HttpConcurrencyTest._ + + @Test def shouldProcessMessagesConcurrently = { + val num = 50 + val latch1 = new CountDownLatch(num) + val latch2 = new CountDownLatch(num) + val latch3 = new CountDownLatch(num) + val client1 = actorOf(new HttpClientActor("client1", latch1)).start + val client2 = actorOf(new HttpClientActor("client2", latch2)).start + val client3 = actorOf(new HttpClientActor("client3", latch3)).start + for (i <- 1 to num) { + client1 ! Message("client1", Map(Message.MessageExchangeId -> i)) + client2 ! Message("client2", Map(Message.MessageExchangeId -> i)) + client3 ! Message("client3", Map(Message.MessageExchangeId -> i)) + } + latch1.await + latch2.await + latch3.await + assert(num == (client1 !! "getCorrelationIdCount").as[Int].get) + assert(num == (client2 !! "getCorrelationIdCount").as[Int].get) + assert(num == (client3 !! "getCorrelationIdCount").as[Int].get) + } +} + +object HttpConcurrencyTest { + var service: CamelService = _ + + @BeforeClass + def beforeClass = { + service = CamelService.newInstance.load + + val workers = for (i <- 1 to 8) yield actorOf[HttpServerWorker].start + val balancer = loadBalancerActor(new CyclicIterator(workers.toList)) + + val completion = service.expectEndpointActivationCount(1) + val server = actorOf(new HttpServerActor(balancer)).start + completion.await + } + + @AfterClass + def afterClass = { + service.unload + ActorRegistry.shutdownAll + } + + class HttpClientActor(label: String, latch: CountDownLatch) extends Actor with Producer { + def endpointUri = "jetty:http://0.0.0.0:8855/echo" + var correlationIds = Set[Any]() + + override protected def receive = { + case "getCorrelationIdCount" => self.reply(correlationIds.size) + case msg => super.receive(msg) + } + + override protected def receiveAfterProduce = { + case msg: Message => { + val corr = msg.headers(Message.MessageExchangeId) + val body = msg.bodyAs[String] + correlationIds += corr + assert(label == body) + latch.countDown + print(".") + } + } + } + + class HttpServerActor(balancer: ActorRef) extends Actor with Consumer { + def endpointUri = "jetty:http://0.0.0.0:8855/echo" + + def receive = { + case msg => balancer forward msg + } + } + + class HttpServerWorker extends Actor { + protected def receive = { + case msg => { + // slow processing + Thread.sleep(100) + self.reply(msg) + } + } + } +} \ No newline at end of file From cc7da99bea97bb9b5308fdac7df21bb691c4a7ba Mon Sep 17 00:00:00 2001 From: Hiram Chirino Date: Wed, 21 Jul 2010 09:44:18 -0400 Subject: [PATCH 043/188] decoupled the mailbox implementation from the actor. The implementation is now controled by dispatcher associated with the actor. --- .../main/scala/component/ActorComponent.scala | 4 +-- akka-core/src/main/scala/actor/ActorRef.scala | 33 +++++++------------ .../ExecutorBasedEventDrivenDispatcher.scala | 33 +++++++++++++++---- ...sedEventDrivenWorkStealingDispatcher.scala | 27 +++++++++++---- .../main/scala/dispatch/MessageHandling.scala | 2 +- ...sedSingleThreadEventDrivenDispatcher.scala | 2 -- ...BasedThreadPoolEventDrivenDispatcher.scala | 2 -- .../dispatch/ThreadBasedDispatcher.scala | 2 -- .../SerializableTypeClassActorSpec.scala | 2 +- 9 files changed, 61 insertions(+), 46 deletions(-) diff --git a/akka-camel/src/main/scala/component/ActorComponent.scala b/akka-camel/src/main/scala/component/ActorComponent.scala index e267fcd077..01e96b6e20 100644 --- a/akka-camel/src/main/scala/component/ActorComponent.scala +++ b/akka-camel/src/main/scala/component/ActorComponent.scala @@ -247,10 +247,10 @@ private[akka] class AsyncCallbackAdapter(exchange: Exchange, callback: AsyncCall def spawnLink[T <: Actor: Manifest]: ActorRef = unsupported def spawnLinkRemote[T <: Actor : Manifest](hostname: String, port: Int): ActorRef = unsupported def shutdownLinkedActors: Unit = unsupported - def mailboxSize: Int = unsupported def supervisor: Option[ActorRef] = unsupported protected[akka] def postMessageToMailboxAndCreateFutureResultWithTimeout[T](message: Any, timeout: Long, senderOption: Option[ActorRef], senderFuture: Option[CompletableFuture[T]]) = unsupported - protected[akka] def mailbox: Deque[MessageInvocation] = unsupported + protected[akka] def mailbox: AnyRef = unsupported + protected[akka] def mailbox_=(msg: AnyRef):AnyRef = unsupported protected[akka] def restart(reason: Throwable, maxNrOfRetries: Int, withinTimeRange: Int): Unit = unsupported protected[akka] def restartLinkedActors(reason: Throwable, maxNrOfRetries: Int, withinTimeRange: Int): Unit = unsupported protected[akka] def handleTrapExit(dead: ActorRef, reason: Throwable): Unit = unsupported diff --git a/akka-core/src/main/scala/actor/ActorRef.scala b/akka-core/src/main/scala/actor/ActorRef.scala index 82f035f311..90c09892ce 100644 --- a/akka-core/src/main/scala/actor/ActorRef.scala +++ b/akka-core/src/main/scala/actor/ActorRef.scala @@ -514,7 +514,7 @@ trait ActorRef extends TransactionManagement { /** * Returns the mailbox size. */ - def mailboxSize: Int + def mailboxSize = dispatcher.mailboxSize(this) /** * Returns the supervisor, if there is one. @@ -542,8 +542,9 @@ trait ActorRef extends TransactionManagement { protected[akka] def supervisor_=(sup: Option[ActorRef]): Unit - protected[akka] def mailbox: Deque[MessageInvocation] - + protected[akka] def mailbox: AnyRef + protected[akka] def mailbox_=(value: AnyRef): AnyRef + protected[akka] def handleTrapExit(dead: ActorRef, reason: Throwable): Unit protected[akka] def restart(reason: Throwable, maxNrOfRetries: Int, withinTimeRange: Int): Unit @@ -599,8 +600,8 @@ sealed class LocalActorRef private[akka]( @volatile private var loader: Option[ClassLoader] = None @volatile private var maxNrOfRetriesCount: Int = 0 @volatile private var restartsWithinTimeRangeTimestamp: Long = 0L - - protected[akka] val _mailbox: Deque[MessageInvocation] = new ConcurrentLinkedDeque[MessageInvocation] + @volatile private var _mailbox: AnyRef = _ + protected[this] val actorInstance = guard.withGuard { new AtomicReference[Actor](newActor) } // Needed to be able to null out the 'val self: ActorRef' member variables to make the Actor @@ -890,17 +891,9 @@ sealed class LocalActorRef private[akka]( /** * Returns the mailbox. */ - def mailbox: Deque[MessageInvocation] = _mailbox + def mailbox: AnyRef = _mailbox - /** - * Returns the mailbox size. - */ - def mailboxSize: Int = _mailbox.size - - /** - * Returns a copy of all the messages, put into a List[MessageInvocation]. - */ - def messagesInMailbox: List[MessageInvocation] = _mailbox.toArray.toList.asInstanceOf[List[MessageInvocation]] + protected[akka] def mailbox_=(value: AnyRef):AnyRef = { _mailbox = value; value } /** * Shuts down and removes all linked actors. @@ -927,10 +920,7 @@ sealed class LocalActorRef private[akka]( createRemoteRequestProtocolBuilder(this, message, true, senderOption).build, None) } else { val invocation = new MessageInvocation(this, message, senderOption, None, transactionSet.get) - if (dispatcher.usesActorMailbox) { - _mailbox.add(invocation) - invocation.send - } else invocation.send + invocation.send } } @@ -951,7 +941,6 @@ sealed class LocalActorRef private[akka]( else new DefaultCompletableFuture[T](timeout) val invocation = new MessageInvocation( this, message, senderOption, Some(future.asInstanceOf[CompletableFuture[Any]]), transactionSet.get) - if (dispatcher.usesActorMailbox) _mailbox.add(invocation) invocation.send future } @@ -1338,10 +1327,10 @@ private[akka] case class RemoteActorRef private[akka] ( def spawnRemote[T <: Actor: Manifest](hostname: String, port: Int): ActorRef = unsupported def spawnLink[T <: Actor: Manifest]: ActorRef = unsupported def spawnLinkRemote[T <: Actor : Manifest](hostname: String, port: Int): ActorRef = unsupported - def mailboxSize: Int = unsupported def supervisor: Option[ActorRef] = unsupported def shutdownLinkedActors: Unit = unsupported - protected[akka] def mailbox: Deque[MessageInvocation] = unsupported + protected[akka] def mailbox: AnyRef = unsupported + protected[akka] def mailbox_=(value: AnyRef):AnyRef = unsupported protected[akka] def handleTrapExit(dead: ActorRef, reason: Throwable): Unit = unsupported protected[akka] def restart(reason: Throwable, maxNrOfRetries: Int, withinTimeRange: Int): Unit = unsupported protected[akka] def restartLinkedActors(reason: Throwable, maxNrOfRetries: Int, withinTimeRange: Int): Unit = unsupported diff --git a/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenDispatcher.scala b/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenDispatcher.scala index 1d34083e0a..89fb90d16e 100644 --- a/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenDispatcher.scala +++ b/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenDispatcher.scala @@ -5,6 +5,7 @@ package se.scalablesolutions.akka.dispatch import se.scalablesolutions.akka.actor.{ActorRef, IllegalActorStateException} +import jsr166x.ConcurrentLinkedDeque /** * Default settings are: @@ -67,15 +68,34 @@ class ExecutorBasedEventDrivenDispatcher(_name: String, throughput: Int = Dispat val name = "akka:event-driven:dispatcher:" + _name init - def dispatch(invocation: MessageInvocation) = dispatch(invocation.receiver) + def dispatch(invocation: MessageInvocation) = { + getMailbox(invocation.receiver).add(invocation) + dispatch(invocation.receiver) + } + + /** + * @return the mailbox associated with the actor + */ + private def getMailbox(receiver: ActorRef) = receiver.mailbox.asInstanceOf[ConcurrentLinkedDeque[MessageInvocation]] + + override def mailboxSize(actorRef: ActorRef) = getMailbox(actorRef).size + + override def register(actorRef: ActorRef) = { + // The actor will need a ConcurrentLinkedDeque based mailbox + if( actorRef.mailbox == null ) { + actorRef.mailbox = new ConcurrentLinkedDeque[MessageInvocation]() + } + super.register(actorRef) + } def dispatch(receiver: ActorRef): Unit = if (active) { + executor.execute(new Runnable() { def run = { var lockAcquiredOnce = false var finishedBeforeMailboxEmpty = false val lock = receiver.dispatcherLock - val mailbox = receiver.mailbox + val mailbox = getMailbox(receiver) // this do-while loop is required to prevent missing new messages between the end of the inner while // loop and releasing the lock do { @@ -102,15 +122,16 @@ class ExecutorBasedEventDrivenDispatcher(_name: String, throughput: Int = Dispat */ def processMailbox(receiver: ActorRef): Boolean = { var processedMessages = 0 - var messageInvocation = receiver.mailbox.poll + val mailbox = getMailbox(receiver) + var messageInvocation = mailbox.poll while (messageInvocation != null) { messageInvocation.invoke processedMessages += 1 // check if we simply continue with other messages, or reached the throughput limit - if (throughput <= 0 || processedMessages < throughput) messageInvocation = receiver.mailbox.poll + if (throughput <= 0 || processedMessages < throughput) messageInvocation = mailbox.poll else { messageInvocation = null - return !receiver.mailbox.isEmpty + return !mailbox.isEmpty } } false @@ -128,8 +149,6 @@ class ExecutorBasedEventDrivenDispatcher(_name: String, throughput: Int = Dispat references.clear } - def usesActorMailbox = true - def ensureNotActive(): Unit = if (active) throw new IllegalActorStateException( "Can't build a new thread pool for a dispatcher that is already up and running") diff --git a/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcher.scala b/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcher.scala index 76138dce35..6f4ec934eb 100644 --- a/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcher.scala +++ b/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcher.scala @@ -7,6 +7,7 @@ package se.scalablesolutions.akka.dispatch import java.util.concurrent.CopyOnWriteArrayList import se.scalablesolutions.akka.actor.{Actor, ActorRef, IllegalActorStateException} +import jsr166x.ConcurrentLinkedDeque /** * An executor based event driven dispatcher which will try to redistribute work from busy actors to idle actors. It is assumed @@ -44,7 +45,16 @@ class ExecutorBasedEventDrivenWorkStealingDispatcher(_name: String) extends Mess val name = "akka:event-driven-work-stealing:dispatcher:" + _name init + + /** + * @return the mailbox associated with the actor + */ + private def getMailbox(receiver: ActorRef) = receiver.mailbox.asInstanceOf[ConcurrentLinkedDeque[MessageInvocation]] + + override def mailboxSize(actorRef: ActorRef) = getMailbox(actorRef).size + def dispatch(invocation: MessageInvocation) = if (active) { + getMailbox(invocation.receiver).add(invocation) executor.execute(new Runnable() { def run = { if (!tryProcessMailbox(invocation.receiver)) { @@ -76,7 +86,7 @@ class ExecutorBasedEventDrivenWorkStealingDispatcher(_name: String) extends Mess lock.unlock } } - } while ((lockAcquiredOnce && !receiver.mailbox.isEmpty)) + } while ((lockAcquiredOnce && !getMailbox(receiver).isEmpty)) return lockAcquiredOnce } @@ -85,10 +95,11 @@ class ExecutorBasedEventDrivenWorkStealingDispatcher(_name: String) extends Mess * Process the messages in the mailbox of the given actor. */ private def processMailbox(receiver: ActorRef) = { - var messageInvocation = receiver.mailbox.poll + val mailbox = getMailbox(receiver) + var messageInvocation = mailbox.poll while (messageInvocation != null) { messageInvocation.invoke - messageInvocation = receiver.mailbox.poll + messageInvocation = mailbox.poll } } @@ -116,7 +127,7 @@ class ExecutorBasedEventDrivenWorkStealingDispatcher(_name: String) extends Mess for (i <- 0 to actors.length) { val index = (i + startIndex) % actors.length val actor = actors(index) - if (actor != receiver && actor.mailbox.isEmpty) return (Some(actor), index) + if (actor != receiver && getMailbox(actor).isEmpty) return (Some(actor), index) } (None, startIndex) // nothing found, reuse same start index next time } @@ -139,7 +150,7 @@ class ExecutorBasedEventDrivenWorkStealingDispatcher(_name: String) extends Mess * Steal a message from the receiver and give it to the thief. */ private def donateMessage(receiver: ActorRef, thief: ActorRef): Boolean = { - val donated = receiver.mailbox.pollLast + val donated = getMailbox(receiver).pollLast if (donated ne null) { if (donated.senderFuture.isDefined) thief.self.postMessageToMailboxAndCreateFutureResultWithTimeout[Any]( donated.message, receiver.timeout, donated.sender, donated.senderFuture) @@ -169,6 +180,10 @@ class ExecutorBasedEventDrivenWorkStealingDispatcher(_name: String) extends Mess override def register(actorRef: ActorRef) = { verifyActorsAreOfSameType(actorRef) + // The actor will need a ConcurrentLinkedDeque based mailbox + if( actorRef.mailbox == null ) { + actorRef.mailbox = new ConcurrentLinkedDeque[MessageInvocation]() + } pooledActors.add(actorRef) super.register(actorRef) } @@ -178,8 +193,6 @@ class ExecutorBasedEventDrivenWorkStealingDispatcher(_name: String) extends Mess super.unregister(actorRef) } - def usesActorMailbox = true - private def verifyActorsAreOfSameType(actorOfId: ActorRef) = { actorType match { case None => actorType = Some(actorOfId.actor.getClass) diff --git a/akka-core/src/main/scala/dispatch/MessageHandling.scala b/akka-core/src/main/scala/dispatch/MessageHandling.scala index a73f2b691b..92926bb253 100644 --- a/akka-core/src/main/scala/dispatch/MessageHandling.scala +++ b/akka-core/src/main/scala/dispatch/MessageHandling.scala @@ -79,7 +79,7 @@ trait MessageDispatcher extends Logging { } def canBeShutDown: Boolean = references.isEmpty def isShutdown: Boolean - def usesActorMailbox : Boolean + def mailboxSize(actorRef: ActorRef):Int = 0 } /** diff --git a/akka-core/src/main/scala/dispatch/ReactorBasedSingleThreadEventDrivenDispatcher.scala b/akka-core/src/main/scala/dispatch/ReactorBasedSingleThreadEventDrivenDispatcher.scala index 8a951a4e72..e6896ef706 100644 --- a/akka-core/src/main/scala/dispatch/ReactorBasedSingleThreadEventDrivenDispatcher.scala +++ b/akka-core/src/main/scala/dispatch/ReactorBasedSingleThreadEventDrivenDispatcher.scala @@ -41,8 +41,6 @@ class ReactorBasedSingleThreadEventDrivenDispatcher(_name: String) def isShutdown = !active - def usesActorMailbox = false - override def toString = "ReactorBasedSingleThreadEventDrivenDispatcher[" + name + "]" class Demultiplexer(private val messageQueue: ReactiveMessageQueue) extends MessageDemultiplexer { diff --git a/akka-core/src/main/scala/dispatch/ReactorBasedThreadPoolEventDrivenDispatcher.scala b/akka-core/src/main/scala/dispatch/ReactorBasedThreadPoolEventDrivenDispatcher.scala index 370426b2fd..530184d4b2 100644 --- a/akka-core/src/main/scala/dispatch/ReactorBasedThreadPoolEventDrivenDispatcher.scala +++ b/akka-core/src/main/scala/dispatch/ReactorBasedThreadPoolEventDrivenDispatcher.scala @@ -139,8 +139,6 @@ class ReactorBasedThreadPoolEventDrivenDispatcher(_name: String) else nrOfBusyMessages < 100 } - def usesActorMailbox = false - def ensureNotActive(): Unit = if (active) throw new IllegalActorStateException( "Can't build a new thread pool for a dispatcher that is already up and running") diff --git a/akka-core/src/main/scala/dispatch/ThreadBasedDispatcher.scala b/akka-core/src/main/scala/dispatch/ThreadBasedDispatcher.scala index 7355012b1f..012c4899d8 100644 --- a/akka-core/src/main/scala/dispatch/ThreadBasedDispatcher.scala +++ b/akka-core/src/main/scala/dispatch/ThreadBasedDispatcher.scala @@ -40,8 +40,6 @@ class ThreadBasedDispatcher(private val actor: ActorRef) extends MessageDispatch def isShutdown = !active - def usesActorMailbox = false - def shutdown = if (active) { log.debug("Shutting down %s", toString) active = false diff --git a/akka-core/src/test/scala/SerializableTypeClassActorSpec.scala b/akka-core/src/test/scala/SerializableTypeClassActorSpec.scala index 2b26c9ad81..c5084c5e30 100644 --- a/akka-core/src/test/scala/SerializableTypeClassActorSpec.scala +++ b/akka-core/src/test/scala/SerializableTypeClassActorSpec.scala @@ -166,7 +166,7 @@ class MyStatelessActor extends Actor { class MyStatelessActorWithMessagesInMailbox extends Actor { def receive = { case "hello" => - println("# messages in mailbox " + self.mailbox.size) + println("# messages in mailbox " + self.mailboxSize) Thread.sleep(500) case "hello-reply" => self.reply("world") } From f4d62224a9f82e45797ef0607f9e8ed65ce07785 Mon Sep 17 00:00:00 2001 From: Hiram Chirino Date: Wed, 21 Jul 2010 11:39:34 -0400 Subject: [PATCH 044/188] adding a HawtDispatch based message dispatcher --- .../HawtDispatchEventDrivenDispatcher.scala | 87 +++++++++++++++++++ ...spatchEventDrivenDispatcherActorSpec.scala | 67 ++++++++++++++ project/build/AkkaProject.scala | 6 ++ 3 files changed, 160 insertions(+) create mode 100644 akka-core/src/main/scala/dispatch/HawtDispatchEventDrivenDispatcher.scala create mode 100644 akka-core/src/test/scala/HawtDispatchEventDrivenDispatcherActorSpec.scala diff --git a/akka-core/src/main/scala/dispatch/HawtDispatchEventDrivenDispatcher.scala b/akka-core/src/main/scala/dispatch/HawtDispatchEventDrivenDispatcher.scala new file mode 100644 index 0000000000..6c0c1686fa --- /dev/null +++ b/akka-core/src/main/scala/dispatch/HawtDispatchEventDrivenDispatcher.scala @@ -0,0 +1,87 @@ +/** + * Copyright (C) 2010, Progress Software Corporation and/or its + * subsidiaries or affiliates. All rights reserved. + * + * 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. + */ +package se.scalablesolutions.akka.dispatch + +import se.scalablesolutions.akka.dispatch.{MessageInvocation, MessageDispatcher} +import se.scalablesolutions.akka.actor.ActorRef +import org.fusesource.hawtdispatch.DispatchQueue +import org.fusesource.hawtdispatch.ScalaDispatch._ +import actors.threadpool.AtomicInteger +import java.util.concurrent.atomic.AtomicBoolean + +/** + *

+ * An HawtDispatch based MessageDispatcher. + *

+ * + * @author Hiram Chirino + */ +class HawtDispatchEventDrivenDispatcher(val name: String) extends MessageDispatcher { + + // a counter used to track if the dispatcher is in use. + private val active = new AtomicBoolean() + private val retained = new AtomicInteger + + def start = { + val rc = active.compareAndSet(false, true) + assert( rc ) + retained.incrementAndGet + } + + def shutdown = { + val rc = active.compareAndSet(true, false) + assert( rc ) + retained.decrementAndGet + } + + def isShutdown = { + retained.get == 0 + } + + def dispatch(invocation: MessageInvocation) = if(active.get) { + retained.incrementAndGet + getMailbox(invocation.receiver) { + try { + invocation.invoke + } finally { + retained.decrementAndGet + } + } + } else { + log.warning("%s is shut down,\n\tignoring the the messages sent to\n\t%s", toString, invocation.receiver) + } + + /** + * @return the mailbox associated with the actor + */ + private def getMailbox(receiver: ActorRef) = receiver.mailbox.asInstanceOf[DispatchQueue] + + // hawtdispatch does not have a way to get queue sizes, getting an accurate + // size can cause extra contention.. is this really needed? + // TODO: figure out if this can be optional in akka + override def mailboxSize(actorRef: ActorRef) = 0 + + override def register(actorRef: ActorRef) = { + if( actorRef.mailbox == null ) { + actorRef.mailbox = createQueue(actorRef.toString) + } + super.register(actorRef) + } + + override def toString = "HawtDispatchEventDrivenDispatcher["+name+"]" + +} \ No newline at end of file diff --git a/akka-core/src/test/scala/HawtDispatchEventDrivenDispatcherActorSpec.scala b/akka-core/src/test/scala/HawtDispatchEventDrivenDispatcherActorSpec.scala new file mode 100644 index 0000000000..fbaa7e8b43 --- /dev/null +++ b/akka-core/src/test/scala/HawtDispatchEventDrivenDispatcherActorSpec.scala @@ -0,0 +1,67 @@ +package se.scalablesolutions.akka.actor + +import java.util.concurrent.{CountDownLatch, TimeUnit} +import org.scalatest.junit.JUnitSuite +import org.junit.Test +import Actor._ +import se.scalablesolutions.akka.dispatch.{HawtDispatchEventDrivenDispatcher, Dispatchers} + +object HawtDispatchEventDrivenDispatcherActorSpec { + class TestActor extends Actor { + self.dispatcher = new HawtDispatchEventDrivenDispatcher(self.uuid) + def receive = { + case "Hello" => + self.reply("World") + case "Failure" => + throw new RuntimeException("Expected exception; to test fault-tolerance") + } + } + + object OneWayTestActor { + val oneWay = new CountDownLatch(1) + } + class OneWayTestActor extends Actor { + self.dispatcher = new HawtDispatchEventDrivenDispatcher(self.uuid) + def receive = { + case "OneWay" => OneWayTestActor.oneWay.countDown + } + } +} +class HawtDispatchEventDrivenDispatcherActorSpec extends JUnitSuite { + import HawtDispatchEventDrivenDispatcherActorSpec._ + + private val unit = TimeUnit.MILLISECONDS + + @Test def shouldSendOneWay = { + val actor = actorOf[OneWayTestActor].start + val result = actor ! "OneWay" + assert(OneWayTestActor.oneWay.await(1, TimeUnit.SECONDS)) + actor.stop + } + + @Test def shouldSendReplySync = { + val actor = actorOf[TestActor].start + val result = (actor !! ("Hello", 10000)).as[String] + assert("World" === result.get) + actor.stop + } + + @Test def shouldSendReplyAsync = { + val actor = actorOf[TestActor].start + val result = actor !! "Hello" + assert("World" === result.get.asInstanceOf[String]) + actor.stop + } + + @Test def shouldSendReceiveException = { + val actor = actorOf[TestActor].start + try { + actor !! "Failure" + fail("Should have thrown an exception") + } catch { + case e => + assert("Expected exception; to test fault-tolerance" === e.getMessage()) + } + actor.stop + } +} diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 6c770d4e54..02f2e18fec 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -44,6 +44,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val AkkaRepo = MavenRepository("Akka Repository", "http://scalablesolutions.se/akka/repository") lazy val CodehausSnapshotRepo = MavenRepository("Codehaus Snapshots", "http://snapshots.repository.codehaus.org") lazy val EmbeddedRepo = MavenRepository("Embedded Repo", (info.projectPath / "embedded-repo").asURL.toString) + lazy val FusesourceSnapshotRepo = MavenRepository("Fusesource Snapshots", "http://repo.fusesource.com/nexus/content/repositories/snapshots") lazy val GuiceyFruitRepo = MavenRepository("GuiceyFruit Repo", "http://guiceyfruit.googlecode.com/svn/repo/releases/") lazy val JBossRepo = MavenRepository("JBoss Repo", "https://repository.jboss.org/nexus/content/groups/public/") lazy val JavaNetRepo = MavenRepository("java.net Repo", "http://download.java.net/maven/2") @@ -62,6 +63,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val atmosphereModuleConfig = ModuleConfiguration("org.atmosphere", SonatypeSnapshotRepo) lazy val grizzlyModuleConfig = ModuleConfiguration("com.sun.grizzly", JavaNetRepo) lazy val guiceyFruitModuleConfig = ModuleConfiguration("org.guiceyfruit", GuiceyFruitRepo) + lazy val hawtdispatchModuleConfig = ModuleConfiguration("org.fusesource.hawtdispatch", FusesourceSnapshotRepo) lazy val jbossModuleConfig = ModuleConfiguration("org.jboss", JBossRepo) lazy val jdmkModuleConfig = ModuleConfiguration("com.sun.jdmk", SunJDMKRepo) lazy val jerseyContrModuleConfig = ModuleConfiguration("com.sun.jersey.contribs", JavaNetRepo) @@ -83,6 +85,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val CAMEL_VERSION = "2.4.0" lazy val CASSANDRA_VERSION = "0.6.1" lazy val DispatchVersion = "0.7.4" + lazy val HAWTDISPATCH_VERSION = "1.0-SNAPSHOT" lazy val JacksonVersion = "1.2.1" lazy val JERSEY_VERSION = "1.2" lazy val LIFT_VERSION = "2.0-scala280-SNAPSHOT" @@ -138,6 +141,8 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val h2_lzf = "voldemort.store.compress" % "h2-lzf" % "1.0" % "compile" + lazy val hawtdispatch = "org.fusesource.hawtdispatch" % "hawtdispatch-scala" % HAWTDISPATCH_VERSION % "compile" + lazy val jackson = "org.codehaus.jackson" % "jackson-mapper-asl" % JacksonVersion % "compile" lazy val jackson_core = "org.codehaus.jackson" % "jackson-core-asl" % JacksonVersion % "compile" lazy val jackson_core_asl = "org.codehaus.jackson" % "jackson-core-asl" % JacksonVersion % "compile" @@ -325,6 +330,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { val dispatch_json = Dependencies.dispatch_json val guicey = Dependencies.guicey val h2_lzf = Dependencies.h2_lzf + val hawtdispatch = Dependencies.hawtdispatch val jackson = Dependencies.jackson val jackson_core = Dependencies.jackson_core val jgroups = Dependencies.jgroups From 9d1b18b7568a56e598d5c0f48c10361b510cff4d Mon Sep 17 00:00:00 2001 From: Hiram Chirino Date: Wed, 21 Jul 2010 15:10:22 -0400 Subject: [PATCH 045/188] fixing HawtDispatchEventDrivenDispatcher so that it has at least one non-daemon thread while it's active --- akka-core/src/main/scala/actor/ActorRef.scala | 3 +- .../ExecutorBasedEventDrivenDispatcher.scala | 6 +- .../HawtDispatchEventDrivenDispatcher.scala | 77 +++++++++++++------ ...spatchEventDrivenDispatcherActorSpec.scala | 4 +- 4 files changed, 61 insertions(+), 29 deletions(-) diff --git a/akka-core/src/main/scala/actor/ActorRef.scala b/akka-core/src/main/scala/actor/ActorRef.scala index 90c09892ce..ccbc1a8675 100644 --- a/akka-core/src/main/scala/actor/ActorRef.scala +++ b/akka-core/src/main/scala/actor/ActorRef.scala @@ -950,7 +950,8 @@ sealed class LocalActorRef private[akka]( * Callback for the dispatcher. This is the ingle entry point to the user Actor implementation. */ protected[akka] def invoke(messageHandle: MessageInvocation): Unit = guard.withGuard { - if (isShutdown) Actor.log.warning("Actor [%s] is shut down,\n\tignoring message [%s]", toString, messageHandle) + if (isShutdown) + Actor.log.warning("Actor [%s] is shut down,\n\tignoring message [%s]", toString, messageHandle) else { currentMessage = Option(messageHandle) try { diff --git a/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenDispatcher.scala b/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenDispatcher.scala index 89fb90d16e..42d1ae1620 100644 --- a/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenDispatcher.scala +++ b/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenDispatcher.scala @@ -112,8 +112,10 @@ class ExecutorBasedEventDrivenDispatcher(_name: String, throughput: Int = Dispat } while ((lockAcquiredOnce && !finishedBeforeMailboxEmpty && !mailbox.isEmpty)) } }) - } else log.warning( - "%s is shut down,\n\tignoring the rest of the messages in the mailbox of\n\t%s", toString, receiver) + } else { + log.warning("%s is shut down,\n\tignoring the rest of the messages in the mailbox of\n\t%s", toString, receiver) + } + /** * Process the messages in the mailbox of the given actor. diff --git a/akka-core/src/main/scala/dispatch/HawtDispatchEventDrivenDispatcher.scala b/akka-core/src/main/scala/dispatch/HawtDispatchEventDrivenDispatcher.scala index 6c0c1686fa..b6e4cbd6cf 100644 --- a/akka-core/src/main/scala/dispatch/HawtDispatchEventDrivenDispatcher.scala +++ b/akka-core/src/main/scala/dispatch/HawtDispatchEventDrivenDispatcher.scala @@ -22,44 +22,73 @@ import org.fusesource.hawtdispatch.DispatchQueue import org.fusesource.hawtdispatch.ScalaDispatch._ import actors.threadpool.AtomicInteger import java.util.concurrent.atomic.AtomicBoolean +import java.util.concurrent.CountDownLatch + +object HawtDispatchEventDrivenDispatcher { + + private val retained = new AtomicInteger() + @volatile private var shutdownLatch: CountDownLatch = _ + + private def retain = { + if( retained.getAndIncrement == 0 ) { + shutdownLatch = new CountDownLatch(1) + new Thread("HawtDispatch Non-Daemon") { + override def run = { + try { + shutdownLatch.await + } catch { + case _ => + } + println("done"); + } + }.start() + } + } + + private def release = { + if( retained.decrementAndGet == 0 ) { + shutdownLatch.countDown + shutdownLatch = null + } + } + +} /** *

- * An HawtDispatch based MessageDispatcher. + * An HawtDispatch based MessageDispatcher. Actors with this dispatcher are executed + * on the HawtDispatch thread pool which is restricted to only executing non blocking + * operations. Therefore, you can only use this dispatcher with actors which are purely + * computational or which use non-blocking IO. + *

+ *

+ * This dispatcher delivers messages to the actors in the order that they + * were producer at the sender. *

* * @author Hiram Chirino */ -class HawtDispatchEventDrivenDispatcher(val name: String) extends MessageDispatcher { - - // a counter used to track if the dispatcher is in use. - private val active = new AtomicBoolean() - private val retained = new AtomicInteger +class HawtDispatchEventDrivenDispatcher(parent:DispatchQueue=globalQueue) extends MessageDispatcher { + private val active = new AtomicBoolean(false) + def start = { - val rc = active.compareAndSet(false, true) - assert( rc ) - retained.incrementAndGet + if( active.compareAndSet(false, true) ) { + HawtDispatchEventDrivenDispatcher.retain + } } def shutdown = { - val rc = active.compareAndSet(true, false) - assert( rc ) - retained.decrementAndGet + if( active.compareAndSet(true, false) ) { + HawtDispatchEventDrivenDispatcher.release + } } - def isShutdown = { - retained.get == 0 - } + def isShutdown = !active.get - def dispatch(invocation: MessageInvocation) = if(active.get) { - retained.incrementAndGet + def dispatch(invocation: MessageInvocation) = if(active.get()) { getMailbox(invocation.receiver) { - try { - invocation.invoke - } finally { - retained.decrementAndGet - } + invocation.invoke } } else { log.warning("%s is shut down,\n\tignoring the the messages sent to\n\t%s", toString, invocation.receiver) @@ -77,11 +106,11 @@ class HawtDispatchEventDrivenDispatcher(val name: String) extends MessageDispatc override def register(actorRef: ActorRef) = { if( actorRef.mailbox == null ) { - actorRef.mailbox = createQueue(actorRef.toString) + actorRef.mailbox = parent.createSerialQueue(actorRef.toString) } super.register(actorRef) } - override def toString = "HawtDispatchEventDrivenDispatcher["+name+"]" + override def toString = "HawtDispatchEventDrivenDispatcher" } \ No newline at end of file diff --git a/akka-core/src/test/scala/HawtDispatchEventDrivenDispatcherActorSpec.scala b/akka-core/src/test/scala/HawtDispatchEventDrivenDispatcherActorSpec.scala index fbaa7e8b43..ce070ab7a7 100644 --- a/akka-core/src/test/scala/HawtDispatchEventDrivenDispatcherActorSpec.scala +++ b/akka-core/src/test/scala/HawtDispatchEventDrivenDispatcherActorSpec.scala @@ -8,7 +8,7 @@ import se.scalablesolutions.akka.dispatch.{HawtDispatchEventDrivenDispatcher, Di object HawtDispatchEventDrivenDispatcherActorSpec { class TestActor extends Actor { - self.dispatcher = new HawtDispatchEventDrivenDispatcher(self.uuid) + self.dispatcher = new HawtDispatchEventDrivenDispatcher() def receive = { case "Hello" => self.reply("World") @@ -21,7 +21,7 @@ object HawtDispatchEventDrivenDispatcherActorSpec { val oneWay = new CountDownLatch(1) } class OneWayTestActor extends Actor { - self.dispatcher = new HawtDispatchEventDrivenDispatcher(self.uuid) + self.dispatcher = new HawtDispatchEventDrivenDispatcher() def receive = { case "OneWay" => OneWayTestActor.oneWay.countDown } From 2ed57141df217e0b47c43743b14421be4f64275a Mon Sep 17 00:00:00 2001 From: Hiram Chirino Date: Wed, 21 Jul 2010 17:23:55 -0400 Subject: [PATCH 046/188] hawtdispatch dispatcher can now optionally use dispatch sources to agregate cross actor invocations --- .../HawtDispatchEventDrivenDispatcher.scala | 51 ++++++++++++++++--- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/akka-core/src/main/scala/dispatch/HawtDispatchEventDrivenDispatcher.scala b/akka-core/src/main/scala/dispatch/HawtDispatchEventDrivenDispatcher.scala index b6e4cbd6cf..316977df22 100644 --- a/akka-core/src/main/scala/dispatch/HawtDispatchEventDrivenDispatcher.scala +++ b/akka-core/src/main/scala/dispatch/HawtDispatchEventDrivenDispatcher.scala @@ -16,7 +16,6 @@ */ package se.scalablesolutions.akka.dispatch -import se.scalablesolutions.akka.dispatch.{MessageInvocation, MessageDispatcher} import se.scalablesolutions.akka.actor.ActorRef import org.fusesource.hawtdispatch.DispatchQueue import org.fusesource.hawtdispatch.ScalaDispatch._ @@ -68,7 +67,7 @@ object HawtDispatchEventDrivenDispatcher { * * @author Hiram Chirino */ -class HawtDispatchEventDrivenDispatcher(parent:DispatchQueue=globalQueue) extends MessageDispatcher { +class HawtDispatchEventDrivenDispatcher(val aggregate:Boolean=true, val parent:DispatchQueue=globalQueue) extends MessageDispatcher { private val active = new AtomicBoolean(false) @@ -87,9 +86,7 @@ class HawtDispatchEventDrivenDispatcher(parent:DispatchQueue=globalQueue) extend def isShutdown = !active.get def dispatch(invocation: MessageInvocation) = if(active.get()) { - getMailbox(invocation.receiver) { - invocation.invoke - } + getMailbox(invocation.receiver).dispatch(invocation) } else { log.warning("%s is shut down,\n\tignoring the the messages sent to\n\t%s", toString, invocation.receiver) } @@ -97,7 +94,7 @@ class HawtDispatchEventDrivenDispatcher(parent:DispatchQueue=globalQueue) extend /** * @return the mailbox associated with the actor */ - private def getMailbox(receiver: ActorRef) = receiver.mailbox.asInstanceOf[DispatchQueue] + private def getMailbox(receiver: ActorRef) = receiver.mailbox.asInstanceOf[HawtDispatchMailbox] // hawtdispatch does not have a way to get queue sizes, getting an accurate // size can cause extra contention.. is this really needed? @@ -106,11 +103,49 @@ class HawtDispatchEventDrivenDispatcher(parent:DispatchQueue=globalQueue) extend override def register(actorRef: ActorRef) = { if( actorRef.mailbox == null ) { - actorRef.mailbox = parent.createSerialQueue(actorRef.toString) + val queue = parent.createSerialQueue(actorRef.toString) + if( aggregate ) { + actorRef.mailbox = new AggregatingHawtDispatchMailbox(queue) + } else { + actorRef.mailbox = new HawtDispatchMailbox(queue) + } } super.register(actorRef) } override def toString = "HawtDispatchEventDrivenDispatcher" -} \ No newline at end of file +} + +class HawtDispatchMailbox(val queue:DispatchQueue) { + def dispatch(invocation: MessageInvocation):Unit = { + queue { + invocation.invoke + } + } +} + +class AggregatingHawtDispatchMailbox(queue:DispatchQueue) extends HawtDispatchMailbox(queue) { + private val source = createSource(new ListEventAggregator[MessageInvocation](), queue) + source.setEventHandler (^{drain_source} ) + source.resume + + private def drain_source = { + source.getData.foreach { invocation => + invocation.invoke + } + } + + override def dispatch(invocation: MessageInvocation):Unit = { + if ( getCurrentQueue == null ) { + // we are being call from a non hawtdispatch thread, can't aggregate + // it's events + super.dispatch(invocation) + } else { + // we are being call from a hawtdispatch thread, use the dispatch source + // so that multiple invocations issues on this thread will aggregate and then once + // the thread runs out of work, they get transferred as a batch to the other thread. + source.merge(invocation) + } + } +} From 74043d3acda3ec48be788ddc36b18e95e9f73238 Mon Sep 17 00:00:00 2001 From: Hiram Chirino Date: Wed, 21 Jul 2010 17:26:33 -0400 Subject: [PATCH 047/188] Simplify the hawt dispatcher class name added a hawt dispatch echo server exampe. --- ...nDispatcher.scala => HawtDispatcher.scala} | 139 +++++++++-- .../test/scala/HawtDispacherEchoServer.scala | 220 ++++++++++++++++++ ...ec.scala => HawtDispatcherActorSpec.scala} | 13 +- 3 files changed, 345 insertions(+), 27 deletions(-) rename akka-core/src/main/scala/dispatch/{HawtDispatchEventDrivenDispatcher.scala => HawtDispatcher.scala} (50%) create mode 100644 akka-core/src/test/scala/HawtDispacherEchoServer.scala rename akka-core/src/test/scala/{HawtDispatchEventDrivenDispatcherActorSpec.scala => HawtDispatcherActorSpec.scala} (79%) diff --git a/akka-core/src/main/scala/dispatch/HawtDispatchEventDrivenDispatcher.scala b/akka-core/src/main/scala/dispatch/HawtDispatcher.scala similarity index 50% rename from akka-core/src/main/scala/dispatch/HawtDispatchEventDrivenDispatcher.scala rename to akka-core/src/main/scala/dispatch/HawtDispatcher.scala index 316977df22..99c4cdd853 100644 --- a/akka-core/src/main/scala/dispatch/HawtDispatchEventDrivenDispatcher.scala +++ b/akka-core/src/main/scala/dispatch/HawtDispatcher.scala @@ -22,13 +22,18 @@ import org.fusesource.hawtdispatch.ScalaDispatch._ import actors.threadpool.AtomicInteger import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.CountDownLatch +import org.fusesource.hawtdispatch.DispatchQueue.QueueType -object HawtDispatchEventDrivenDispatcher { +/** + * Holds helper methods for working with actors that are using + * a HawtDispatcher as it's dispatcher. + */ +object HawtDispatcher { private val retained = new AtomicInteger() @volatile private var shutdownLatch: CountDownLatch = _ - private def retain = { + private def retainNonDaemon = { if( retained.getAndIncrement == 0 ) { shutdownLatch = new CountDownLatch(1) new Thread("HawtDispatch Non-Daemon") { @@ -44,58 +49,150 @@ object HawtDispatchEventDrivenDispatcher { } } - private def release = { + private def releaseNonDaemon = { if( retained.decrementAndGet == 0 ) { shutdownLatch.countDown shutdownLatch = null } } + /** + * @return the mailbox associated with the actor + */ + private def mailbox(actorRef: ActorRef) = { + actorRef.mailbox.asInstanceOf[HawtDispatcherMailbox] + } + + /** + * @return the dispatch queue associated with the actor + */ + def queue(actorRef: ActorRef) = { + mailbox(actorRef).queue + } + + + /** + *

+ * Pins an actor to a random thread queue. Once pinned the actor will always execute + * on the same thread. + *

+ * + *

+ * This method can only succeed if the actor it's dispatcher is set to a HawtDispatcher and it has been started + *

+ * + * @return true if the actor was pinned + */ + def pin(actorRef: ActorRef) = { + actorRef.mailbox match { + case x:HawtDispatcherMailbox=> + x.queue.setTargetQueue( getRandomThreadQueue ) + true + case _ => false + } + } + + /** + *

+ * Unpins the actor so that all threads in the hawt dispatch thread pool + * compete to execute him. + *

+ * + *

+ * This method can only succeed if the actor it's dispatcher is set to a HawtDispatcher and it has been started + *

+ * @return true if the actor was unpinned + */ + def unpin(actorRef: ActorRef) = { + target(actorRef, globalQueue) + } + + + /** + * @return true if the actor was pinned to a thread. + */ + def pinned(actorRef: ActorRef):Boolean = { + actorRef.mailbox match { + case x:HawtDispatcherMailbox=> + x.queue.getTargetQueue.getQueueType == QueueType.THREAD_QUEUE + case _ => false + } + } + + /** + *

+ * Updates the actor's target dispatch queue to the value specified. This allows + * you to do odd things like targeting another serial queue. + *

+ * + *

+ * This method can only succeed if the actor it's dispatcher is set to a HawtDispatcher and it has been started + *

+ * @return true if the actor was unpinned + */ + def target(actorRef: ActorRef, parent:DispatchQueue) = { + actorRef.mailbox match { + case x:HawtDispatcherMailbox=> + x.queue.setTargetQueue( parent ) + true + case _ => false + } + } + } /** *

- * An HawtDispatch based MessageDispatcher. Actors with this dispatcher are executed - * on the HawtDispatch thread pool which is restricted to only executing non blocking - * operations. Therefore, you can only use this dispatcher with actors which are purely - * computational or which use non-blocking IO. + * A HawtDispatch based MessageDispatcher. Actors with this dispatcher are executed + * on the HawtDispatch fixed sized thread pool. The number of of threads will match + * the number of cores available on your system. + * *

*

+ * Actors using this dispatcher are restricted to only executing non blocking + * operations. The actor cannot synchronously call another actor or call 3rd party + * libraries that can block for a long time. You should use non blocking IO APIs + * instead of blocking IO apis to avoid blocking that actor for an extended amount + * of time. + *

+ * + *

* This dispatcher delivers messages to the actors in the order that they * were producer at the sender. *

* + *

+ * HawtDispatch supports processing Non blocking Socket IO in both the reactor + * and proactor styles. For more details, see the HawtDispacherEchoServer.scala + * example. + *

+ * * @author Hiram Chirino */ -class HawtDispatchEventDrivenDispatcher(val aggregate:Boolean=true, val parent:DispatchQueue=globalQueue) extends MessageDispatcher { - +class HawtDispatcher(val aggregate:Boolean=true, val parent:DispatchQueue=globalQueue) extends MessageDispatcher { + import HawtDispatcher._ private val active = new AtomicBoolean(false) def start = { if( active.compareAndSet(false, true) ) { - HawtDispatchEventDrivenDispatcher.retain + retainNonDaemon } } def shutdown = { if( active.compareAndSet(true, false) ) { - HawtDispatchEventDrivenDispatcher.release + releaseNonDaemon } } def isShutdown = !active.get def dispatch(invocation: MessageInvocation) = if(active.get()) { - getMailbox(invocation.receiver).dispatch(invocation) + mailbox(invocation.receiver).dispatch(invocation) } else { log.warning("%s is shut down,\n\tignoring the the messages sent to\n\t%s", toString, invocation.receiver) } - /** - * @return the mailbox associated with the actor - */ - private def getMailbox(receiver: ActorRef) = receiver.mailbox.asInstanceOf[HawtDispatchMailbox] - // hawtdispatch does not have a way to get queue sizes, getting an accurate // size can cause extra contention.. is this really needed? // TODO: figure out if this can be optional in akka @@ -105,9 +202,9 @@ class HawtDispatchEventDrivenDispatcher(val aggregate:Boolean=true, val parent:D if( actorRef.mailbox == null ) { val queue = parent.createSerialQueue(actorRef.toString) if( aggregate ) { - actorRef.mailbox = new AggregatingHawtDispatchMailbox(queue) + actorRef.mailbox = new AggregatingHawtDispatcherMailbox(queue) } else { - actorRef.mailbox = new HawtDispatchMailbox(queue) + actorRef.mailbox = new HawtDispatcherMailbox(queue) } } super.register(actorRef) @@ -117,7 +214,7 @@ class HawtDispatchEventDrivenDispatcher(val aggregate:Boolean=true, val parent:D } -class HawtDispatchMailbox(val queue:DispatchQueue) { +class HawtDispatcherMailbox(val queue:DispatchQueue) { def dispatch(invocation: MessageInvocation):Unit = { queue { invocation.invoke @@ -125,7 +222,7 @@ class HawtDispatchMailbox(val queue:DispatchQueue) { } } -class AggregatingHawtDispatchMailbox(queue:DispatchQueue) extends HawtDispatchMailbox(queue) { +class AggregatingHawtDispatcherMailbox(queue:DispatchQueue) extends HawtDispatcherMailbox(queue) { private val source = createSource(new ListEventAggregator[MessageInvocation](), queue) source.setEventHandler (^{drain_source} ) source.resume diff --git a/akka-core/src/test/scala/HawtDispacherEchoServer.scala b/akka-core/src/test/scala/HawtDispacherEchoServer.scala new file mode 100644 index 0000000000..2b6bd1e449 --- /dev/null +++ b/akka-core/src/test/scala/HawtDispacherEchoServer.scala @@ -0,0 +1,220 @@ +/** + * Copyright (C) 2010, Progress Software Corporation and/or its + * subsidiaries or affiliates. All rights reserved. + * + * 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. + */ +package se.scalablesolutions.akka.actor + +import collection.mutable.ListBuffer +import java.util.concurrent.TimeUnit +import java.net.InetSocketAddress +import java.io.IOException +import java.nio.ByteBuffer +import java.nio.channels.{SocketChannel, SelectionKey, ServerSocketChannel} + +import se.scalablesolutions.akka.actor.Actor._ +import se.scalablesolutions.akka.dispatch.HawtDispatcher +import org.fusesource.hawtdispatch.DispatchSource +import org.fusesource.hawtdispatch.ScalaDispatch._ + +/** + * This is an example of how to crate an Akka actor based TCP echo server using + * the HawtDispatch dispatcher and NIO event sources. + * + */ +object HawtDispacherEchoServer { + + private val hawt = new HawtDispatcher + var port=4444; + var useReactorPattern=true + + def main(args:Array[String]):Unit = run + + def run() = { + val server = actorOf(new Server(port)) + server.start + Scheduler.schedule(server, DisplayStats, 1, 5, TimeUnit.SECONDS) + + println("Press enter to shutdown."); + System.in.read + server ! Shutdown + } + + case object Shutdown + case object DisplayStats + case class SessionClosed(session:ActorRef) + + class Server(val port: Int) extends Actor { + + self.dispatcher = hawt + + var channel:ServerSocketChannel = _ + var accept_source:DispatchSource = _ + var sessions = ListBuffer[ActorRef]() + + override def init = { + channel = ServerSocketChannel.open(); + channel.socket().bind(new InetSocketAddress(port)); + channel.configureBlocking(false); + + // Setup the accept source, it will callback to the handler methods + // via the actor's mailbox so you don't need to worry about + // synchronizing with the local variables + accept_source = createSource(channel, SelectionKey.OP_ACCEPT, HawtDispatcher.queue(self)); + accept_source.setEventHandler(^{ accept }); + accept_source.setDisposer(^{ + channel.close(); + println("Closed port: "+port); + }); + + accept_source.resume + + println("Listening on port: "+port); + } + + + private def accept() = { + var socket = channel.accept(); + while( socket!=null ) { + try { + socket.configureBlocking(false); + val session = actorOf(new Session(self, socket)) + session.start() + sessions += session + } catch { + case e: Exception => + socket.close + } + socket = channel.accept(); + } + } + + def receive = { + case SessionClosed(session) => + sessions = sessions.filterNot( _ == session ) + session.stop + case DisplayStats => + sessions.foreach { session=> + session ! DisplayStats + } + case Shutdown => + sessions.foreach { session=> + session.stop + } + sessions.clear + accept_source.release + self.stop + } + } + + class Session(val server:ActorRef, val channel: SocketChannel) extends Actor { + + self.dispatcher = hawt + + val buffer = ByteBuffer.allocate(1024); + val remote_address = channel.socket.getRemoteSocketAddress.toString + + var read_source:DispatchSource = _ + var write_source:DispatchSource = _ + + var readCounter = 0L + var writeCounter = 0L + var closed = false + + override def init = { + + if(useReactorPattern) { + // Then we will be using the reactor pattern for handling IO: + // Pin this actor to a single thread. The read/write event sources will poll + // a Selector on the pinned thread. Since the IO events are generated on the same + // thread as where the Actor is pinned to, it can avoid a substantial amount + // thread synchronization. Plus your GC will perform better since all the IO + // processing is done on a single thread. + HawtDispatcher.pin(self) + } else { + // Then we will be using sing the proactor pattern for handling IO: + // Then the actor will not be pinned to a specific thread. The read/write + // event sources will poll a Selector and then asynchronously dispatch the + // event's to the actor via the thread pool. + } + + // Setup the sources, they will callback to the handler methods + // via the actor's mailbox so you don't need to worry about + // synchronizing with the local variables + read_source = createSource(channel, SelectionKey.OP_READ, HawtDispatcher.queue(self)); + read_source.setEventHandler(^{ read }) + read_source.setCancelHandler(^{ close }) + + write_source = createSource(channel, SelectionKey.OP_READ, HawtDispatcher.queue(self)); + write_source.setEventHandler(^{ write }) + write_source.setCancelHandler(^{ close }) + + read_source.resume + println("Accepted connection from: "+remote_address); + } + + override def shutdown = { + closed = true + read_source.release + write_source.release + channel.close + } + + private def catchio(func: =>Unit):Unit = { + try { + func + } catch { + case e:IOException => close + } + } + + def read():Unit = catchio { + channel.read(buffer) match { + case -1 => + close // peer disconnected. + case 0 => + case count:Int => + readCounter += count + buffer.flip; + read_source.suspend + write_source.resume + write() + } + } + + def write() = catchio { + writeCounter += channel.write(buffer) + if (buffer.remaining == 0) { + buffer.clear + write_source.suspend + read_source.resume + } + } + + + def close() = { + if( !closed ) { + closed = true + server ! SessionClosed(self) + } + } + + def receive = { + case DisplayStats => + println("connection to %s reads: %,d bytes, writes: %,d".format(remote_address, readCounter, writeCounter)) + } + + } + +} diff --git a/akka-core/src/test/scala/HawtDispatchEventDrivenDispatcherActorSpec.scala b/akka-core/src/test/scala/HawtDispatcherActorSpec.scala similarity index 79% rename from akka-core/src/test/scala/HawtDispatchEventDrivenDispatcherActorSpec.scala rename to akka-core/src/test/scala/HawtDispatcherActorSpec.scala index ce070ab7a7..f6720059fc 100644 --- a/akka-core/src/test/scala/HawtDispatchEventDrivenDispatcherActorSpec.scala +++ b/akka-core/src/test/scala/HawtDispatcherActorSpec.scala @@ -4,11 +4,11 @@ import java.util.concurrent.{CountDownLatch, TimeUnit} import org.scalatest.junit.JUnitSuite import org.junit.Test import Actor._ -import se.scalablesolutions.akka.dispatch.{HawtDispatchEventDrivenDispatcher, Dispatchers} +import se.scalablesolutions.akka.dispatch.{HawtDispatcher, Dispatchers} -object HawtDispatchEventDrivenDispatcherActorSpec { +object HawtDispatcherActorSpec { class TestActor extends Actor { - self.dispatcher = new HawtDispatchEventDrivenDispatcher() + self.dispatcher = new HawtDispatcher() def receive = { case "Hello" => self.reply("World") @@ -21,14 +21,15 @@ object HawtDispatchEventDrivenDispatcherActorSpec { val oneWay = new CountDownLatch(1) } class OneWayTestActor extends Actor { - self.dispatcher = new HawtDispatchEventDrivenDispatcher() + self.dispatcher = new HawtDispatcher() def receive = { case "OneWay" => OneWayTestActor.oneWay.countDown } } } -class HawtDispatchEventDrivenDispatcherActorSpec extends JUnitSuite { - import HawtDispatchEventDrivenDispatcherActorSpec._ + +class HawtDispatcherActorSpec extends JUnitSuite { + import HawtDispatcherActorSpec._ private val unit = TimeUnit.MILLISECONDS From c668615777aa2fb92c2d185638e1e8bbc163de1c Mon Sep 17 00:00:00 2001 From: Debasish Ghosh Date: Thu, 22 Jul 2010 16:57:19 +0530 Subject: [PATCH 048/188] MongoDB based persistent Maps now use Mongo updates. Also upgraded mongo-java driver to 2.0 --- .../src/main/scala/MongoStorageBackend.scala | 6 ++---- project/build/AkkaProject.scala | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/akka-persistence/akka-persistence-mongo/src/main/scala/MongoStorageBackend.scala b/akka-persistence/akka-persistence-mongo/src/main/scala/MongoStorageBackend.scala index d5581b373b..950165567d 100644 --- a/akka-persistence/akka-persistence-mongo/src/main/scala/MongoStorageBackend.scala +++ b/akka-persistence/akka-persistence-mongo/src/main/scala/MongoStorageBackend.scala @@ -78,10 +78,8 @@ private[akka] object MongoStorageBackend extends val o = dbo.get(VALUE).asInstanceOf[Map[AnyRef, AnyRef]] o.putAll(m) - // remove existing reference - removeMapStorageFor(name) - // and insert - coll.insert(new BasicDBObject().append(KEY, name).append(VALUE, o)) + val newdbo = new BasicDBObject().append(KEY, name).append(VALUE, o) + coll.update(new BasicDBObject().append(KEY, name), newdbo, true, false) } } } diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 6c770d4e54..4507193de9 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -162,7 +162,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val log4j = "log4j" % "log4j" % "1.2.15" % "compile" - lazy val mongo = "org.mongodb" % "mongo-java-driver" % "1.4" % "compile" + lazy val mongo = "org.mongodb" % "mongo-java-driver" % "2.0" % "compile" lazy val multiverse = "org.multiverse" % "multiverse-alpha" % MULTIVERSE_VERSION % "compile" intransitive From c0ae02ca07126e9a8418a84b459bbe75c9d2cf65 Mon Sep 17 00:00:00 2001 From: momania Date: Thu, 22 Jul 2010 18:20:53 +0200 Subject: [PATCH 049/188] WIP --- akka-core/src/test/scala/ScalazSpec.scala | 66 +++++++++++++++++++++++ project/build/AkkaProject.scala | 58 +++++++++++--------- 2 files changed, 100 insertions(+), 24 deletions(-) create mode 100644 akka-core/src/test/scala/ScalazSpec.scala diff --git a/akka-core/src/test/scala/ScalazSpec.scala b/akka-core/src/test/scala/ScalazSpec.scala new file mode 100644 index 0000000000..123f213f10 --- /dev/null +++ b/akka-core/src/test/scala/ScalazSpec.scala @@ -0,0 +1,66 @@ +package se.scalablesolutions.akka.actor + +import org.scalatest.junit.JUnitSuite +import org.junit.Test + +import Actor._ +import org.multiverse.api.latches.StandardLatch +import scalaz._ +import concurrent.{Strategy, Promise} +import java.lang.String +import Scalaz._ +import se.scalablesolutions.akka.config.ScalaConfig.{LifeCycle, Permanent} +import se.scalablesolutions.akka.dispatch.{Future, FutureTimeoutException} +import java.util.concurrent.{Executors, TimeUnit} + +class ScalazSpec extends JUnitSuite { + val actorRef = actorOf(new Actor { + protected def receive = { + case "one" => self.reply(1) + case "error" => TimeUnit.SECONDS.sleep(10) + } + }).start + + @Test def callActorAndGetValidation = { + + implicit val executorService = Executors.newFixedThreadPool(2) + import Strategy.Executor + + val promiseError: Promise[ValidationNEL[String, Option[Int]]] = promise(callActor("error")) + val promiseOne: Promise[ValidationNEL[String, Option[Int]]] = promise(callActor("error")) + + //[X]Promise[X] <-- Applicative / Monad + //[X]Option[X] <-- Applicative / Monad + //[X]Validation[String, X] <-- Applicative / Monad iff Semigroup[String] + //[X]Promise[Option[X]] <-- Applicative + + val pvi: Promise[ValidationNEL[String, Option[Int]]] = (promiseError |@| promiseOne) { + (v1, v2) => + (v1 |@| v2) { + (o1, o2) => + (o1 |@| o2) { _ + _} + } + } + + println(pvi.get) + + val listOptionInt: List[Option[Int]] = List.fill(5)(1.some) + // val listOptionInt = (listOptionInt.comp) map (_ * 2) + + println(listOptionInt.sequence[Option, Int]) + + } + + def callActor(msg: String): ValidationNEL[String, Option[Int]] = { + try { + val future: Future[Int] = (actorRef !!! msg) + future.await + future.exception match { + case Some((_, t)) => t.getMessage.failNel + case None => future.result.successNel + } + } catch { + case e: FutureTimeoutException => e.getMessage.failNel + } + } +} \ No newline at end of file diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 89685dffd6..ede37d51fd 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -38,16 +38,22 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // All repositories *must* go here! See ModuleConigurations below. // ------------------------------------------------------------------------------------------------------------------- - object Repositories { - lazy val AkkaRepo = MavenRepository("Akka Repository", "http://scalablesolutions.se/akka/repository") - lazy val CodehausSnapshotRepo = MavenRepository("Codehaus Snapshots", "http://snapshots.repository.codehaus.org") +// object Repositories { +// lazy val AkkaRepo = MavenRepository("Akka Repository", "http://scalablesolutions.se/akka/repository") +// lazy val CodehausSnapshotRepo = MavenRepository("Codehaus Snapshots", "http://snapshots.repository.codehaus.org") lazy val EmbeddedRepo = MavenRepository("Embedded Repo", (info.projectPath / "embedded-repo").asURL.toString) - lazy val GuiceyFruitRepo = MavenRepository("GuiceyFruit Repo", "http://guiceyfruit.googlecode.com/svn/repo/releases/") - lazy val JBossRepo = MavenRepository("JBoss Repo", "https://repository.jboss.org/nexus/content/groups/public/") - lazy val JavaNetRepo = MavenRepository("java.net Repo", "http://download.java.net/maven/2") - lazy val SonatypeSnapshotRepo = MavenRepository("Sonatype OSS Repo", "http://oss.sonatype.org/content/repositories/releases") - lazy val SunJDMKRepo = MavenRepository("Sun JDMK Repo", "http://wp5.e-taxonomy.eu/cdmlib/mavenrepo") - } +// lazy val GuiceyFruitRepo = MavenRepository("GuiceyFruit Repo", "http://guiceyfruit.googlecode.com/svn/repo/releases/") +// lazy val JBossRepo = MavenRepository("JBoss Repo", "https://repository.jboss.org/nexus/content/groups/public/") +// lazy val JavaNetRepo = MavenRepository("java.net Repo", "http://download.java.net/maven/2") +// lazy val SonatypeSnapshotRepo = MavenRepository("Sonatype OSS Repo", "http://oss.sonatype.org/content/repositories/releases") +// lazy val SunJDMKRepo = MavenRepository("Sun JDMK Repo", "http://wp5.e-taxonomy.eu/cdmlib/mavenrepo") +// lazy val ScalazRepo = MavenRepository("Scalaz Repo", "http://scala-tools.org/repo-releases") +// } + + val mavenLocal = "Local Maven Repository" at "file:/e:/maven-repository" + + val efgfpNexusReleasesRepository = "Nexus Releases" at "http://nexus/nexus/content/groups/public" + val efgfpNexusSnaphotsRepository = "Nexus Snapshots" at "http://nexus/nexus/content/groups/public-snapshots" // ------------------------------------------------------------------------------------------------------------------- // ModuleConfigurations @@ -55,21 +61,22 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // must be resolved from a ModuleConfiguration. This will result in a significant acceleration of the update action. // Therefore, if repositories are defined, this must happen as def, not as val. // ------------------------------------------------------------------------------------------------------------------- - import Repositories._ - lazy val atmosphereModuleConfig = ModuleConfiguration("org.atmosphere", SonatypeSnapshotRepo) - lazy val grizzlyModuleConfig = ModuleConfiguration("com.sun.grizzly", JavaNetRepo) - lazy val guiceyFruitModuleConfig = ModuleConfiguration("org.guiceyfruit", GuiceyFruitRepo) - lazy val jbossModuleConfig = ModuleConfiguration("org.jboss", JBossRepo) - lazy val jdmkModuleConfig = ModuleConfiguration("com.sun.jdmk", SunJDMKRepo) - lazy val jerseyContrModuleConfig = ModuleConfiguration("com.sun.jersey.contribs", JavaNetRepo) - lazy val jerseyModuleConfig = ModuleConfiguration("com.sun.jersey", JavaNetRepo) - lazy val jgroupsModuleConfig = ModuleConfiguration("jgroups", JBossRepo) - lazy val jmsModuleConfig = ModuleConfiguration("javax.jms", SunJDMKRepo) - lazy val jmxModuleConfig = ModuleConfiguration("com.sun.jmx", SunJDMKRepo) - lazy val liftModuleConfig = ModuleConfiguration("net.liftweb", ScalaToolsSnapshots) - lazy val multiverseModuleConfig = ModuleConfiguration("org.multiverse", CodehausSnapshotRepo) - lazy val nettyModuleConfig = ModuleConfiguration("org.jboss.netty", JBossRepo) - lazy val scalaTestModuleConfig = ModuleConfiguration("org.scalatest", ScalaToolsSnapshots) +// import Repositories._ +// lazy val atmosphereModuleConfig = ModuleConfiguration("org.atmosphere", SonatypeSnapshotRepo) +// lazy val grizzlyModuleConfig = ModuleConfiguration("com.sun.grizzly", JavaNetRepo) +// lazy val guiceyFruitModuleConfig = ModuleConfiguration("org.guiceyfruit", GuiceyFruitRepo) +// lazy val jbossModuleConfig = ModuleConfiguration("org.jboss", JBossRepo) +// lazy val jdmkModuleConfig = ModuleConfiguration("com.sun.jdmk", SunJDMKRepo) +// lazy val jerseyContrModuleConfig = ModuleConfiguration("com.sun.jersey.contribs", JavaNetRepo) +// lazy val jerseyModuleConfig = ModuleConfiguration("com.sun.jersey", JavaNetRepo) +// lazy val jgroupsModuleConfig = ModuleConfiguration("jgroups", JBossRepo) +// lazy val jmsModuleConfig = ModuleConfiguration("javax.jms", SunJDMKRepo) +// lazy val jmxModuleConfig = ModuleConfiguration("com.sun.jmx", SunJDMKRepo) +// lazy val liftModuleConfig = ModuleConfiguration("net.liftweb", ScalaToolsSnapshots) +// lazy val multiverseModuleConfig = ModuleConfiguration("org.multiverse", CodehausSnapshotRepo) +// lazy val nettyModuleConfig = ModuleConfiguration("org.jboss.netty", JBossRepo) +// lazy val scalazModuleConfig = ModuleConfiguration("scalaz", ScalazRepo) +// lazy val scalaTestModuleConfig = ModuleConfiguration("org.scalatest", ScalaToolsSnapshots) lazy val embeddedRepo = EmbeddedRepo // This is the only exception, because the embedded repo is fast! // ------------------------------------------------------------------------------------------------------------------- @@ -171,6 +178,8 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val sbinary = "sbinary" % "sbinary" % "2.8.0-0.3.1" % "compile" + lazy val scalaz = "com.googlecode.scalaz" % "scalaz-core_2.8.0" % "5.0" % "compile" + lazy val servlet = "javax.servlet" % "servlet-api" % "2.5" % "compile" lazy val sjson = "sjson.json" % "sjson" % "0.7-SNAPSHOT-2.8.0" % "compile" @@ -321,6 +330,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { val multiverse = Dependencies.multiverse val netty = Dependencies.netty val protobuf = Dependencies.protobuf + val scalaz = Dependencies.scalaz val sbinary = Dependencies.sbinary val sjson = Dependencies.sjson val werkz = Dependencies.werkz From 7ddc5531765d5351de39a61ac8a1cd051259417f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bon=C3=A9r?= Date: Fri, 23 Jul 2010 04:54:21 +0200 Subject: [PATCH 050/188] Now uses 'Duration' for all time properties in config --- .../src/main/scala/actor/ActiveObject.scala | 9 +++++---- akka-core/src/main/scala/actor/Actor.scala | 5 +++-- akka-core/src/main/scala/config/Config.scala | 2 ++ .../src/main/scala/remote/RemoteClient.scala | 12 ++++++------ .../src/main/scala/remote/RemoteServer.scala | 6 +++--- .../main/scala/stm/TransactionFactory.scala | 1 - akka-core/src/main/scala/util/Duration.scala | 17 ++++++++++++++++- .../scala/AtomikosTransactionService.scala | 8 +++++--- .../main/scala/ActiveObjectFactoryBean.scala | 4 ++-- config/akka-reference.conf | 18 +++++++++--------- 10 files changed, 51 insertions(+), 31 deletions(-) diff --git a/akka-core/src/main/scala/actor/ActiveObject.scala b/akka-core/src/main/scala/actor/ActiveObject.scala index b83816f4d2..83ac1fc924 100644 --- a/akka-core/src/main/scala/actor/ActiveObject.scala +++ b/akka-core/src/main/scala/actor/ActiveObject.scala @@ -42,8 +42,9 @@ final class ActiveObjectConfiguration { private[akka] var _host: Option[InetSocketAddress] = None private[akka] var _messageDispatcher: Option[MessageDispatcher] = None - def timeout(timeout: Long) : ActiveObjectConfiguration = { - _timeout = timeout + def timeout = _timeout + def timeout(timeout: Duration) : ActiveObjectConfiguration = { + _timeout = timeout.toMillis this } @@ -181,7 +182,7 @@ object ActiveObject extends Logging { if (config._messageDispatcher.isDefined) { actor.dispatcher = config._messageDispatcher.get } - newInstance(target, actor, config._host, config._timeout) + newInstance(target, actor, config._host, config.timeout) } def newInstance[T](intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration): T = { @@ -189,7 +190,7 @@ object ActiveObject extends Logging { if (config._messageDispatcher.isDefined) { actor.dispatcher = config._messageDispatcher.get } - newInstance(intf, target, actor, config._host, config._timeout) + newInstance(intf, target, actor, config._host, config.timeout) } @deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead") diff --git a/akka-core/src/main/scala/actor/Actor.scala b/akka-core/src/main/scala/actor/Actor.scala index 244fd8fbc7..b99ce22a93 100644 --- a/akka-core/src/main/scala/actor/Actor.scala +++ b/akka-core/src/main/scala/actor/Actor.scala @@ -9,9 +9,10 @@ import se.scalablesolutions.akka.config.Config._ import se.scalablesolutions.akka.config.ScalaConfig._ import se.scalablesolutions.akka.serialization.Serializer import se.scalablesolutions.akka.util.Helpers.{narrow, narrowSilently} -import se.scalablesolutions.akka.util.Logging +import se.scalablesolutions.akka.util.{Logging, Duration} import com.google.protobuf.Message + import java.util.concurrent.TimeUnit /** @@ -62,7 +63,7 @@ class ActorInitializationException private[akka](message: String) extends Runtim * @author Jonas Bonér */ object Actor extends Logging { - val TIMEOUT = config.getInt("akka.actor.timeout", 5000) + val TIMEOUT = Duration(config.getInt("akka.actor.timeout", 5), TIME_UNIT).toMillis val SERIALIZE_MESSAGES = config.getBool("akka.actor.serialize-messages", false) /** diff --git a/akka-core/src/main/scala/config/Config.scala b/akka-core/src/main/scala/config/Config.scala index 68842ad1e3..ec44453e59 100644 --- a/akka-core/src/main/scala/config/Config.scala +++ b/akka-core/src/main/scala/config/Config.scala @@ -82,6 +82,8 @@ object Config extends Logging { if (VERSION != CONFIG_VERSION) throw new ConfigurationException( "Akka JAR version [" + VERSION + "] is different than the provided config ('akka.conf') version [" + CONFIG_VERSION + "]") + val TIME_UNIT = config.getString("akka.time-unit", "seconds") + val startTime = System.currentTimeMillis def uptime = (System.currentTimeMillis - startTime) / 1000 } diff --git a/akka-core/src/main/scala/remote/RemoteClient.scala b/akka-core/src/main/scala/remote/RemoteClient.scala index 4c18dcc6c8..2936b73b67 100644 --- a/akka-core/src/main/scala/remote/RemoteClient.scala +++ b/akka-core/src/main/scala/remote/RemoteClient.scala @@ -7,8 +7,8 @@ package se.scalablesolutions.akka.remote import se.scalablesolutions.akka.remote.protocol.RemoteProtocol._ import se.scalablesolutions.akka.actor.{Exit, Actor, ActorRef, RemoteActorRef, IllegalActorStateException} import se.scalablesolutions.akka.dispatch.{DefaultCompletableFuture, CompletableFuture} -import se.scalablesolutions.akka.util.{UUID, Logging} -import se.scalablesolutions.akka.config.Config.config +import se.scalablesolutions.akka.util.{UUID, Logging, Duration} +import se.scalablesolutions.akka.config.Config._ import org.jboss.netty.channel._ import group.DefaultChannelGroup @@ -50,8 +50,8 @@ case class RemoteClientConnected(host: String, port: Int) extends RemoteClientLi * @author Jonas Bonér */ object RemoteClient extends Logging { - val READ_TIMEOUT = config.getInt("akka.remote.client.read-timeout", 10000) - val RECONNECT_DELAY = config.getInt("akka.remote.client.reconnect-delay", 5000) + val READ_TIMEOUT = Duration(config.getInt("akka.remote.client.read-timeout", 1), TIME_UNIT) + val RECONNECT_DELAY = Duration(config.getInt("akka.remote.client.reconnect-delay", 5), TIME_UNIT) private val remoteClients = new HashMap[String, RemoteClient] private val remoteActors = new HashMap[RemoteServer.Address, HashSet[String]] @@ -249,7 +249,7 @@ class RemoteClientPipelineFactory(name: String, timer: HashedWheelTimer, client: RemoteClient) extends ChannelPipelineFactory { def getPipeline: ChannelPipeline = { - val timeout = new ReadTimeoutHandler(timer, RemoteClient.READ_TIMEOUT) + val timeout = new ReadTimeoutHandler(timer, RemoteClient.READ_TIMEOUT.toMillis.toInt) val lenDec = new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4) val lenPrep = new LengthFieldPrepender(4) val protobufDec = new ProtobufDecoder(RemoteReplyProtocol.getDefaultInstance) @@ -338,7 +338,7 @@ class RemoteClientHandler(val name: String, log.error(client.connection.getCause, "Reconnection to [%s] has failed", remoteAddress) } } - }, RemoteClient.RECONNECT_DELAY, TimeUnit.MILLISECONDS) + }, RemoteClient.RECONNECT_DELAY.toMillis, TimeUnit.MILLISECONDS) } override def channelConnected(ctx: ChannelHandlerContext, event: ChannelStateEvent) = { diff --git a/akka-core/src/main/scala/remote/RemoteServer.scala b/akka-core/src/main/scala/remote/RemoteServer.scala index 4283945de9..9ad33e9f3e 100644 --- a/akka-core/src/main/scala/remote/RemoteServer.scala +++ b/akka-core/src/main/scala/remote/RemoteServer.scala @@ -13,7 +13,7 @@ import se.scalablesolutions.akka.actor._ import se.scalablesolutions.akka.actor.Actor._ import se.scalablesolutions.akka.util._ import se.scalablesolutions.akka.remote.protocol.RemoteProtocol._ -import se.scalablesolutions.akka.config.Config.config +import se.scalablesolutions.akka.config.Config._ import org.jboss.netty.bootstrap.ServerBootstrap import org.jboss.netty.channel._ @@ -63,7 +63,7 @@ object RemoteServer { val HOSTNAME = config.getString("akka.remote.server.hostname", "localhost") val PORT = config.getInt("akka.remote.server.port", 9999) - val CONNECTION_TIMEOUT_MILLIS = config.getInt("akka.remote.server.connection-timeout", 1000) + val CONNECTION_TIMEOUT_MILLIS = Duration(config.getInt("akka.remote.server.connection-timeout", 1), TIME_UNIT) val COMPRESSION_SCHEME = config.getString("akka.remote.compression-scheme", "zlib") val ZLIB_COMPRESSION_LEVEL = { @@ -202,7 +202,7 @@ class RemoteServer extends Logging { bootstrap.setOption("child.tcpNoDelay", true) bootstrap.setOption("child.keepAlive", true) bootstrap.setOption("child.reuseAddress", true) - bootstrap.setOption("child.connectTimeoutMillis", RemoteServer.CONNECTION_TIMEOUT_MILLIS) + bootstrap.setOption("child.connectTimeoutMillis", RemoteServer.CONNECTION_TIMEOUT_MILLIS.toMillis) openChannels.add(bootstrap.bind(new InetSocketAddress(hostname, port))) _isRunning = true Cluster.registerLocalNode(hostname, port) diff --git a/akka-core/src/main/scala/stm/TransactionFactory.scala b/akka-core/src/main/scala/stm/TransactionFactory.scala index 24c4712509..329928c011 100644 --- a/akka-core/src/main/scala/stm/TransactionFactory.scala +++ b/akka-core/src/main/scala/stm/TransactionFactory.scala @@ -23,7 +23,6 @@ object TransactionConfig { val READONLY = null.asInstanceOf[JBoolean] val MAX_RETRIES = config.getInt("akka.stm.max-retries", 1000) val TIMEOUT = config.getLong("akka.stm.timeout", 10) - val TIME_UNIT = config.getString("akka.stm.time-unit", "seconds") val TRACK_READS = null.asInstanceOf[JBoolean] val WRITE_SKEW = config.getBool("akka.stm.write-skew", true) val EXPLICIT_RETRIES = config.getBool("akka.stm.explicit-retries", false) diff --git a/akka-core/src/main/scala/util/Duration.scala b/akka-core/src/main/scala/util/Duration.scala index f49e1ae04b..0dee2fc139 100644 --- a/akka-core/src/main/scala/util/Duration.scala +++ b/akka-core/src/main/scala/util/Duration.scala @@ -20,8 +20,21 @@ object Duration { /** * Utility for working with java.util.concurrent.TimeUnit durations. + * *

- * Example: + * Examples of usage from Java: + *

+ * import se.scalablesolutions.akka.util.Duration;
+ * import java.util.concurrent.TimeUnit;
+ *
+ * Duration duration = new Duration(100, TimeUnit.MILLISECONDS);
+ * Duration duration = new Duration(5, "seconds");
+ *
+ * duration.toNanos();
+ * 
+ * + *

+ * Examples of usage from Scala: *

  * import se.scalablesolutions.akka.util.Duration
  * import java.util.concurrent.TimeUnit
@@ -31,6 +44,7 @@ object Duration {
  *
  * duration.toNanos
  * 
+ * *

* Implicits are also provided for Int and Long. Example usage: *

@@ -40,6 +54,7 @@ object Duration {
  * 
*/ class Duration(val length: Long, val unit: TimeUnit) { + def this(length: Long, unit: String) = this(length, Duration.timeUnit(unit)) def toNanos = unit.toNanos(length) def toMicros = unit.toMicros(length) def toMillis = unit.toMillis(length) diff --git a/akka-jta/src/main/scala/AtomikosTransactionService.scala b/akka-jta/src/main/scala/AtomikosTransactionService.scala index 937f31a54e..f85ff56e6a 100644 --- a/akka-jta/src/main/scala/AtomikosTransactionService.scala +++ b/akka-jta/src/main/scala/AtomikosTransactionService.scala @@ -10,6 +10,7 @@ import com.atomikos.icatch.jta.{J2eeTransactionManager, J2eeUserTransaction} import com.atomikos.icatch.config.{TSInitInfo, UserTransactionService, UserTransactionServiceImp} import se.scalablesolutions.akka.config.Config._ +import se.scalablesolutions.akka.util.Duration import se.scalablesolutions.akka.stm.{TransactionService, TransactionContainer} object AtomikosTransactionService extends AtomikosTransactionService @@ -20,8 +21,8 @@ object AtomikosTransactionService extends AtomikosTransactionService * @author Jonas Bonér */ class AtomikosTransactionService extends TransactionService with TransactionProtocol { + val JTA_TRANSACTION_TIMEOUT = Duration(config.getInt("akka.jta.timeout", 60), TIME_UNIT) - val JTA_TRANSACTION_TIMEOUT: Int = config.getInt("akka.jta.timeout", 60000) / 1000 private val txService: UserTransactionService = new UserTransactionServiceImp private val info: TSInitInfo = txService.createTSInitInfo @@ -29,10 +30,11 @@ class AtomikosTransactionService extends TransactionService with TransactionProt try { txService.init(info) val tm: TransactionManager = new J2eeTransactionManager - tm.setTransactionTimeout(JTA_TRANSACTION_TIMEOUT) + tm.setTransactionTimeout(JTA_TRANSACTION_TIMEOUT.toSeconds.toInt) tm } catch { - case e => throw new SystemException("Could not create a new Atomikos J2EE Transaction Manager, due to: " + e.toString) + case e => throw new SystemException( + "Could not create a new Atomikos J2EE Transaction Manager, due to: " + e.toString) } ))) // TODO: gracefully shutdown of the TM diff --git a/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala b/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala index 6f62c5a8c4..7e33d0176a 100644 --- a/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala +++ b/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala @@ -22,7 +22,7 @@ import org.springframework.util.StringUtils import se.scalablesolutions.akka.actor.{ActiveObjectConfiguration, ActiveObject} import se.scalablesolutions.akka.config.ScalaConfig.{ShutdownCallback, RestartCallbacks} import se.scalablesolutions.akka.dispatch.MessageDispatcher -import se.scalablesolutions.akka.util.Logging +import se.scalablesolutions.akka.util.{Logging, Duration} /** * Factory bean for active objects. @@ -167,7 +167,7 @@ class ActiveObjectFactoryBean extends AbstractFactoryBean[AnyRef] with Logging w private[akka] def createConfig: ActiveObjectConfiguration = { - val config = new ActiveObjectConfiguration().timeout(timeout) + val config = new ActiveObjectConfiguration().timeout(Duration(timeout, "millis")) if (hasRestartCallbacks) config.restartCallbacks(pre, post) if (hasShutdownCallback) config.shutdownCallback(shutdown) if (transactional) config.makeTransactionRequired diff --git a/config/akka-reference.conf b/config/akka-reference.conf index c504598e31..a3cb3467b0 100644 --- a/config/akka-reference.conf +++ b/config/akka-reference.conf @@ -13,15 +13,17 @@ log { # syslog_host = "" # syslog_server_name = "" - akka { + akka { # example of package level logging settings node = "se.scalablesolutions.akka" - level = "info" + level = "debug" } } akka { version = "0.10" + time-unit = "seconds" # default timeout time unit for all timeout properties throughout the config + # FQN (Fully Qualified Name) to the class doing initial active object/actor # supervisor bootstrap, should be defined in default constructor boot = ["sample.camel.Boot", @@ -30,7 +32,7 @@ akka { "sample.security.Boot"] actor { - timeout = 5000 # default timeout for future based invocations + timeout = 5 # default timeout for future based invocations serialize-messages = off # does a deep clone of (non-primitive) messages to ensure immutability throughput = 5 # default throughput for ExecutorBasedEventDrivenDispatcher } @@ -41,15 +43,13 @@ akka { # begin (or join), commit or rollback the JTA transaction. Default is 'off'. timeout = 5 # default timeout for blocking transactions and transaction set (in unit defined by # the time-unit property) - # FIXME: use 'time-unit' for all timeouts - time-unit = "seconds" # default timeout time unit } jta { provider = "from-jndi" # Options: "from-jndi" (means that Akka will try to detect a TransactionManager in the JNDI) # "atomikos" (means that Akka will use the Atomikos based JTA impl in 'akka-jta', # e.g. you need the akka-jta JARs on classpath). - timeout = 60000 + timeout = 60 } rest { @@ -85,12 +85,12 @@ akka { service = on hostname = "localhost" port = 9999 - connection-timeout = 1000 # in millis (1 sec default) + connection-timeout = 1 } client { - reconnect-delay = 5000 # in millis (5 sec default) - read-timeout = 10000 # in millis (10 sec default) + reconnect-delay = 5 + read-timeout = 10 } } From ec97e72da1224906870308fd58031a9bd27a3b07 Mon Sep 17 00:00:00 2001 From: momania Date: Fri, 23 Jul 2010 11:28:42 +0200 Subject: [PATCH 051/188] Test #307 - Proof schedule continues with retarted actor --- akka-core/src/main/scala/actor/Actor.scala | 10 +- .../src/main/scala/actor/ActorRegistry.scala | 2 +- akka-core/src/test/scala/ScalazSpec.scala | 66 ------ akka-core/src/test/scala/SchedulerSpec.scala | 51 ++++- project/build/AkkaProject.scala | 191 +++++++++++++++--- project/plugins/Plugins.scala | 7 +- 6 files changed, 225 insertions(+), 102 deletions(-) delete mode 100644 akka-core/src/test/scala/ScalazSpec.scala diff --git a/akka-core/src/main/scala/actor/Actor.scala b/akka-core/src/main/scala/actor/Actor.scala index 76adf9c729..244fd8fbc7 100644 --- a/akka-core/src/main/scala/actor/Actor.scala +++ b/akka-core/src/main/scala/actor/Actor.scala @@ -414,6 +414,14 @@ trait Actor extends Logging { * Is the actor able to handle the message passed in as arguments? */ def isDefinedAt(message: Any): Boolean = base.isDefinedAt(message) + + /** One of the fundamental methods of the ActorsModel + * Actor assumes a new behavior + */ + def become(behavior: Option[Receive]) { + self.hotswap = behavior + self.checkReceiveTimeout // FIXME : how to reschedule receivetimeout on hotswap? + } // ========================================= // ==== INTERNAL IMPLEMENTATION DETAILS ==== @@ -427,7 +435,7 @@ trait Actor extends Logging { } private val lifeCycles: Receive = { - case HotSwap(code) => self.hotswap = code; self.checkReceiveTimeout // FIXME : how to reschedule receivetimeout on hotswap? + case HotSwap(code) => become(code) case Exit(dead, reason) => self.handleTrapExit(dead, reason) case Link(child) => self.link(child) case Unlink(child) => self.unlink(child) diff --git a/akka-core/src/main/scala/actor/ActorRegistry.scala b/akka-core/src/main/scala/actor/ActorRegistry.scala index 88113a30a0..57b27f08b0 100644 --- a/akka-core/src/main/scala/actor/ActorRegistry.scala +++ b/akka-core/src/main/scala/actor/ActorRegistry.scala @@ -159,7 +159,7 @@ object ActorRegistry extends ListenerManagement { /** * Shuts down and unregisters all actors in the system. */ - def shutdownAll = { + def shutdownAll() { log.info("Shutting down all actors in the system...") foreach(_.stop) actorsByUUID.clear diff --git a/akka-core/src/test/scala/ScalazSpec.scala b/akka-core/src/test/scala/ScalazSpec.scala deleted file mode 100644 index 123f213f10..0000000000 --- a/akka-core/src/test/scala/ScalazSpec.scala +++ /dev/null @@ -1,66 +0,0 @@ -package se.scalablesolutions.akka.actor - -import org.scalatest.junit.JUnitSuite -import org.junit.Test - -import Actor._ -import org.multiverse.api.latches.StandardLatch -import scalaz._ -import concurrent.{Strategy, Promise} -import java.lang.String -import Scalaz._ -import se.scalablesolutions.akka.config.ScalaConfig.{LifeCycle, Permanent} -import se.scalablesolutions.akka.dispatch.{Future, FutureTimeoutException} -import java.util.concurrent.{Executors, TimeUnit} - -class ScalazSpec extends JUnitSuite { - val actorRef = actorOf(new Actor { - protected def receive = { - case "one" => self.reply(1) - case "error" => TimeUnit.SECONDS.sleep(10) - } - }).start - - @Test def callActorAndGetValidation = { - - implicit val executorService = Executors.newFixedThreadPool(2) - import Strategy.Executor - - val promiseError: Promise[ValidationNEL[String, Option[Int]]] = promise(callActor("error")) - val promiseOne: Promise[ValidationNEL[String, Option[Int]]] = promise(callActor("error")) - - //[X]Promise[X] <-- Applicative / Monad - //[X]Option[X] <-- Applicative / Monad - //[X]Validation[String, X] <-- Applicative / Monad iff Semigroup[String] - //[X]Promise[Option[X]] <-- Applicative - - val pvi: Promise[ValidationNEL[String, Option[Int]]] = (promiseError |@| promiseOne) { - (v1, v2) => - (v1 |@| v2) { - (o1, o2) => - (o1 |@| o2) { _ + _} - } - } - - println(pvi.get) - - val listOptionInt: List[Option[Int]] = List.fill(5)(1.some) - // val listOptionInt = (listOptionInt.comp) map (_ * 2) - - println(listOptionInt.sequence[Option, Int]) - - } - - def callActor(msg: String): ValidationNEL[String, Option[Int]] = { - try { - val future: Future[Int] = (actorRef !!! msg) - future.await - future.exception match { - case Some((_, t)) => t.getMessage.failNel - case None => future.result.successNel - } - } catch { - case e: FutureTimeoutException => e.getMessage.failNel - } - } -} \ No newline at end of file diff --git a/akka-core/src/test/scala/SchedulerSpec.scala b/akka-core/src/test/scala/SchedulerSpec.scala index 0fe7c45ea5..7db5727834 100644 --- a/akka-core/src/test/scala/SchedulerSpec.scala +++ b/akka-core/src/test/scala/SchedulerSpec.scala @@ -3,10 +3,11 @@ package se.scalablesolutions.akka.actor import org.scalatest.junit.JUnitSuite import Actor._ import java.util.concurrent.{CountDownLatch, TimeUnit} -import org.junit.{After, Test} +import org.junit.Test +import se.scalablesolutions.akka.config.ScalaConfig._ +import org.multiverse.api.latches.StandardLatch class SchedulerSpec extends JUnitSuite { - @Test def schedulerShouldScheduleMoreThanOnce = { case object Tick @@ -35,4 +36,50 @@ class SchedulerSpec extends JUnitSuite { // should still be 1 left assert(countDownLatch.getCount == 1) } + + /** + * ticket #307 + */ + @Test def actorRestartShouldPickUpScheduleAgain = { + + try { + object Ping + object Crash + + val restartLatch = new StandardLatch + val pingLatch = new CountDownLatch(4) + + val actor = actorOf(new Actor { + self.lifeCycle = Some(LifeCycle(Permanent)) + + def receive = { + case Ping => pingLatch.countDown + case Crash => throw new Exception("CRASH") + } + + override def postRestart(reason: Throwable) = restartLatch.open + }) + + Supervisor( + SupervisorConfig( + RestartStrategy(AllForOne, 3, 1000, + List(classOf[Exception])), + Supervise( + actor, + LifeCycle(Permanent)) + :: Nil)).start + + Scheduler.schedule(actor, Ping, 500, 500, TimeUnit.MILLISECONDS) + // appx 2 pings before crash + Scheduler.scheduleOnce(actor, Crash, 1000, TimeUnit.MILLISECONDS) + + assert(restartLatch.tryAwait(4, TimeUnit.SECONDS)) + // should be enough time for the ping countdown to recover and reach 4 pings + assert(pingLatch.await(4, TimeUnit.SECONDS)) + + } finally { + + Scheduler.shutdown + } + } } diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 03fbc9b80c..4507193de9 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -2,21 +2,21 @@ | Copyright (C) 2009-2010 Scalable Solutions AB | \---------------------------------------------------------------------------*/ -import sbt._ -import sbt.CompileOrder._ - -import spde._ +import com.weiglewilczek.bnd4sbt.BNDPlugin import de.tuxed.codefellow.plugin.CodeFellowPlugin - +import java.io.File import java.util.jar.Attributes import java.util.jar.Attributes.Name._ -import java.io.File +import sbt._ +import sbt.CompileOrder._ +import spde._ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // Compile settings // ------------------------------------------------------------------------------------------------------------------- + override def compileOptions = super.compileOptions ++ Seq("-deprecation", "-Xmigration", @@ -30,6 +30,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // Deploy/dist settings // ------------------------------------------------------------------------------------------------------------------- + lazy val deployPath = info.projectPath / "deploy" lazy val distPath = info.projectPath / "dist" def distName = "%s_%s-%s.zip".format(name, buildScalaVersion, version) @@ -38,6 +39,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // All repositories *must* go here! See ModuleConigurations below. // ------------------------------------------------------------------------------------------------------------------- + object Repositories { lazy val AkkaRepo = MavenRepository("Akka Repository", "http://scalablesolutions.se/akka/repository") lazy val CodehausSnapshotRepo = MavenRepository("Codehaus Snapshots", "http://snapshots.repository.codehaus.org") @@ -47,20 +49,15 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val JavaNetRepo = MavenRepository("java.net Repo", "http://download.java.net/maven/2") lazy val SonatypeSnapshotRepo = MavenRepository("Sonatype OSS Repo", "http://oss.sonatype.org/content/repositories/releases") lazy val SunJDMKRepo = MavenRepository("Sun JDMK Repo", "http://wp5.e-taxonomy.eu/cdmlib/mavenrepo") - lazy val ScalazRepo = MavenRepository("Scalaz Repo", "http://scala-tools.org/repo-releases") } - val mavenLocal = "Local Maven Repository" at "file:/e:/maven-repository" - - val efgfpNexusReleasesRepository = "Nexus Releases" at "http://nexus/nexus/content/groups/public" - val efgfpNexusSnaphotsRepository = "Nexus Snapshots" at "http://nexus/nexus/content/groups/public-snapshots" - // ------------------------------------------------------------------------------------------------------------------- // ModuleConfigurations // Every dependency that cannot be resolved from the built-in repositories (Maven Central and Scala Tools Releases) // must be resolved from a ModuleConfiguration. This will result in a significant acceleration of the update action. // Therefore, if repositories are defined, this must happen as def, not as val. // ------------------------------------------------------------------------------------------------------------------- + import Repositories._ lazy val atmosphereModuleConfig = ModuleConfiguration("org.atmosphere", SonatypeSnapshotRepo) lazy val grizzlyModuleConfig = ModuleConfiguration("com.sun.grizzly", JavaNetRepo) @@ -75,13 +72,13 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val liftModuleConfig = ModuleConfiguration("net.liftweb", ScalaToolsSnapshots) lazy val multiverseModuleConfig = ModuleConfiguration("org.multiverse", CodehausSnapshotRepo) lazy val nettyModuleConfig = ModuleConfiguration("org.jboss.netty", JBossRepo) - lazy val scalazModuleConfig = ModuleConfiguration("scalaz", ScalazRepo) lazy val scalaTestModuleConfig = ModuleConfiguration("org.scalatest", ScalaToolsSnapshots) lazy val embeddedRepo = EmbeddedRepo // This is the only exception, because the embedded repo is fast! // ------------------------------------------------------------------------------------------------------------------- // Versions // ------------------------------------------------------------------------------------------------------------------- + lazy val ATMO_VERSION = "0.6" lazy val CAMEL_VERSION = "2.4.0" lazy val CASSANDRA_VERSION = "0.6.1" @@ -98,6 +95,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // Dependencies // ------------------------------------------------------------------------------------------------------------------- + object Dependencies { // Compile @@ -157,29 +155,29 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val jsr311 = "javax.ws.rs" % "jsr311-api" % "1.1" % "compile" - lazy val jta_1_1 = "org.apache.geronimo.specs" % "geronimo-jta_1.1_spec" % "1.1.1" % "compile" intransitive() + lazy val jta_1_1 = "org.apache.geronimo.specs" % "geronimo-jta_1.1_spec" % "1.1.1" % "compile" intransitive - lazy val lift = "net.liftweb" % "lift-webkit" % LIFT_VERSION % "compile" - lazy val lift_util = "net.liftweb" % "lift-util" % LIFT_VERSION % "compile" + lazy val lift_util = "net.liftweb" % "lift-util" % LIFT_VERSION % "compile" + lazy val lift_webkit = "net.liftweb" % "lift-webkit" % LIFT_VERSION % "compile" lazy val log4j = "log4j" % "log4j" % "1.2.15" % "compile" - lazy val mongo = "org.mongodb" % "mongo-java-driver" % "1.4" % "compile" + lazy val mongo = "org.mongodb" % "mongo-java-driver" % "2.0" % "compile" - lazy val multiverse = "org.multiverse" % "multiverse-alpha" % MULTIVERSE_VERSION % "compile" intransitive() + lazy val multiverse = "org.multiverse" % "multiverse-alpha" % MULTIVERSE_VERSION % "compile" intransitive lazy val netty = "org.jboss.netty" % "netty" % "3.2.1.Final" % "compile" lazy val protobuf = "com.google.protobuf" % "protobuf-java" % "2.3.0" % "compile" + lazy val osgi_core = "org.osgi" % "org.osgi.core" % "4.2.0" + lazy val rabbit = "com.rabbitmq" % "amqp-client" % "1.8.1" % "compile" lazy val redis = "com.redis" % "redisclient" % "2.8.0-1.4" % "compile" lazy val sbinary = "sbinary" % "sbinary" % "2.8.0-0.3.1" % "compile" - lazy val scalaz = "com.googlecode.scalaz" % "scalaz-core_2.8.0" % "5.0" % "compile" - lazy val servlet = "javax.servlet" % "servlet-api" % "2.5" % "compile" lazy val sjson = "sjson.json" % "sjson" % "0.7-SNAPSHOT-2.8.0" % "compile" @@ -213,6 +211,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // Subprojects // ------------------------------------------------------------------------------------------------------------------- + lazy val akka_core = project("akka-core", "akka-core", new AkkaCoreProject(_)) lazy val akka_amqp = project("akka-amqp", "akka-amqp", new AkkaAMQPProject(_), akka_core) lazy val akka_http = project("akka-http", "akka-http", new AkkaHttpProject(_), akka_core, akka_camel) @@ -222,10 +221,13 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val akka_jta = project("akka-jta", "akka-jta", new AkkaJTAProject(_), akka_core) lazy val akka_kernel = project("akka-kernel", "akka-kernel", new AkkaKernelProject(_), akka_core, akka_http, akka_spring, akka_camel, akka_persistence, akka_amqp) + lazy val akka_osgi = project("akka-osgi", "akka-osgi", new AkkaOSGiParentProject(_)) lazy val akka_samples = project("akka-samples", "akka-samples", new AkkaSamplesParentProject(_)) - // ------------------------------------------------------------ - // Run Akka microkernel using 'sbt run' + use for packaging executable JAR + // ------------------------------------------------------------------------------------------------------------------- + // Miscellaneous + // ------------------------------------------------------------------------------------------------------------------- + override def mainClass = Some("se.scalablesolutions.akka.kernel.Main") override def packageOptions = @@ -307,12 +309,13 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { " -Dpackaging=jar -DgeneratePom=true" command ! log } - None + None } dependsOn(dist) describedAs("Run mvn install for artifacts in dist.") // ------------------------------------------------------------------------------------------------------------------- // akka-core subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaCoreProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val aopalliance = Dependencies.aopalliance val commons_codec = Dependencies.commons_codec @@ -330,7 +333,6 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { val multiverse = Dependencies.multiverse val netty = Dependencies.netty val protobuf = Dependencies.protobuf - val scalaz = Dependencies.scalaz val sbinary = Dependencies.sbinary val sjson = Dependencies.sjson val werkz = Dependencies.werkz @@ -344,6 +346,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-amqp subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaAMQPProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val commons_io = Dependencies.commons_io val rabbit = Dependencies.rabbit @@ -357,6 +360,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-http subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaHttpProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val annotation = Dependencies.annotation val atmo = Dependencies.atmo @@ -385,6 +389,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-camel subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaCamelProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val camel_core = Dependencies.camel_core } @@ -392,6 +397,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-persistence subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaPersistenceParentProject(info: ProjectInfo) extends ParentProject(info) { lazy val akka_persistence_common = project("akka-persistence-common", "akka-persistence-common", new AkkaPersistenceCommonProject(_), akka_core) @@ -414,6 +420,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-persistence-redis subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaRedisProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val commons_codec = Dependencies.commons_codec val redis = Dependencies.redis @@ -424,6 +431,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-persistence-mongo subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaMongoProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val mongo = Dependencies.mongo @@ -433,6 +441,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-persistence-cassandra subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaCassandraProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val cassandra = Dependencies.cassandra val log4j = Dependencies.log4j @@ -451,11 +460,13 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-kernel subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaKernelProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) // ------------------------------------------------------------------------------------------------------------------- // akka-spring subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaSpringProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val spring_beans = Dependencies.spring_beans val spring_context = Dependencies.spring_context @@ -469,6 +480,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- // akka-jta subproject // ------------------------------------------------------------------------------------------------------------------- + class AkkaJTAProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val atomikos_transactions = Dependencies.atomikos_transactions val atomikos_transactions_api = Dependencies.atomikos_transactions_api @@ -477,7 +489,112 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { //val atomikos_transactions_util = "com.atomikos" % "transactions-util" % "3.2.3" % "compile" } - // ================= EXAMPLES ================== + // ------------------------------------------------------------------------------------------------------------------- + // OSGi stuff + // ------------------------------------------------------------------------------------------------------------------- + + class AkkaOSGiParentProject(info: ProjectInfo) extends ParentProject(info) { + lazy val akka_osgi_dependencies_bundle = project("akka-osgi-dependencies-bundle", "akka-osgi-dependencies-bundle", + new AkkaOSGiDependenciesBundleProject(_), akka_kernel, akka_jta) // akka_kernel does not depend on akka_jta (why?) therefore we list akka_jta here + lazy val akka_osgi_assembly = project("akka-osgi-assembly", "akka-osgi-assembly", + new AkkaOSGiAssemblyProject(_), akka_osgi_dependencies_bundle, akka_core, akka_amqp, akka_http, + akka_camel, akka_spring, akka_jta, akka_persistence.akka_persistence_common, + akka_persistence.akka_persistence_redis, akka_persistence.akka_persistence_mongo, + akka_persistence.akka_persistence_cassandra) + } + + class AkkaOSGiDependenciesBundleProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with BNDPlugin { + override def bndClasspath = compileClasspath + override def bndPrivatePackage = Seq("") + override def bndImportPackage = Seq("*;resolution:=optional") + override def bndExportPackage = Seq( + "org.aopalliance.*;version=1.0.0", + + // Provided by other bundles + "!se.scalablesolutions.akka.*", + "!net.liftweb.*", + "!com.google.inject.*", + "!javax.transaction.*", + "!javax.ws.rs.*", + "!javax.jms.*", + "!javax.transaction,*", + "!org.apache.commons.io.*", + "!org.apache.commons.pool.*", + "!org.codehaus.jackson.*", + "!org.jboss.netty.*", + "!org.springframework.*", + "!org.apache.camel.*", + "!org.fusesource.commons.management.*", + + "*;version=0.0.0") + } + + class AkkaOSGiAssemblyProject(info: ProjectInfo) extends DefaultProject(info) { + + // Scala bundle + val scala_bundle = "com.weiglewilczek.scala-lang-osgi" % "scala-library" % buildScalaVersion % "compile" intransitive + + // Lift bundles +// val lift_util = Dependencies.lift_util.intransitive +// val lift_actor = "net.liftweb" % "lift-actor" % LIFT_VERSION % "compile" intransitive +// val lift_common = "net.liftweb" % "lift-common" % LIFT_VERSION % "compile" intransitive +// val lift_json = "net.liftweb" % "lift-json" % LIFT_VERSION % "compile" intransitive + + // Camel bundles + val camel_core = Dependencies.camel_core.intransitive + val fusesource_commonman = "org.fusesource.commonman" % "commons-management" % "1.0" intransitive + + // Spring bundles + val spring_beans = Dependencies.spring_beans.intransitive + val spring_context = Dependencies.spring_context.intransitive + val spring_aop = "org.springframework" % "spring-aop" % SPRING_VERSION % "compile" intransitive + val spring_asm = "org.springframework" % "spring-asm" % SPRING_VERSION % "compile" intransitive + val spring_core = "org.springframework" % "spring-core" % SPRING_VERSION % "compile" intransitive + val spring_expression = "org.springframework" % "spring-expression" % SPRING_VERSION % "compile" intransitive + val spring_jms = "org.springframework" % "spring-jms" % SPRING_VERSION % "compile" intransitive + val spring_tx = "org.springframework" % "spring-tx" % SPRING_VERSION % "compile" intransitive + + val commons_codec = Dependencies.commons_codec.intransitive + val commons_io = Dependencies.commons_io.intransitive + val commons_pool = Dependencies.commons_pool.intransitive + val guicey = Dependencies.guicey.intransitive + val jackson = Dependencies.jackson.intransitive + val jackson_core = Dependencies.jackson_core.intransitive + val jsr311 = Dependencies.jsr311.intransitive + val jta_1_1 = Dependencies.jta_1_1.intransitive + val netty = Dependencies.netty.intransitive + val commons_fileupload = "commons-fileupload" % "commons-fileupload" % "1.2.1" % "compile" intransitive + val jms_1_1 = "org.apache.geronimo.specs" % "geronimo-jms_1.1_spec" % "1.1.1" % "compile" intransitive + val joda = "joda-time" % "joda-time" % "1.6" intransitive + + override def packageAction = + task { + val libs: Seq[Path] = managedClasspath(config("compile")).get.toSeq + val prjs: Seq[Path] = info.dependencies.toSeq.asInstanceOf[Seq[DefaultProject]] map { _.jarPath } + val all = libs ++ prjs + val destination = outputPath / "bundles" + FileUtilities.copyFlat(all, destination, log) + log info "Copied %s bundles to %s".format(all.size, destination) + None + } + + override def artifacts = Set.empty + } + + // ------------------------------------------------------------------------------------------------------------------- + // Test + // ------------------------------------------------------------------------------------------------------------------- + + class AkkaActiveObjectTestProject(info: ProjectInfo) extends DefaultProject(info) { + // testing + val junit = "junit" % "junit" % "4.5" % "test" + val jmock = "org.jmock" % "jmock" % "2.4.0" % "test" + } + + // ------------------------------------------------------------------------------------------------------------------- + // Examples + // ------------------------------------------------------------------------------------------------------------------- + class AkkaSampleAntsProject(info: ProjectInfo) extends DefaultSpdeProject(info) with CodeFellowPlugin { // val scalaToolsSnapshots = ScalaToolsSnapshots override def spdeSourcePath = mainSourcePath / "spde" @@ -488,8 +605,8 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { class AkkaSampleLiftProject(info: ProjectInfo) extends DefaultWebProject(info) with DeployProject with CodeFellowPlugin { val commons_logging = Dependencies.commons_logging - val lift = Dependencies.lift val lift_util = Dependencies.lift_util + val lift_webkit = Dependencies.lift_webkit val servlet = Dependencies.servlet // testing @@ -530,6 +647,12 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { val jsr311 = Dependencies.jsr311 } + class AkkaSampleOSGiProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with BNDPlugin { + val osgi_core = Dependencies.osgi_core + override lazy val bndBundleActivator = Some("se.scalablesolutions.akka.sample.osgi.Activator") + override lazy val bndExportPackage = Nil // Necessary because of mixing-in AkkaDefaultProject which exports all ...akka.* packages! + } + class AkkaSamplesParentProject(info: ProjectInfo) extends ParentProject(info) { lazy val akka_sample_ants = project("akka-sample-ants", "akka-sample-ants", new AkkaSampleAntsProject(_), akka_core) @@ -549,10 +672,14 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { new AkkaSampleSecurityProject(_), akka_kernel) lazy val akka_sample_remote = project("akka-sample-remote", "akka-sample-remote", new AkkaSampleRemoteProject(_), akka_kernel) + lazy val akka_sample_osgi = project("akka-sample-osgi", "akka-sample-osgi", + new AkkaSampleOSGiProject(_), akka_core) } - // ------------------------------------------------------------ - // helper functions + // ------------------------------------------------------------------------------------------------------------------- + // Helpers + // ------------------------------------------------------------------------------------------------------------------- + def removeDupEntries(paths: PathFinder) = Path.lazyPathFinder { val mapped = paths.get map { p => (p.relativePath, p) } @@ -576,11 +703,11 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { !jar.toString.endsWith("scala-library-2.7.7.jar") ) } - + def akkaArtifacts = descendents(info.projectPath / "dist", "*" + buildScalaVersion + "-" + version + ".jar") // ------------------------------------------------------------ - class AkkaDefaultProject(info: ProjectInfo, val deployPath: Path) extends DefaultProject(info) with DeployProject + class AkkaDefaultProject(info: ProjectInfo, val deployPath: Path) extends DefaultProject(info) with DeployProject with OSGiProject trait DeployProject { self: Project => // defines where the deployTask copies jars to @@ -601,4 +728,8 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { FileUtilities.copyFile(jar, toDir / jar.name, log) } else None } + + trait OSGiProject extends DefaultProject with BNDPlugin { + override def bndExportPackage = Seq("se.scalablesolutions.akka.*;version=%s".format(projectVersion.value)) + } } diff --git a/project/plugins/Plugins.scala b/project/plugins/Plugins.scala index b19b0ebf8c..f0332505da 100644 --- a/project/plugins/Plugins.scala +++ b/project/plugins/Plugins.scala @@ -6,6 +6,7 @@ class Plugins(info: ProjectInfo) extends PluginDefinition(info) { // All repositories *must* go here! See ModuleConigurations below. // ------------------------------------------------------------------------------------------------------------------- object Repositories { + lazy val AquteRepo = "aQute Maven Repository" at "http://www.aqute.biz/repo" lazy val DatabinderRepo = "Databinder Repository" at "http://databinder.net/repo" lazy val EmbeddedRepo = "Embedded Repo" at (info.projectPath / "embedded-repo").asURL.toString } @@ -17,12 +18,14 @@ class Plugins(info: ProjectInfo) extends PluginDefinition(info) { // Therefore, if repositories are defined, this must happen as def, not as val. // ------------------------------------------------------------------------------------------------------------------- import Repositories._ + lazy val aquteModuleConfig = ModuleConfiguration("biz.aQute", AquteRepo) lazy val codeFellowModuleConfig = ModuleConfiguration("de.tuxed", EmbeddedRepo) lazy val spdeModuleConfig = ModuleConfiguration("us.technically.spde", DatabinderRepo) // ------------------------------------------------------------------------------------------------------------------- // Dependencies // ------------------------------------------------------------------------------------------------------------------- - lazy val codeFellow = "de.tuxed" % "codefellow-plugin" % "0.3" // for code completion and more in VIM - lazy val spdeSbt = "us.technically.spde" % "spde-sbt-plugin" % "0.4.1" + lazy val bnd4sbt = "com.weiglewilczek.bnd4sbt" % "bnd4sbt" % "1.0.0.RC4" + lazy val codeFellow = "de.tuxed" % "codefellow-plugin" % "0.3" // for code completion and more in VIM + lazy val spdeSbt = "us.technically.spde" % "spde-sbt-plugin" % "0.4.1" } From 7288e832b3e9899784a924f160a5f4f4b2a8c7aa Mon Sep 17 00:00:00 2001 From: momania Date: Fri, 23 Jul 2010 12:06:33 +0200 Subject: [PATCH 052/188] proof restart strategy --- .../src/test/scala/RestartStrategySpec.scala | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 akka-core/src/test/scala/RestartStrategySpec.scala diff --git a/akka-core/src/test/scala/RestartStrategySpec.scala b/akka-core/src/test/scala/RestartStrategySpec.scala new file mode 100644 index 0000000000..d314cf9388 --- /dev/null +++ b/akka-core/src/test/scala/RestartStrategySpec.scala @@ -0,0 +1,71 @@ +/** + * Copyright (C) 2009-2010 Scalable Solutions AB + */ + +package se.scalablesolutions.akka.actor + +import org.scalatest.junit.JUnitSuite +import org.junit.Test + +import Actor._ +import se.scalablesolutions.akka.config.OneForOneStrategy +import java.util.concurrent.{TimeUnit, CountDownLatch} +import se.scalablesolutions.akka.config.ScalaConfig.{Permanent, LifeCycle} +import org.multiverse.api.latches.StandardLatch + +class RestartStrategySpec extends JUnitSuite { + + object Ping + object Crash + + @Test + def slaveShouldStayDeadAfterMaxRestarts = { + + val boss = actorOf(new Actor{ + self.trapExit = List(classOf[Throwable]) + self.faultHandler = Some(OneForOneStrategy(1, 1000)) + protected def receive = { case _ => () } + }).start + + val restartLatch = new StandardLatch + val firstCountDown = new CountDownLatch(2) + val secondCountDown = new CountDownLatch(2) + + + val slave = actorOf(new Actor{ + self.lifeCycle = Some(LifeCycle(Permanent)) + + protected def receive = { + case Ping => { + log.info("png") + if (firstCountDown.getCount > 0) { + firstCountDown.countDown + } else { + secondCountDown.countDown + } + } + case Crash => throw new Exception("Crashing...") + } + override def postRestart(reason: Throwable) = restartLatch.open + }) + boss.startLink(slave) + + slave ! Ping + slave ! Crash + slave ! Ping + + // test restart and post restart ping + assert(restartLatch.tryAwait(1, TimeUnit.SECONDS)) + assert(firstCountDown.await(1, TimeUnit.SECONDS)) + + // now crash again... should not restart + slave ! Crash + + slave ! Ping // this should fail + slave ! Ping // this should fail + slave ! Ping // this should fail + slave ! Ping // this should fail + assert(secondCountDown.await(2, TimeUnit.SECONDS) == false) // should not hold + } +} + From f540ee1d33167afd7be96c26473fed3f46426bc8 Mon Sep 17 00:00:00 2001 From: Hiram Chirino Date: Fri, 23 Jul 2010 08:29:10 -0400 Subject: [PATCH 053/188] update to the released version of hawtdispatch --- akka-core/src/main/scala/dispatch/HawtDispatcher.scala | 3 ++- project/build/AkkaProject.scala | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/akka-core/src/main/scala/dispatch/HawtDispatcher.scala b/akka-core/src/main/scala/dispatch/HawtDispatcher.scala index 99c4cdd853..3e14f0a5aa 100644 --- a/akka-core/src/main/scala/dispatch/HawtDispatcher.scala +++ b/akka-core/src/main/scala/dispatch/HawtDispatcher.scala @@ -19,10 +19,11 @@ package se.scalablesolutions.akka.dispatch import se.scalablesolutions.akka.actor.ActorRef import org.fusesource.hawtdispatch.DispatchQueue import org.fusesource.hawtdispatch.ScalaDispatch._ -import actors.threadpool.AtomicInteger +import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.CountDownLatch import org.fusesource.hawtdispatch.DispatchQueue.QueueType +import org.fusesource.hawtdispatch.ListEventAggregator /** * Holds helper methods for working with actors that are using diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 02f2e18fec..505800a66d 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -63,7 +63,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val atmosphereModuleConfig = ModuleConfiguration("org.atmosphere", SonatypeSnapshotRepo) lazy val grizzlyModuleConfig = ModuleConfiguration("com.sun.grizzly", JavaNetRepo) lazy val guiceyFruitModuleConfig = ModuleConfiguration("org.guiceyfruit", GuiceyFruitRepo) - lazy val hawtdispatchModuleConfig = ModuleConfiguration("org.fusesource.hawtdispatch", FusesourceSnapshotRepo) + // lazy val hawtdispatchModuleConfig = ModuleConfiguration("org.fusesource.hawtdispatch", FusesourceSnapshotRepo) lazy val jbossModuleConfig = ModuleConfiguration("org.jboss", JBossRepo) lazy val jdmkModuleConfig = ModuleConfiguration("com.sun.jdmk", SunJDMKRepo) lazy val jerseyContrModuleConfig = ModuleConfiguration("com.sun.jersey.contribs", JavaNetRepo) @@ -85,7 +85,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val CAMEL_VERSION = "2.4.0" lazy val CASSANDRA_VERSION = "0.6.1" lazy val DispatchVersion = "0.7.4" - lazy val HAWTDISPATCH_VERSION = "1.0-SNAPSHOT" + lazy val HAWTDISPATCH_VERSION = "1.0" lazy val JacksonVersion = "1.2.1" lazy val JERSEY_VERSION = "1.2" lazy val LIFT_VERSION = "2.0-scala280-SNAPSHOT" From e91dc5cd4535c20478704290ce6d6f2e106d9484 Mon Sep 17 00:00:00 2001 From: momania Date: Fri, 23 Jul 2010 16:38:14 +0200 Subject: [PATCH 054/188] - better restart strategy test - make sure actor stops when restart strategy maxes out - nicer patternmathing on lifecycle making sure lifecycle.get is never called anymore (sometimes gave nullpointer exceptions) - also applying the defaults in a nicer way --- akka-core/src/main/scala/actor/ActorRef.scala | 52 ++++++++----------- .../src/test/scala/RestartStrategySpec.scala | 40 +++++++------- 2 files changed, 44 insertions(+), 48 deletions(-) diff --git a/akka-core/src/main/scala/actor/ActorRef.scala b/akka-core/src/main/scala/actor/ActorRef.scala index 82f035f311..d0b5496a6a 100644 --- a/akka-core/src/main/scala/actor/ActorRef.scala +++ b/akka-core/src/main/scala/actor/ActorRef.scala @@ -991,7 +991,6 @@ sealed class LocalActorRef private[akka]( "\n\tto non-empty list of exception classes - can't proceed " + toString) } } else { - if (lifeCycle.isEmpty) lifeCycle = Some(LifeCycle(Permanent)) // when passing on make sure we have a lifecycle notifySupervisorWithMessage(Exit(this, reason)) // if 'trapExit' is not defined then pass the Exit on } } @@ -1004,6 +1003,7 @@ sealed class LocalActorRef private[akka]( val restartingHasExpired = (System.currentTimeMillis - restartsWithinTimeRangeTimestamp) > withinTimeRange if (tooManyRestarts || restartingHasExpired) { + stop val notification = MaximumNumberOfRestartsWithinTimeRangeReached(this, maxNrOfRetries, withinTimeRange, reason) Actor.log.warning( "Maximum number of restarts [%s] within time range [%s] reached." + @@ -1018,30 +1018,27 @@ sealed class LocalActorRef private[akka]( "No message handler defined for system message [MaximumNumberOfRestartsWithinTimeRangeReached]" + "\n\tCan't send the message to the supervisor [%s].", sup) } - } else { + } else { _isBeingRestarted = true val failedActor = actorInstance.get guard.withGuard { - lifeCycle.get match { - case LifeCycle(scope, _, _) => { - scope match { - case Permanent => - Actor.log.info("Restarting actor [%s] configured as PERMANENT.", id) - restartLinkedActors(reason, maxNrOfRetries, withinTimeRange) - Actor.log.debug("Restarting linked actors for actor [%s].", id) - Actor.log.debug("Invoking 'preRestart' for failed actor instance [%s].", id) - failedActor.preRestart(reason) - nullOutActorRefReferencesFor(failedActor) - val freshActor = newActor - freshActor.init - freshActor.initTransactionalState - actorInstance.set(freshActor) - Actor.log.debug("Invoking 'postRestart' for new actor instance [%s].", id) - freshActor.postRestart(reason) - _isBeingRestarted = false - case Temporary => shutDownTemporaryActor(this) - } - } + lifeCycle match { + case Some(LifeCycle(Temporary, _, _)) => shutDownTemporaryActor(this) + case _ => + // eith permanent or none where default is permanent + Actor.log.info("Restarting actor [%s] configured as PERMANENT.", id) + Actor.log.debug("Restarting linked actors for actor [%s].", id) + restartLinkedActors(reason, maxNrOfRetries, withinTimeRange) + Actor.log.debug("Invoking 'preRestart' for failed actor instance [%s].", id) + failedActor.preRestart(reason) + nullOutActorRefReferencesFor(failedActor) + val freshActor = newActor + freshActor.init + freshActor.initTransactionalState + actorInstance.set(freshActor) + Actor.log.debug("Invoking 'postRestart' for new actor instance [%s].", id) + freshActor.postRestart(reason) + _isBeingRestarted = false } } } @@ -1049,14 +1046,9 @@ sealed class LocalActorRef private[akka]( protected[akka] def restartLinkedActors(reason: Throwable, maxNrOfRetries: Int, withinTimeRange: Int) = { linkedActorsAsList.foreach { actorRef => - if (actorRef.lifeCycle.isEmpty) actorRef.lifeCycle = Some(LifeCycle(Permanent)) - actorRef.lifeCycle.get match { - case LifeCycle(scope, _, _) => { - scope match { - case Permanent => actorRef.restart(reason, maxNrOfRetries, withinTimeRange) - case Temporary => shutDownTemporaryActor(actorRef) - } - } + actorRef.lifeCycle match { + case Some(LifeCycle(Temporary, _, _)) => shutDownTemporaryActor(actorRef) + case _ => actorRef.restart(reason, maxNrOfRetries, withinTimeRange) } } } diff --git a/akka-core/src/test/scala/RestartStrategySpec.scala b/akka-core/src/test/scala/RestartStrategySpec.scala index d314cf9388..e7e90b2782 100644 --- a/akka-core/src/test/scala/RestartStrategySpec.scala +++ b/akka-core/src/test/scala/RestartStrategySpec.scala @@ -28,25 +28,26 @@ class RestartStrategySpec extends JUnitSuite { }).start val restartLatch = new StandardLatch - val firstCountDown = new CountDownLatch(2) - val secondCountDown = new CountDownLatch(2) + val secondRestartLatch = new StandardLatch + val countDownLatch = new CountDownLatch(2) val slave = actorOf(new Actor{ - self.lifeCycle = Some(LifeCycle(Permanent)) +// self.lifeCycle = Some(LifeCycle(Permanent)) protected def receive = { - case Ping => { - log.info("png") - if (firstCountDown.getCount > 0) { - firstCountDown.countDown - } else { - secondCountDown.countDown - } - } + case Ping => countDownLatch.countDown case Crash => throw new Exception("Crashing...") } - override def postRestart(reason: Throwable) = restartLatch.open + override def postRestart(reason: Throwable) = { + restartLatch.open + } + + override def shutdown = { + if (restartLatch.isOpen) { + secondRestartLatch.open + } + } }) boss.startLink(slave) @@ -56,16 +57,19 @@ class RestartStrategySpec extends JUnitSuite { // test restart and post restart ping assert(restartLatch.tryAwait(1, TimeUnit.SECONDS)) - assert(firstCountDown.await(1, TimeUnit.SECONDS)) + assert(countDownLatch.await(1, TimeUnit.SECONDS)) // now crash again... should not restart slave ! Crash - slave ! Ping // this should fail - slave ! Ping // this should fail - slave ! Ping // this should fail - slave ! Ping // this should fail - assert(secondCountDown.await(2, TimeUnit.SECONDS) == false) // should not hold + assert(secondRestartLatch.tryAwait(1, TimeUnit.SECONDS)) + val exceptionLatch = new StandardLatch + try { + slave ! Ping // this should fail + } catch { + case e => exceptionLatch.open // expected here + } + assert(exceptionLatch.tryAwait(1, TimeUnit.SECONDS)) } } From 8a2716d640fccca1e28af622bb8484ce421def6e Mon Sep 17 00:00:00 2001 From: momania Date: Fri, 23 Jul 2010 18:02:54 +0200 Subject: [PATCH 055/188] cosmetic --- akka-core/src/main/scala/actor/ActorRef.scala | 7 +++---- akka-core/src/test/scala/RestartStrategySpec.scala | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/akka-core/src/main/scala/actor/ActorRef.scala b/akka-core/src/main/scala/actor/ActorRef.scala index d0b5496a6a..45ff0edd3f 100644 --- a/akka-core/src/main/scala/actor/ActorRef.scala +++ b/akka-core/src/main/scala/actor/ActorRef.scala @@ -979,7 +979,6 @@ sealed class LocalActorRef private[akka]( protected[akka] def handleTrapExit(dead: ActorRef, reason: Throwable): Unit = { if (trapExit.exists(_.isAssignableFrom(reason.getClass))) { faultHandler match { - // FIXME: implement support for maxNrOfRetries and withinTimeRange in RestartStrategy case Some(AllForOneStrategy(maxNrOfRetries, withinTimeRange)) => restartLinkedActors(reason, maxNrOfRetries, withinTimeRange) @@ -1001,9 +1000,7 @@ sealed class LocalActorRef private[akka]( val tooManyRestarts = maxNrOfRetriesCount > maxNrOfRetries val restartingHasExpired = (System.currentTimeMillis - restartsWithinTimeRangeTimestamp) > withinTimeRange - if (tooManyRestarts || restartingHasExpired) { - stop val notification = MaximumNumberOfRestartsWithinTimeRangeReached(this, maxNrOfRetries, withinTimeRange, reason) Actor.log.warning( "Maximum number of restarts [%s] within time range [%s] reached." + @@ -1018,6 +1015,7 @@ sealed class LocalActorRef private[akka]( "No message handler defined for system message [MaximumNumberOfRestartsWithinTimeRangeReached]" + "\n\tCan't send the message to the supervisor [%s].", sup) } + stop } else { _isBeingRestarted = true val failedActor = actorInstance.get @@ -1025,7 +1023,7 @@ sealed class LocalActorRef private[akka]( lifeCycle match { case Some(LifeCycle(Temporary, _, _)) => shutDownTemporaryActor(this) case _ => - // eith permanent or none where default is permanent + // either permanent or none where default is permanent Actor.log.info("Restarting actor [%s] configured as PERMANENT.", id) Actor.log.debug("Restarting linked actors for actor [%s].", id) restartLinkedActors(reason, maxNrOfRetries, withinTimeRange) @@ -1047,6 +1045,7 @@ sealed class LocalActorRef private[akka]( protected[akka] def restartLinkedActors(reason: Throwable, maxNrOfRetries: Int, withinTimeRange: Int) = { linkedActorsAsList.foreach { actorRef => actorRef.lifeCycle match { + // either permanent or none where default is permanent case Some(LifeCycle(Temporary, _, _)) => shutDownTemporaryActor(actorRef) case _ => actorRef.restart(reason, maxNrOfRetries, withinTimeRange) } diff --git a/akka-core/src/test/scala/RestartStrategySpec.scala b/akka-core/src/test/scala/RestartStrategySpec.scala index e7e90b2782..5023c756e1 100644 --- a/akka-core/src/test/scala/RestartStrategySpec.scala +++ b/akka-core/src/test/scala/RestartStrategySpec.scala @@ -33,7 +33,6 @@ class RestartStrategySpec extends JUnitSuite { val slave = actorOf(new Actor{ -// self.lifeCycle = Some(LifeCycle(Permanent)) protected def receive = { case Ping => countDownLatch.countDown From 2c3431ac9161f4f03dbdaef8393c967b655fdb51 Mon Sep 17 00:00:00 2001 From: momania Date: Fri, 23 Jul 2010 19:06:53 +0200 Subject: [PATCH 056/188] clean end state --- akka-core/src/test/scala/SchedulerSpec.scala | 74 ++++++++++---------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/akka-core/src/test/scala/SchedulerSpec.scala b/akka-core/src/test/scala/SchedulerSpec.scala index 7db5727834..08be87d728 100644 --- a/akka-core/src/test/scala/SchedulerSpec.scala +++ b/akka-core/src/test/scala/SchedulerSpec.scala @@ -3,12 +3,20 @@ package se.scalablesolutions.akka.actor import org.scalatest.junit.JUnitSuite import Actor._ import java.util.concurrent.{CountDownLatch, TimeUnit} -import org.junit.Test import se.scalablesolutions.akka.config.ScalaConfig._ import org.multiverse.api.latches.StandardLatch +import org.junit.Test class SchedulerSpec extends JUnitSuite { - @Test def schedulerShouldScheduleMoreThanOnce = { + + def withCleanEndState(action: => Unit) { + action + Scheduler.restart + ActorRegistry.shutdownAll + } + + + @Test def schedulerShouldScheduleMoreThanOnce = withCleanEndState { case object Tick val countDownLatch = new CountDownLatch(3) @@ -22,7 +30,7 @@ class SchedulerSpec extends JUnitSuite { assert(countDownLatch.await(1, TimeUnit.SECONDS)) } - @Test def schedulerShouldScheduleOnce = { + @Test def schedulerShouldScheduleOnce = withCleanEndState { case object Tick val countDownLatch = new CountDownLatch(2) val tickActor = actor { @@ -40,46 +48,40 @@ class SchedulerSpec extends JUnitSuite { /** * ticket #307 */ - @Test def actorRestartShouldPickUpScheduleAgain = { + @Test def actorRestartShouldPickUpScheduleAgain = withCleanEndState { - try { - object Ping - object Crash + object Ping + object Crash - val restartLatch = new StandardLatch - val pingLatch = new CountDownLatch(4) + val restartLatch = new StandardLatch + val pingLatch = new CountDownLatch(6) - val actor = actorOf(new Actor { - self.lifeCycle = Some(LifeCycle(Permanent)) + val actor = actorOf(new Actor { + self.lifeCycle = Some(LifeCycle(Permanent)) - def receive = { - case Ping => pingLatch.countDown - case Crash => throw new Exception("CRASH") - } + def receive = { + case Ping => pingLatch.countDown + case Crash => throw new Exception("CRASH") + } - override def postRestart(reason: Throwable) = restartLatch.open - }) + override def postRestart(reason: Throwable) = restartLatch.open + }) - Supervisor( - SupervisorConfig( - RestartStrategy(AllForOne, 3, 1000, - List(classOf[Exception])), - Supervise( - actor, - LifeCycle(Permanent)) - :: Nil)).start + Supervisor( + SupervisorConfig( + RestartStrategy(AllForOne, 3, 1000, + List(classOf[Exception])), + Supervise( + actor, + LifeCycle(Permanent)) + :: Nil)).start - Scheduler.schedule(actor, Ping, 500, 500, TimeUnit.MILLISECONDS) - // appx 2 pings before crash - Scheduler.scheduleOnce(actor, Crash, 1000, TimeUnit.MILLISECONDS) + Scheduler.schedule(actor, Ping, 500, 500, TimeUnit.MILLISECONDS) + // appx 2 pings before crash + Scheduler.scheduleOnce(actor, Crash, 1000, TimeUnit.MILLISECONDS) - assert(restartLatch.tryAwait(4, TimeUnit.SECONDS)) - // should be enough time for the ping countdown to recover and reach 4 pings - assert(pingLatch.await(4, TimeUnit.SECONDS)) - - } finally { - - Scheduler.shutdown - } + assert(restartLatch.tryAwait(2, TimeUnit.SECONDS)) + // should be enough time for the ping countdown to recover and reach 6 pings + assert(pingLatch.await(4, TimeUnit.SECONDS)) } } From ff52aa91d76523ddbfd4141b164b05f3f4499206 Mon Sep 17 00:00:00 2001 From: momania Date: Fri, 23 Jul 2010 20:52:33 +0200 Subject: [PATCH 057/188] re-arranged tests into folders/packages --- akka-core/src/test/scala/Messages.scala | 2 +- .../{ => actor}/ActiveObjectContextSpec.scala | 1 - .../ActiveObjectGuiceConfiguratorSpec.scala | 2 -- .../{ => actor}/ActiveObjectLifecycleSpec.scala | 0 .../ActorFireForgetRequestReplySpec.scala | 0 .../ActorObjectUtilFunctionsSpec.scala | 2 +- .../scala/{ => actor}/ActorRegistrySpec.scala | 0 .../src/test/scala/{ => actor}/AgentSpec.scala | 4 ---- akka-core/src/test/scala/{ => actor}/Bench.scala | 0 ...isedNestedTransactionalActiveObjectSpec.scala | 3 --- ...SupervisedTransactionalActiveObjectSpec.scala | 3 --- .../scala/{ => actor}/ForwardActorSpec.scala | 0 .../src/test/scala/{ => actor}/FutureSpec.scala | 0 .../scala/{ => actor}/ReceiveTimeoutSpec.scala | 4 ++-- .../test/scala/{ => actor}/SchedulerSpec.scala | 2 +- .../{ => actor}/SupervisorHierarchySpec.scala | 0 .../test/scala/{ => actor}/SupervisorSpec.scala | 1 - .../test/scala/{ => actor}/TransactorSpec.scala | 0 ...utorBasedEventDrivenDispatcherActorSpec.scala | 3 ++- ...torBasedEventDrivenDispatcherActorsSpec.scala | 4 ++-- ...edEventDrivenWorkStealingDispatcherSpec.scala | 5 +++-- ...gleThreadEventDrivenDispatcherActorSpec.scala | 5 +++-- ...hreadPoolEventDrivenDispatcherActorSpec.scala | 3 ++- .../{ => dispatch}/ThreadBasedActorSpec.scala | 3 ++- .../ThreadBasedDispatcherSpec.scala | 0 .../ClientInitiatedRemoteActorSpec.scala | 5 ++--- .../{ => remote}/RemoteSupervisorSpec.scala | 11 ++++------- .../RemoteTransactionalActiveObjectSpec.scala | 7 ++----- .../ServerInitiatedRemoteActorSample.scala | 2 +- .../ServerInitiatedRemoteActorSpec.scala | 16 +++++++--------- .../test/scala/{ => remote}/ShutdownSpec.scala | 0 .../test/scala/{ => routing}/RoutingSpec.scala | 10 ++++------ .../ProtobufActorMessageSerializationSpec.scala | 7 +++---- .../SerializableTypeClassActorSpec.scala | 7 +++---- .../{ => serialization}/SerializerSpec.scala | 4 +--- akka-core/src/test/scala/{ => stm}/RefSpec.scala | 6 +++--- akka-core/src/test/scala/{ => stm}/StmSpec.scala | 7 +++---- .../src/test/scala/tickets/Proof001Spec.scala | 10 ++++++++++ 38 files changed, 62 insertions(+), 77 deletions(-) rename akka-core/src/test/scala/{ => actor}/ActiveObjectContextSpec.scala (97%) rename akka-core/src/test/scala/{ => actor}/ActiveObjectGuiceConfiguratorSpec.scala (97%) rename akka-core/src/test/scala/{ => actor}/ActiveObjectLifecycleSpec.scala (100%) rename akka-core/src/test/scala/{ => actor}/ActorFireForgetRequestReplySpec.scala (100%) rename akka-core/src/test/scala/{ => actor}/ActorObjectUtilFunctionsSpec.scala (93%) rename akka-core/src/test/scala/{ => actor}/ActorRegistrySpec.scala (100%) rename akka-core/src/test/scala/{ => actor}/AgentSpec.scala (95%) rename akka-core/src/test/scala/{ => actor}/Bench.scala (100%) rename akka-core/src/test/scala/{ => actor}/DeclarativelySupervisedNestedTransactionalActiveObjectSpec.scala (98%) rename akka-core/src/test/scala/{ => actor}/DeclarativelySupervisedTransactionalActiveObjectSpec.scala (97%) rename akka-core/src/test/scala/{ => actor}/ForwardActorSpec.scala (100%) rename akka-core/src/test/scala/{ => actor}/FutureSpec.scala (100%) rename akka-core/src/test/scala/{ => actor}/ReceiveTimeoutSpec.scala (99%) rename akka-core/src/test/scala/{ => actor}/SchedulerSpec.scala (99%) rename akka-core/src/test/scala/{ => actor}/SupervisorHierarchySpec.scala (100%) rename akka-core/src/test/scala/{ => actor}/SupervisorSpec.scala (99%) rename akka-core/src/test/scala/{ => actor}/TransactorSpec.scala (100%) rename akka-core/src/test/scala/{ => dispatch}/ExecutorBasedEventDrivenDispatcherActorSpec.scala (95%) rename akka-core/src/test/scala/{ => dispatch}/ExecutorBasedEventDrivenDispatcherActorsSpec.scala (93%) rename akka-core/src/test/scala/{ => dispatch}/ExecutorBasedEventDrivenWorkStealingDispatcherSpec.scala (95%) rename akka-core/src/test/scala/{ => dispatch}/ReactorBasedSingleThreadEventDrivenDispatcherActorSpec.scala (95%) rename akka-core/src/test/scala/{ => dispatch}/ReactorBasedThreadPoolEventDrivenDispatcherActorSpec.scala (95%) rename akka-core/src/test/scala/{ => dispatch}/ThreadBasedActorSpec.scala (94%) rename akka-core/src/test/scala/{ => dispatch}/ThreadBasedDispatcherSpec.scala (100%) rename akka-core/src/test/scala/{ => remote}/ClientInitiatedRemoteActorSpec.scala (97%) rename akka-core/src/test/scala/{ => remote}/RemoteSupervisorSpec.scala (98%) rename akka-core/src/test/scala/{ => remote}/RemoteTransactionalActiveObjectSpec.scala (96%) rename akka-core/src/test/scala/{ => remote}/ServerInitiatedRemoteActorSample.scala (94%) rename akka-core/src/test/scala/{ => remote}/ServerInitiatedRemoteActorSpec.scala (84%) rename akka-core/src/test/scala/{ => remote}/ShutdownSpec.scala (100%) rename akka-core/src/test/scala/{ => routing}/RoutingSpec.scala (96%) rename akka-core/src/test/scala/{ => serialization}/ProtobufActorMessageSerializationSpec.scala (91%) rename akka-core/src/test/scala/{ => serialization}/SerializableTypeClassActorSpec.scala (98%) rename akka-core/src/test/scala/{ => serialization}/SerializerSpec.scala (93%) rename akka-core/src/test/scala/{ => stm}/RefSpec.scala (97%) rename akka-core/src/test/scala/{ => stm}/StmSpec.scala (96%) create mode 100644 akka-core/src/test/scala/tickets/Proof001Spec.scala diff --git a/akka-core/src/test/scala/Messages.scala b/akka-core/src/test/scala/Messages.scala index 436257e3b5..ad1fcf8885 100644 --- a/akka-core/src/test/scala/Messages.scala +++ b/akka-core/src/test/scala/Messages.scala @@ -7,9 +7,9 @@ package se.scalablesolutions.akka import se.scalablesolutions.akka.serialization.Serializable import sbinary._ import sbinary.Operations._ -import sbinary.DefaultProtocol._ sealed abstract class TestMessage + case object Ping extends TestMessage case object Pong extends TestMessage case object OneWay extends TestMessage diff --git a/akka-core/src/test/scala/ActiveObjectContextSpec.scala b/akka-core/src/test/scala/actor/ActiveObjectContextSpec.scala similarity index 97% rename from akka-core/src/test/scala/ActiveObjectContextSpec.scala rename to akka-core/src/test/scala/actor/ActiveObjectContextSpec.scala index 5a54f0a505..62b9962ac2 100644 --- a/akka-core/src/test/scala/ActiveObjectContextSpec.scala +++ b/akka-core/src/test/scala/actor/ActiveObjectContextSpec.scala @@ -5,7 +5,6 @@ package se.scalablesolutions.akka.actor import org.scalatest.Spec -import org.scalatest.Assertions import org.scalatest.matchers.ShouldMatchers import org.scalatest.BeforeAndAfterAll import org.scalatest.junit.JUnitRunner diff --git a/akka-core/src/test/scala/ActiveObjectGuiceConfiguratorSpec.scala b/akka-core/src/test/scala/actor/ActiveObjectGuiceConfiguratorSpec.scala similarity index 97% rename from akka-core/src/test/scala/ActiveObjectGuiceConfiguratorSpec.scala rename to akka-core/src/test/scala/actor/ActiveObjectGuiceConfiguratorSpec.scala index 3cb871d0d8..178d16f8d4 100644 --- a/akka-core/src/test/scala/ActiveObjectGuiceConfiguratorSpec.scala +++ b/akka-core/src/test/scala/actor/ActiveObjectGuiceConfiguratorSpec.scala @@ -8,7 +8,6 @@ import com.google.inject.AbstractModule import com.google.inject.Scopes import org.scalatest.Spec -import org.scalatest.Assertions import org.scalatest.matchers.ShouldMatchers import org.scalatest.BeforeAndAfterAll import org.scalatest.junit.JUnitRunner @@ -18,7 +17,6 @@ import se.scalablesolutions.akka.config.Config import se.scalablesolutions.akka.config.ActiveObjectConfigurator import se.scalablesolutions.akka.config.JavaConfig._ import se.scalablesolutions.akka.dispatch._ -import se.scalablesolutions.akka.dispatch.FutureTimeoutException @RunWith(classOf[JUnitRunner]) class ActiveObjectGuiceConfiguratorSpec extends diff --git a/akka-core/src/test/scala/ActiveObjectLifecycleSpec.scala b/akka-core/src/test/scala/actor/ActiveObjectLifecycleSpec.scala similarity index 100% rename from akka-core/src/test/scala/ActiveObjectLifecycleSpec.scala rename to akka-core/src/test/scala/actor/ActiveObjectLifecycleSpec.scala diff --git a/akka-core/src/test/scala/ActorFireForgetRequestReplySpec.scala b/akka-core/src/test/scala/actor/ActorFireForgetRequestReplySpec.scala similarity index 100% rename from akka-core/src/test/scala/ActorFireForgetRequestReplySpec.scala rename to akka-core/src/test/scala/actor/ActorFireForgetRequestReplySpec.scala diff --git a/akka-core/src/test/scala/ActorObjectUtilFunctionsSpec.scala b/akka-core/src/test/scala/actor/ActorObjectUtilFunctionsSpec.scala similarity index 93% rename from akka-core/src/test/scala/ActorObjectUtilFunctionsSpec.scala rename to akka-core/src/test/scala/actor/ActorObjectUtilFunctionsSpec.scala index 48424f3c17..3c540f02ab 100644 --- a/akka-core/src/test/scala/ActorObjectUtilFunctionsSpec.scala +++ b/akka-core/src/test/scala/actor/ActorObjectUtilFunctionsSpec.scala @@ -4,7 +4,7 @@ import org.scalatest.Suite import org.junit.runner.RunWith import org.scalatest.junit.JUnitRunner import org.scalatest.matchers.MustMatchers -import org.junit.{Before, After, Test} +import org.junit.Test import java.util.concurrent.{ CountDownLatch, TimeUnit } @RunWith(classOf[JUnitRunner]) diff --git a/akka-core/src/test/scala/ActorRegistrySpec.scala b/akka-core/src/test/scala/actor/ActorRegistrySpec.scala similarity index 100% rename from akka-core/src/test/scala/ActorRegistrySpec.scala rename to akka-core/src/test/scala/actor/ActorRegistrySpec.scala diff --git a/akka-core/src/test/scala/AgentSpec.scala b/akka-core/src/test/scala/actor/AgentSpec.scala similarity index 95% rename from akka-core/src/test/scala/AgentSpec.scala rename to akka-core/src/test/scala/actor/AgentSpec.scala index de4326c646..71911c3ad8 100644 --- a/akka-core/src/test/scala/AgentSpec.scala +++ b/akka-core/src/test/scala/actor/AgentSpec.scala @@ -1,10 +1,6 @@ package se.scalablesolutions.akka.actor import se.scalablesolutions.akka.actor.Actor.transactor -import se.scalablesolutions.akka.stm.Transaction.Global.atomic -import se.scalablesolutions.akka.util.Logging -import Actor._ - import org.scalatest.Suite import org.scalatest.junit.JUnitRunner import org.scalatest.matchers.MustMatchers diff --git a/akka-core/src/test/scala/Bench.scala b/akka-core/src/test/scala/actor/Bench.scala similarity index 100% rename from akka-core/src/test/scala/Bench.scala rename to akka-core/src/test/scala/actor/Bench.scala diff --git a/akka-core/src/test/scala/DeclarativelySupervisedNestedTransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/actor/DeclarativelySupervisedNestedTransactionalActiveObjectSpec.scala similarity index 98% rename from akka-core/src/test/scala/DeclarativelySupervisedNestedTransactionalActiveObjectSpec.scala rename to akka-core/src/test/scala/actor/DeclarativelySupervisedNestedTransactionalActiveObjectSpec.scala index ea244bf966..07da09edad 100644 --- a/akka-core/src/test/scala/DeclarativelySupervisedNestedTransactionalActiveObjectSpec.scala +++ b/akka-core/src/test/scala/actor/DeclarativelySupervisedNestedTransactionalActiveObjectSpec.scala @@ -5,17 +5,14 @@ package se.scalablesolutions.akka.actor import org.scalatest.Spec -import org.scalatest.Assertions import org.scalatest.matchers.ShouldMatchers import org.scalatest.BeforeAndAfterAll import org.scalatest.junit.JUnitRunner import org.junit.runner.RunWith import se.scalablesolutions.akka.config.Config -import se.scalablesolutions.akka.config._ import se.scalablesolutions.akka.config.ActiveObjectConfigurator import se.scalablesolutions.akka.config.JavaConfig._ -import se.scalablesolutions.akka.actor._ @RunWith(classOf[JUnitRunner]) class DeclarativelySupervisedNestedTransactionalActiveObjectSpec extends diff --git a/akka-core/src/test/scala/DeclarativelySupervisedTransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/actor/DeclarativelySupervisedTransactionalActiveObjectSpec.scala similarity index 97% rename from akka-core/src/test/scala/DeclarativelySupervisedTransactionalActiveObjectSpec.scala rename to akka-core/src/test/scala/actor/DeclarativelySupervisedTransactionalActiveObjectSpec.scala index 95d7b8e5df..07bb52a890 100644 --- a/akka-core/src/test/scala/DeclarativelySupervisedTransactionalActiveObjectSpec.scala +++ b/akka-core/src/test/scala/actor/DeclarativelySupervisedTransactionalActiveObjectSpec.scala @@ -5,17 +5,14 @@ package se.scalablesolutions.akka.actor import org.scalatest.Spec -import org.scalatest.Assertions import org.scalatest.matchers.ShouldMatchers import org.scalatest.BeforeAndAfterAll import org.scalatest.junit.JUnitRunner import org.junit.runner.RunWith import se.scalablesolutions.akka.config.Config -import se.scalablesolutions.akka.config._ import se.scalablesolutions.akka.config.ActiveObjectConfigurator import se.scalablesolutions.akka.config.JavaConfig._ -import se.scalablesolutions.akka.actor._ @RunWith(classOf[JUnitRunner]) class DeclarativelySupervisedTransactionalActiveObjectSpec extends diff --git a/akka-core/src/test/scala/ForwardActorSpec.scala b/akka-core/src/test/scala/actor/ForwardActorSpec.scala similarity index 100% rename from akka-core/src/test/scala/ForwardActorSpec.scala rename to akka-core/src/test/scala/actor/ForwardActorSpec.scala diff --git a/akka-core/src/test/scala/FutureSpec.scala b/akka-core/src/test/scala/actor/FutureSpec.scala similarity index 100% rename from akka-core/src/test/scala/FutureSpec.scala rename to akka-core/src/test/scala/actor/FutureSpec.scala diff --git a/akka-core/src/test/scala/ReceiveTimeoutSpec.scala b/akka-core/src/test/scala/actor/ReceiveTimeoutSpec.scala similarity index 99% rename from akka-core/src/test/scala/ReceiveTimeoutSpec.scala rename to akka-core/src/test/scala/actor/ReceiveTimeoutSpec.scala index 5c50337894..248cbcbcab 100644 --- a/akka-core/src/test/scala/ReceiveTimeoutSpec.scala +++ b/akka-core/src/test/scala/actor/ReceiveTimeoutSpec.scala @@ -3,9 +3,9 @@ package se.scalablesolutions.akka.actor import org.scalatest.junit.JUnitSuite import org.junit.Test -import Actor._ import java.util.concurrent.TimeUnit import org.multiverse.api.latches.StandardLatch +import Actor._ class ReceiveTimeoutSpec extends JUnitSuite { @@ -74,4 +74,4 @@ class ReceiveTimeoutSpec extends JUnitSuite { assert(timeoutLatch.tryAwait(1, TimeUnit.SECONDS) == false) } -} +} \ No newline at end of file diff --git a/akka-core/src/test/scala/SchedulerSpec.scala b/akka-core/src/test/scala/actor/SchedulerSpec.scala similarity index 99% rename from akka-core/src/test/scala/SchedulerSpec.scala rename to akka-core/src/test/scala/actor/SchedulerSpec.scala index 08be87d728..b7e9b63b0b 100644 --- a/akka-core/src/test/scala/SchedulerSpec.scala +++ b/akka-core/src/test/scala/actor/SchedulerSpec.scala @@ -84,4 +84,4 @@ class SchedulerSpec extends JUnitSuite { // should be enough time for the ping countdown to recover and reach 6 pings assert(pingLatch.await(4, TimeUnit.SECONDS)) } -} +} \ No newline at end of file diff --git a/akka-core/src/test/scala/SupervisorHierarchySpec.scala b/akka-core/src/test/scala/actor/SupervisorHierarchySpec.scala similarity index 100% rename from akka-core/src/test/scala/SupervisorHierarchySpec.scala rename to akka-core/src/test/scala/actor/SupervisorHierarchySpec.scala diff --git a/akka-core/src/test/scala/SupervisorSpec.scala b/akka-core/src/test/scala/actor/SupervisorSpec.scala similarity index 99% rename from akka-core/src/test/scala/SupervisorSpec.scala rename to akka-core/src/test/scala/actor/SupervisorSpec.scala index fcbedd476b..01eb9cb006 100644 --- a/akka-core/src/test/scala/SupervisorSpec.scala +++ b/akka-core/src/test/scala/actor/SupervisorSpec.scala @@ -6,7 +6,6 @@ package se.scalablesolutions.akka.actor import se.scalablesolutions.akka.config.ScalaConfig._ import se.scalablesolutions.akka.config.OneForOneStrategy -import se.scalablesolutions.akka.dispatch.Dispatchers import se.scalablesolutions.akka.{OneWay, Die, Ping} import Actor._ diff --git a/akka-core/src/test/scala/TransactorSpec.scala b/akka-core/src/test/scala/actor/TransactorSpec.scala similarity index 100% rename from akka-core/src/test/scala/TransactorSpec.scala rename to akka-core/src/test/scala/actor/TransactorSpec.scala diff --git a/akka-core/src/test/scala/ExecutorBasedEventDrivenDispatcherActorSpec.scala b/akka-core/src/test/scala/dispatch/ExecutorBasedEventDrivenDispatcherActorSpec.scala similarity index 95% rename from akka-core/src/test/scala/ExecutorBasedEventDrivenDispatcherActorSpec.scala rename to akka-core/src/test/scala/dispatch/ExecutorBasedEventDrivenDispatcherActorSpec.scala index b25a02db5e..9cdf43682e 100644 --- a/akka-core/src/test/scala/ExecutorBasedEventDrivenDispatcherActorSpec.scala +++ b/akka-core/src/test/scala/dispatch/ExecutorBasedEventDrivenDispatcherActorSpec.scala @@ -1,9 +1,10 @@ -package se.scalablesolutions.akka.actor +package se.scalablesolutions.akka.actor.dispatch import java.util.concurrent.{CountDownLatch, TimeUnit} import org.scalatest.junit.JUnitSuite import org.junit.Test import se.scalablesolutions.akka.dispatch.Dispatchers +import se.scalablesolutions.akka.actor.Actor import Actor._ object ExecutorBasedEventDrivenDispatcherActorSpec { diff --git a/akka-core/src/test/scala/ExecutorBasedEventDrivenDispatcherActorsSpec.scala b/akka-core/src/test/scala/dispatch/ExecutorBasedEventDrivenDispatcherActorsSpec.scala similarity index 93% rename from akka-core/src/test/scala/ExecutorBasedEventDrivenDispatcherActorsSpec.scala rename to akka-core/src/test/scala/dispatch/ExecutorBasedEventDrivenDispatcherActorsSpec.scala index b2c9cf4422..fc8f1aa37f 100644 --- a/akka-core/src/test/scala/ExecutorBasedEventDrivenDispatcherActorsSpec.scala +++ b/akka-core/src/test/scala/dispatch/ExecutorBasedEventDrivenDispatcherActorsSpec.scala @@ -1,10 +1,10 @@ -package se.scalablesolutions.akka.actor +package se.scalablesolutions.akka.actor.dispatch import org.scalatest.junit.JUnitSuite import org.junit.Test -import se.scalablesolutions.akka.dispatch.Dispatchers import org.scalatest.matchers.MustMatchers import java.util.concurrent.CountDownLatch +import se.scalablesolutions.akka.actor.Actor import Actor._ /** diff --git a/akka-core/src/test/scala/ExecutorBasedEventDrivenWorkStealingDispatcherSpec.scala b/akka-core/src/test/scala/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcherSpec.scala similarity index 95% rename from akka-core/src/test/scala/ExecutorBasedEventDrivenWorkStealingDispatcherSpec.scala rename to akka-core/src/test/scala/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcherSpec.scala index 8ad3e3f212..cde57a0544 100644 --- a/akka-core/src/test/scala/ExecutorBasedEventDrivenWorkStealingDispatcherSpec.scala +++ b/akka-core/src/test/scala/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcherSpec.scala @@ -1,4 +1,4 @@ -package se.scalablesolutions.akka.actor +package se.scalablesolutions.akka.actor.dispatch import org.scalatest.matchers.MustMatchers import org.scalatest.junit.JUnitSuite @@ -6,9 +6,10 @@ import org.scalatest.junit.JUnitSuite import org.junit.Test import se.scalablesolutions.akka.dispatch.Dispatchers -import Actor._ import java.util.concurrent.{TimeUnit, CountDownLatch} +import se.scalablesolutions.akka.actor.{IllegalActorStateException, Actor} +import Actor._ object ExecutorBasedEventDrivenWorkStealingDispatcherSpec { val delayableActorDispatcher = Dispatchers.newExecutorBasedEventDrivenWorkStealingDispatcher("pooled-dispatcher") diff --git a/akka-core/src/test/scala/ReactorBasedSingleThreadEventDrivenDispatcherActorSpec.scala b/akka-core/src/test/scala/dispatch/ReactorBasedSingleThreadEventDrivenDispatcherActorSpec.scala similarity index 95% rename from akka-core/src/test/scala/ReactorBasedSingleThreadEventDrivenDispatcherActorSpec.scala rename to akka-core/src/test/scala/dispatch/ReactorBasedSingleThreadEventDrivenDispatcherActorSpec.scala index a84cdfc8e5..de9b912bf5 100644 --- a/akka-core/src/test/scala/ReactorBasedSingleThreadEventDrivenDispatcherActorSpec.scala +++ b/akka-core/src/test/scala/dispatch/ReactorBasedSingleThreadEventDrivenDispatcherActorSpec.scala @@ -1,11 +1,12 @@ -package se.scalablesolutions.akka.actor +package se.scalablesolutions.akka.actor.dispatch import java.util.concurrent.{CountDownLatch, TimeUnit} import org.scalatest.junit.JUnitSuite import org.junit.Test -import Actor._ import se.scalablesolutions.akka.dispatch.Dispatchers +import se.scalablesolutions.akka.actor.Actor +import Actor._ object ReactorBasedSingleThreadEventDrivenDispatcherActorSpec { class TestActor extends Actor { diff --git a/akka-core/src/test/scala/ReactorBasedThreadPoolEventDrivenDispatcherActorSpec.scala b/akka-core/src/test/scala/dispatch/ReactorBasedThreadPoolEventDrivenDispatcherActorSpec.scala similarity index 95% rename from akka-core/src/test/scala/ReactorBasedThreadPoolEventDrivenDispatcherActorSpec.scala rename to akka-core/src/test/scala/dispatch/ReactorBasedThreadPoolEventDrivenDispatcherActorSpec.scala index f917b462b5..4001df8f56 100644 --- a/akka-core/src/test/scala/ReactorBasedThreadPoolEventDrivenDispatcherActorSpec.scala +++ b/akka-core/src/test/scala/dispatch/ReactorBasedThreadPoolEventDrivenDispatcherActorSpec.scala @@ -1,10 +1,11 @@ -package se.scalablesolutions.akka.actor +package se.scalablesolutions.akka.actor.dispatch import java.util.concurrent.{CountDownLatch, TimeUnit} import org.scalatest.junit.JUnitSuite import org.junit.Test import se.scalablesolutions.akka.dispatch.Dispatchers +import se.scalablesolutions.akka.actor.Actor import Actor._ object ReactorBasedThreadPoolEventDrivenDispatcherActorSpec { diff --git a/akka-core/src/test/scala/ThreadBasedActorSpec.scala b/akka-core/src/test/scala/dispatch/ThreadBasedActorSpec.scala similarity index 94% rename from akka-core/src/test/scala/ThreadBasedActorSpec.scala rename to akka-core/src/test/scala/dispatch/ThreadBasedActorSpec.scala index fc726ecf49..d69ee984d8 100644 --- a/akka-core/src/test/scala/ThreadBasedActorSpec.scala +++ b/akka-core/src/test/scala/dispatch/ThreadBasedActorSpec.scala @@ -1,10 +1,11 @@ -package se.scalablesolutions.akka.actor +package se.scalablesolutions.akka.actor.dispatch import java.util.concurrent.{CountDownLatch, TimeUnit} import org.scalatest.junit.JUnitSuite import org.junit.Test import se.scalablesolutions.akka.dispatch.Dispatchers +import se.scalablesolutions.akka.actor.Actor import Actor._ object ThreadBasedActorSpec { diff --git a/akka-core/src/test/scala/ThreadBasedDispatcherSpec.scala b/akka-core/src/test/scala/dispatch/ThreadBasedDispatcherSpec.scala similarity index 100% rename from akka-core/src/test/scala/ThreadBasedDispatcherSpec.scala rename to akka-core/src/test/scala/dispatch/ThreadBasedDispatcherSpec.scala diff --git a/akka-core/src/test/scala/ClientInitiatedRemoteActorSpec.scala b/akka-core/src/test/scala/remote/ClientInitiatedRemoteActorSpec.scala similarity index 97% rename from akka-core/src/test/scala/ClientInitiatedRemoteActorSpec.scala rename to akka-core/src/test/scala/remote/ClientInitiatedRemoteActorSpec.scala index ea48d45252..e9ed8d4fa5 100644 --- a/akka-core/src/test/scala/ClientInitiatedRemoteActorSpec.scala +++ b/akka-core/src/test/scala/remote/ClientInitiatedRemoteActorSpec.scala @@ -1,13 +1,12 @@ -package se.scalablesolutions.akka.actor +package se.scalablesolutions.akka.actor.remote import java.util.concurrent.{CountDownLatch, TimeUnit} -import junit.framework.TestCase - import org.scalatest.junit.JUnitSuite import org.junit.{Test, Before, After} import se.scalablesolutions.akka.remote.{RemoteServer, RemoteClient} import se.scalablesolutions.akka.dispatch.Dispatchers +import se.scalablesolutions.akka.actor.{ActorRef, Actor} import Actor._ case class Send(actor: Actor) diff --git a/akka-core/src/test/scala/RemoteSupervisorSpec.scala b/akka-core/src/test/scala/remote/RemoteSupervisorSpec.scala similarity index 98% rename from akka-core/src/test/scala/RemoteSupervisorSpec.scala rename to akka-core/src/test/scala/remote/RemoteSupervisorSpec.scala index 10f8c3bcf9..936d1cf5c4 100644 --- a/akka-core/src/test/scala/RemoteSupervisorSpec.scala +++ b/akka-core/src/test/scala/remote/RemoteSupervisorSpec.scala @@ -2,20 +2,17 @@ * Copyright (C) 2009-2010 Scalable Solutions AB */ -package se.scalablesolutions.akka.actor +package se.scalablesolutions.akka.actor.remote import java.util.concurrent.{LinkedBlockingQueue, TimeUnit, BlockingQueue} import se.scalablesolutions.akka.serialization.BinaryString import se.scalablesolutions.akka.config.ScalaConfig._ -import se.scalablesolutions.akka.config.Config -import se.scalablesolutions.akka.remote.{RemoteNode, RemoteServer, RemoteClient} +import se.scalablesolutions.akka.remote.{RemoteServer, RemoteClient} import se.scalablesolutions.akka.OneWay -import se.scalablesolutions.akka.dispatch.Dispatchers -import Actor._ - import org.scalatest.junit.JUnitSuite -import org.junit.Test import org.junit.{Test, Before, After} +import se.scalablesolutions.akka.actor.{SupervisorFactory, Supervisor, ActorRef, Actor} +import Actor._ object Log { val messageLog: BlockingQueue[String] = new LinkedBlockingQueue[String] diff --git a/akka-core/src/test/scala/RemoteTransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/remote/RemoteTransactionalActiveObjectSpec.scala similarity index 96% rename from akka-core/src/test/scala/RemoteTransactionalActiveObjectSpec.scala rename to akka-core/src/test/scala/remote/RemoteTransactionalActiveObjectSpec.scala index 897318ce7d..21fadb14ac 100644 --- a/akka-core/src/test/scala/RemoteTransactionalActiveObjectSpec.scala +++ b/akka-core/src/test/scala/remote/RemoteTransactionalActiveObjectSpec.scala @@ -2,19 +2,16 @@ * Copyright (C) 2009-2010 Scalable Solutions AB */ -package se.scalablesolutions.akka.actor +package se.scalablesolutions.akka.actor.remote import org.scalatest.Spec -import org.scalatest.Assertions import org.scalatest.matchers.ShouldMatchers import org.scalatest.BeforeAndAfterAll import org.scalatest.junit.JUnitRunner import org.junit.runner.RunWith -import org.junit.{Test, Before, After} - import se.scalablesolutions.akka.config.Config import se.scalablesolutions.akka.config.ActiveObjectConfigurator -import se.scalablesolutions.akka.remote.{RemoteNode, RemoteServer, RemoteClient} +import se.scalablesolutions.akka.remote.{RemoteServer, RemoteClient} object RemoteTransactionalActiveObjectSpec { val HOSTNAME = "localhost" diff --git a/akka-core/src/test/scala/ServerInitiatedRemoteActorSample.scala b/akka-core/src/test/scala/remote/ServerInitiatedRemoteActorSample.scala similarity index 94% rename from akka-core/src/test/scala/ServerInitiatedRemoteActorSample.scala rename to akka-core/src/test/scala/remote/ServerInitiatedRemoteActorSample.scala index dad54e6d3a..b9b8946bee 100644 --- a/akka-core/src/test/scala/ServerInitiatedRemoteActorSample.scala +++ b/akka-core/src/test/scala/remote/ServerInitiatedRemoteActorSample.scala @@ -1,4 +1,4 @@ -package sample +package se.scalablesolutions.akka.actor.remote import se.scalablesolutions.akka.actor.Actor import se.scalablesolutions.akka.remote.{RemoteClient, RemoteNode} diff --git a/akka-core/src/test/scala/ServerInitiatedRemoteActorSpec.scala b/akka-core/src/test/scala/remote/ServerInitiatedRemoteActorSpec.scala similarity index 84% rename from akka-core/src/test/scala/ServerInitiatedRemoteActorSpec.scala rename to akka-core/src/test/scala/remote/ServerInitiatedRemoteActorSpec.scala index 51685a0073..59cfe3778d 100644 --- a/akka-core/src/test/scala/ServerInitiatedRemoteActorSpec.scala +++ b/akka-core/src/test/scala/remote/ServerInitiatedRemoteActorSpec.scala @@ -1,12 +1,12 @@ -package se.scalablesolutions.akka.actor +package se.scalablesolutions.akka.actor.remote import java.util.concurrent.{CountDownLatch, TimeUnit} import org.scalatest.junit.JUnitSuite import org.junit.{Test, Before, After} -import Actor._ import se.scalablesolutions.akka.remote.{RemoteServer, RemoteClient} -import se.scalablesolutions.akka.dispatch.Dispatchers +import se.scalablesolutions.akka.actor.{ActorRef, Actor} +import Actor._ object ServerInitiatedRemoteActorSpec { val HOSTNAME = "localhost" @@ -52,8 +52,6 @@ object ServerInitiatedRemoteActorSpec { class ServerInitiatedRemoteActorSpec extends JUnitSuite { import ServerInitiatedRemoteActorSpec._ - import se.scalablesolutions.akka.config.Config.config - private val unit = TimeUnit.MILLISECONDS @Before @@ -84,7 +82,7 @@ class ServerInitiatedRemoteActorSpec extends JUnitSuite { @Test def shouldSendWithBang { val actor = RemoteClient.actorFor( - "se.scalablesolutions.akka.actor.ServerInitiatedRemoteActorSpec$RemoteActorSpecActorUnidirectional", + "se.scalablesolutions.akka.actor.remote.ServerInitiatedRemoteActorSpec$RemoteActorSpecActorUnidirectional", 5000L, HOSTNAME, PORT) val result = actor ! "OneWay" @@ -95,7 +93,7 @@ class ServerInitiatedRemoteActorSpec extends JUnitSuite { @Test def shouldSendWithBangBangAndGetReply { val actor = RemoteClient.actorFor( - "se.scalablesolutions.akka.actor.ServerInitiatedRemoteActorSpec$RemoteActorSpecActorBidirectional", + "se.scalablesolutions.akka.actor.remote.ServerInitiatedRemoteActorSpec$RemoteActorSpecActorBidirectional", 5000L, HOSTNAME, PORT) val result = actor !! "Hello" @@ -107,7 +105,7 @@ class ServerInitiatedRemoteActorSpec extends JUnitSuite { def shouldSendWithBangAndGetReplyThroughSenderRef { implicit val timeout = 500000000L val actor = RemoteClient.actorFor( - "se.scalablesolutions.akka.actor.ServerInitiatedRemoteActorSpec$RemoteActorSpecActorBidirectional", + "se.scalablesolutions.akka.actor.remote.ServerInitiatedRemoteActorSpec$RemoteActorSpecActorBidirectional", timeout, HOSTNAME, PORT) val sender = actorOf[RemoteActorSpecActorAsyncSender] @@ -122,7 +120,7 @@ class ServerInitiatedRemoteActorSpec extends JUnitSuite { def shouldSendWithBangBangAndReplyWithException { implicit val timeout = 500000000L val actor = RemoteClient.actorFor( - "se.scalablesolutions.akka.actor.ServerInitiatedRemoteActorSpec$RemoteActorSpecActorBidirectional", + "se.scalablesolutions.akka.actor.remote.ServerInitiatedRemoteActorSpec$RemoteActorSpecActorBidirectional", timeout, HOSTNAME, PORT) try { diff --git a/akka-core/src/test/scala/ShutdownSpec.scala b/akka-core/src/test/scala/remote/ShutdownSpec.scala similarity index 100% rename from akka-core/src/test/scala/ShutdownSpec.scala rename to akka-core/src/test/scala/remote/ShutdownSpec.scala diff --git a/akka-core/src/test/scala/RoutingSpec.scala b/akka-core/src/test/scala/routing/RoutingSpec.scala similarity index 96% rename from akka-core/src/test/scala/RoutingSpec.scala rename to akka-core/src/test/scala/routing/RoutingSpec.scala index 06b8117c24..b709714de9 100644 --- a/akka-core/src/test/scala/RoutingSpec.scala +++ b/akka-core/src/test/scala/routing/RoutingSpec.scala @@ -1,6 +1,5 @@ -package se.scalablesolutions.akka.routing +package se.scalablesolutions.akka.actor.routing -import se.scalablesolutions.akka.config.ScalaConfig._ import se.scalablesolutions.akka.actor.Actor import se.scalablesolutions.akka.actor.Actor._ import se.scalablesolutions.akka.util.Logging @@ -9,12 +8,11 @@ import org.scalatest.Suite import org.junit.runner.RunWith import org.scalatest.junit.JUnitRunner import org.scalatest.matchers.MustMatchers -import org.junit.{Before, After, Test} - -import scala.collection.mutable.HashSet +import org.junit.Test import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.{CountDownLatch, TimeUnit} +import se.scalablesolutions.akka.routing._ @RunWith(classOf[JUnitRunner]) class RoutingSpec extends junit.framework.TestCase with Suite with MustMatchers with Logging { @@ -174,4 +172,4 @@ class RoutingSpec extends junit.framework.TestCase with Suite with MustMatchers for(a <- List(t1,t2,d1,d2)) a.stop } -} +} \ No newline at end of file diff --git a/akka-core/src/test/scala/ProtobufActorMessageSerializationSpec.scala b/akka-core/src/test/scala/serialization/ProtobufActorMessageSerializationSpec.scala similarity index 91% rename from akka-core/src/test/scala/ProtobufActorMessageSerializationSpec.scala rename to akka-core/src/test/scala/serialization/ProtobufActorMessageSerializationSpec.scala index fbf5411e02..011c656f8d 100644 --- a/akka-core/src/test/scala/ProtobufActorMessageSerializationSpec.scala +++ b/akka-core/src/test/scala/serialization/ProtobufActorMessageSerializationSpec.scala @@ -1,12 +1,11 @@ -package se.scalablesolutions.akka.actor +package se.scalablesolutions.akka.actor.serialization -import java.util.concurrent.{CountDownLatch, TimeUnit} +import java.util.concurrent.TimeUnit import org.scalatest.junit.JUnitSuite import org.junit.{Test, Before, After} import se.scalablesolutions.akka.remote.{RemoteServer, RemoteClient} -import se.scalablesolutions.akka.dispatch.Dispatchers - +import se.scalablesolutions.akka.actor.{ProtobufProtocol, Actor} import ProtobufProtocol.ProtobufPOJO import Actor._ diff --git a/akka-core/src/test/scala/SerializableTypeClassActorSpec.scala b/akka-core/src/test/scala/serialization/SerializableTypeClassActorSpec.scala similarity index 98% rename from akka-core/src/test/scala/SerializableTypeClassActorSpec.scala rename to akka-core/src/test/scala/serialization/SerializableTypeClassActorSpec.scala index 2b26c9ad81..1166daf6be 100644 --- a/akka-core/src/test/scala/SerializableTypeClassActorSpec.scala +++ b/akka-core/src/test/scala/serialization/SerializableTypeClassActorSpec.scala @@ -1,16 +1,15 @@ -package se.scalablesolutions.akka.actor +package se.scalablesolutions.akka.actor.serialization -import Actor._ import org.scalatest.Spec -import org.scalatest.Assertions import org.scalatest.matchers.ShouldMatchers import org.scalatest.BeforeAndAfterAll import org.scalatest.junit.JUnitRunner import org.junit.runner.RunWith -import com.google.protobuf.Message +import se.scalablesolutions.akka.actor._ import ActorSerialization._ +import Actor._ @RunWith(classOf[JUnitRunner]) class SerializableTypeClassActorSpec extends diff --git a/akka-core/src/test/scala/SerializerSpec.scala b/akka-core/src/test/scala/serialization/SerializerSpec.scala similarity index 93% rename from akka-core/src/test/scala/SerializerSpec.scala rename to akka-core/src/test/scala/serialization/SerializerSpec.scala index 95b291ed9d..bff387ec99 100644 --- a/akka-core/src/test/scala/SerializerSpec.scala +++ b/akka-core/src/test/scala/serialization/SerializerSpec.scala @@ -1,9 +1,7 @@ package se.scalablesolutions.akka.serialization -import junit.framework.TestCase - import org.scalatest.junit.JUnitSuite -import org.junit.{Test, Before, After} +import org.junit.Test import scala.reflect.BeanInfo diff --git a/akka-core/src/test/scala/RefSpec.scala b/akka-core/src/test/scala/stm/RefSpec.scala similarity index 97% rename from akka-core/src/test/scala/RefSpec.scala rename to akka-core/src/test/scala/stm/RefSpec.scala index 805e0834ea..33ce43ab10 100644 --- a/akka-core/src/test/scala/RefSpec.scala +++ b/akka-core/src/test/scala/stm/RefSpec.scala @@ -5,13 +5,13 @@ import org.scalatest.matchers.ShouldMatchers import org.scalatest.junit.JUnitRunner import org.junit.runner.RunWith -import se.scalablesolutions.akka.actor.Actor._ +import se.scalablesolutions.akka.stm.local._ @RunWith(classOf[JUnitRunner]) class RefSpec extends Spec with ShouldMatchers { describe("A Ref") { - import local._ + it("should optionally accept an initial value") { val emptyRef = Ref[Int] @@ -153,4 +153,4 @@ class RefSpec extends Spec with ShouldMatchers { optGreater2 should be(None) } } -} +} \ No newline at end of file diff --git a/akka-core/src/test/scala/StmSpec.scala b/akka-core/src/test/scala/stm/StmSpec.scala similarity index 96% rename from akka-core/src/test/scala/StmSpec.scala rename to akka-core/src/test/scala/stm/StmSpec.scala index 16912726a9..0bb2851274 100644 --- a/akka-core/src/test/scala/StmSpec.scala +++ b/akka-core/src/test/scala/stm/StmSpec.scala @@ -4,7 +4,6 @@ import se.scalablesolutions.akka.actor.{Actor, Transactor} import Actor._ import org.scalatest.Spec -import org.scalatest.Assertions import org.scalatest.matchers.ShouldMatchers import org.scalatest.BeforeAndAfterAll import org.scalatest.junit.JUnitRunner @@ -18,7 +17,7 @@ class StmSpec extends describe("Local STM") { it("should be able to do multiple consecutive atomic {..} statements") { - import local._ + import se.scalablesolutions.akka.stm.local._ lazy val ref = Ref[Int]() @@ -37,7 +36,7 @@ class StmSpec extends } it("should be able to do nested atomic {..} statements") { - import local._ + import se.scalablesolutions.akka.stm.local._ lazy val ref = Ref[Int]() @@ -59,7 +58,7 @@ class StmSpec extends } it("should roll back failing nested atomic {..} statements") { - import local._ + import se.scalablesolutions.akka.stm.local._ lazy val ref = Ref[Int]() diff --git a/akka-core/src/test/scala/tickets/Proof001Spec.scala b/akka-core/src/test/scala/tickets/Proof001Spec.scala new file mode 100644 index 0000000000..29e4ca3137 --- /dev/null +++ b/akka-core/src/test/scala/tickets/Proof001Spec.scala @@ -0,0 +1,10 @@ +package se.scalablesolutions.akka.actor.tickets + +import org.scalatest.junit.JUnitSuite +import org.junit.Test + +// Sample ticket spec +class Proof001Spec extends JUnitSuite { + + @Test def thisFixesSomeSpecifiedBug = () +} \ No newline at end of file From f62eb75798636ce652b6f30b6338ea545dcfc304 Mon Sep 17 00:00:00 2001 From: Hiram Chirino Date: Fri, 23 Jul 2010 19:15:32 -0400 Subject: [PATCH 058/188] move into the new test dispach directory. --- .../test/scala/{ => dispatch}/HawtDispatcherActorSpec.scala | 3 ++- .../HawtDispatcherEchoServer.scala} | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) rename akka-core/src/test/scala/{ => dispatch}/HawtDispatcherActorSpec.scala (94%) rename akka-core/src/test/scala/{HawtDispacherEchoServer.scala => dispatch/HawtDispatcherEchoServer.scala} (98%) diff --git a/akka-core/src/test/scala/HawtDispatcherActorSpec.scala b/akka-core/src/test/scala/dispatch/HawtDispatcherActorSpec.scala similarity index 94% rename from akka-core/src/test/scala/HawtDispatcherActorSpec.scala rename to akka-core/src/test/scala/dispatch/HawtDispatcherActorSpec.scala index f6720059fc..dcc8f7eafb 100644 --- a/akka-core/src/test/scala/HawtDispatcherActorSpec.scala +++ b/akka-core/src/test/scala/dispatch/HawtDispatcherActorSpec.scala @@ -1,8 +1,9 @@ -package se.scalablesolutions.akka.actor +package se.scalablesolutions.akka.actor.dispatch import java.util.concurrent.{CountDownLatch, TimeUnit} import org.scalatest.junit.JUnitSuite import org.junit.Test +import se.scalablesolutions.akka.actor.Actor import Actor._ import se.scalablesolutions.akka.dispatch.{HawtDispatcher, Dispatchers} diff --git a/akka-core/src/test/scala/HawtDispacherEchoServer.scala b/akka-core/src/test/scala/dispatch/HawtDispatcherEchoServer.scala similarity index 98% rename from akka-core/src/test/scala/HawtDispacherEchoServer.scala rename to akka-core/src/test/scala/dispatch/HawtDispatcherEchoServer.scala index 2b6bd1e449..208433bd4b 100644 --- a/akka-core/src/test/scala/HawtDispacherEchoServer.scala +++ b/akka-core/src/test/scala/dispatch/HawtDispatcherEchoServer.scala @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package se.scalablesolutions.akka.actor +package se.scalablesolutions.akka.actor.dispatch import collection.mutable.ListBuffer import java.util.concurrent.TimeUnit @@ -23,6 +23,7 @@ import java.io.IOException import java.nio.ByteBuffer import java.nio.channels.{SocketChannel, SelectionKey, ServerSocketChannel} +import se.scalablesolutions.akka.actor._ import se.scalablesolutions.akka.actor.Actor._ import se.scalablesolutions.akka.dispatch.HawtDispatcher import org.fusesource.hawtdispatch.DispatchSource @@ -33,7 +34,7 @@ import org.fusesource.hawtdispatch.ScalaDispatch._ * the HawtDispatch dispatcher and NIO event sources. * */ -object HawtDispacherEchoServer { +object HawtDispatcherEchoServer { private val hawt = new HawtDispatcher var port=4444; From 922259b171eb28dccfbe4df133b64f5e3c413588 Mon Sep 17 00:00:00 2001 From: Martin Krasser Date: Sat, 24 Jul 2010 09:07:44 +0200 Subject: [PATCH 059/188] Upload patched camel-jetty-2.4.0.1 that fixes concurrency bug (will be officially released with Camel 2.5.0) See also https://issues.apache.org/activemq/browse/CAMEL-2986 --- .../src/test/scala/HttpConcurrencyTest.scala | 9 +- .../2.4.0.1/camel-jetty-2.4.0.1-sources.jar | Bin 0 -> 24926 bytes .../camel-jetty-2.4.0.1-sources.jar.md5 | 1 + .../camel-jetty-2.4.0.1-sources.jar.sha1 | 1 + .../2.4.0.1/camel-jetty-2.4.0.1.jar | Bin 0 -> 39062 bytes .../2.4.0.1/camel-jetty-2.4.0.1.jar.md5 | 1 + .../2.4.0.1/camel-jetty-2.4.0.1.jar.sha1 | 1 + .../2.4.0.1/camel-jetty-2.4.0.1.pom | 144 ++++++++++++++++++ .../2.4.0.1/camel-jetty-2.4.0.1.pom.md5 | 1 + .../2.4.0.1/camel-jetty-2.4.0.1.pom.sha1 | 1 + .../camel/camel-jetty/maven-metadata.xml | 11 ++ .../camel/camel-jetty/maven-metadata.xml.md5 | 1 + .../camel/camel-jetty/maven-metadata.xml.sha1 | 1 + project/build/AkkaProject.scala | 2 +- 14 files changed, 167 insertions(+), 7 deletions(-) create mode 100644 embedded-repo/org/apache/camel/camel-jetty/2.4.0.1/camel-jetty-2.4.0.1-sources.jar create mode 100644 embedded-repo/org/apache/camel/camel-jetty/2.4.0.1/camel-jetty-2.4.0.1-sources.jar.md5 create mode 100644 embedded-repo/org/apache/camel/camel-jetty/2.4.0.1/camel-jetty-2.4.0.1-sources.jar.sha1 create mode 100644 embedded-repo/org/apache/camel/camel-jetty/2.4.0.1/camel-jetty-2.4.0.1.jar create mode 100644 embedded-repo/org/apache/camel/camel-jetty/2.4.0.1/camel-jetty-2.4.0.1.jar.md5 create mode 100644 embedded-repo/org/apache/camel/camel-jetty/2.4.0.1/camel-jetty-2.4.0.1.jar.sha1 create mode 100644 embedded-repo/org/apache/camel/camel-jetty/2.4.0.1/camel-jetty-2.4.0.1.pom create mode 100644 embedded-repo/org/apache/camel/camel-jetty/2.4.0.1/camel-jetty-2.4.0.1.pom.md5 create mode 100644 embedded-repo/org/apache/camel/camel-jetty/2.4.0.1/camel-jetty-2.4.0.1.pom.sha1 create mode 100644 embedded-repo/org/apache/camel/camel-jetty/maven-metadata.xml create mode 100644 embedded-repo/org/apache/camel/camel-jetty/maven-metadata.xml.md5 create mode 100644 embedded-repo/org/apache/camel/camel-jetty/maven-metadata.xml.sha1 diff --git a/akka-samples/akka-sample-camel/src/test/scala/HttpConcurrencyTest.scala b/akka-samples/akka-sample-camel/src/test/scala/HttpConcurrencyTest.scala index 8372304afd..71c5d02ce4 100644 --- a/akka-samples/akka-sample-camel/src/test/scala/HttpConcurrencyTest.scala +++ b/akka-samples/akka-sample-camel/src/test/scala/HttpConcurrencyTest.scala @@ -16,7 +16,7 @@ import org.scalatest.junit.JUnitSuite /** * @author Martin Krasser */ -@Ignore +@Ignore // do not run concurrency test by default class HttpConcurrencyTest extends JUnitSuite { import HttpConcurrencyTest._ @@ -86,6 +86,7 @@ object HttpConcurrencyTest { class HttpServerActor(balancer: ActorRef) extends Actor with Consumer { def endpointUri = "jetty:http://0.0.0.0:8855/echo" + var counter = 0 def receive = { case msg => balancer forward msg @@ -94,11 +95,7 @@ object HttpConcurrencyTest { class HttpServerWorker extends Actor { protected def receive = { - case msg => { - // slow processing - Thread.sleep(100) - self.reply(msg) - } + case msg => self.reply(msg) } } } \ No newline at end of file diff --git a/embedded-repo/org/apache/camel/camel-jetty/2.4.0.1/camel-jetty-2.4.0.1-sources.jar b/embedded-repo/org/apache/camel/camel-jetty/2.4.0.1/camel-jetty-2.4.0.1-sources.jar new file mode 100644 index 0000000000000000000000000000000000000000..7aa139315385a80cd3e99f83e04bb866af2c56eb GIT binary patch literal 24926 zcmWIWW@h1H0D;h??=~PBhB+A+7<^qr9CbbY-1K3}I2b~bzS{^(>`qz7z`(%E$iN_i ztjyQZ&(qB{I7H9at+vmW`;dW%>vxBL&M)RoD0>l5m~qr~1xM5BBVRHXX9i8$a-%-q zenXyKzQy-@hqYS+%Re;69jHw8bxS&CcxvvNQ2uxA{!;hms^4c=JeOH;!J?xRChig4 z#1_;g$K&R@yky4CM|0FU;{#mzuV#N*-V^`0q-ohDhx5+Go1;!H&QMUkW;sZXDS z{&YLVmd484mYlDPYWWuLy|U`-;+#C4pY=DF#b3L9q9n>)BJm3&%zq3FE=H)qz{0@5 zkYAJz4*^US+)x#X1&PTSsdy9$qAE;I%uUTfQtpaovotp4$@#ej`FW{%B}f|Gj8UDe zh+kt?YDq~Yl6G`^g^**kIJKxOGdZ;wk9skz>QTcC-40otdN4u}U8^!7t%Sl=mpB73 zLz;s@!{ob7&Dw&?hHMNBtArUC?1%|zXHYyl=jWAV=9MOvWaj4urxumvq?YJqC6*;_ zjR?%Yb{!E+uZgcu_^$$GjT#uw4OE%y-)6_hD6UYCSth8%B#XACa z_RJLYYI@u%o_k<^O!Fj}DQ!zH-PzSS#U#q7xY>O2A=M2#pVgdPdNQVALhwUn;=(f>M#YcEHgULqw!FM?Lh&7oyBUV@ z5&_vKOScKE%>LWM=~EHtI$5;u?LLmLi%)s0m|jp7m#ygU%a|R1cm7)acCoFej<5YD znRB7$q?y9hMw`c`_y2ew32r`^lycfc(8p~LU*2x+qE8#YELzsKka2T@!`WA-8zeVv zx%MqeV)DLMW!GPCJ)Lu7-KEcYt(&TQ-|#v8uaw-ib@x=x^F}If-^XM;soKRjEh$HE zcG3~f=wPkfZ8?$&8ri*TPFJ#T+QheJe$~FRC!vi>%wJhOkG!9C(NkrRsMsOu(Yu|29 z+x}|aJcYaSPl^h~70Pc^^^fr~Eo(7(r=EA_*_$sz(e|Rd%Hv41MlIm(OWyeDZU*;()7 zYmQYo{D;vyZ-(KF#_F(l8Cwj$zetn(a(FFACjZB$-s|?CeI+Xb%>}ji;$U zGboZ%RXWgqq*-^J(|1C7NwbCp{-=-_=Skn*HtT zta~%}FH;EJ^vEyss$KT1PDzX1SJyi}^SrcAS~^xV;tG%C?mB-StAeQ?Wq|2KL6lFkPY3x!G*epa0hS*CDl&MYB!OMUCI`|D0*T)lX^b%tkAnY(`Z zk|eKM$>m-ikGEJCr2Fk?lzCRIx_A1_Her{FJ}-mkyQA3~FNL~xdK#KXJzRJoXO0$| zd5!cPAHDyF`0Fo7e``LN%6@LDm&N3F6(!XM+VT4huk1VVf}ySH*|_qxso}xH+;_5Y@^2GPqZc|)UoRR$Q1uRC;znWf?PSa-50f&R#>z%CN38_ zUiXH_O7mgI1g-N2c5}X9={43^bXm*R{+`*_LmQs2oqdSs>B6_u^s-WdrKFAG;b_Hd^URs{4R4c$A8oAq?5tI;&#t;Q zXf0zu!;iSxvrWve+9zsR{@r)NPDKA}^m}_Zr|px<^wwl8o_4WbxT5q-W>0@n)|>D* z-?Ym#!elJI9yYu0?5(lWHe&0WpQ|D}wuMCBm{xAS$-VkPI{UZZiMuEE+^?NpAeHU? zV_VvX$MLY13I~I!$#)x0V?BFyW(I~1HU1Be`R!y_q9OEg`ezJ(^ONZ1H zmjEfRr56vUctxEx-@0`AqE?o$j3YuzO&J}UUVMBUDs@(T!&4^3=gV{#edFD3-Jeo^ z$6@i8@*6^8r;FdsGG>gq)V*oxqKyew&o?bNcGdB7Qo5t5(AJwDwLVy^6rQY8ZMKZ{ zTdn7-xvQ*InJ>;25B}lfuZ2UCwr?e<-M_tVQKOnf16o0vUP7n)fdIM&Xi?VZvY z8OeDrrOmnUxZabKvF(e@rUf#7PIAa?zugcS{&Mx-t(&)18P7KL6*lm<4%jv0t5&-F z$-5SjbIPyO-d!t_!87yQ;%Bq=+>>btJ))Z|oum`-*zM)=r^yZ>Qoid>Cvh!1-FRH` z-0O>b=4n_O+;RA3$hka`DX@quJW)tBxc`%?*ZuW*!9Rr7T~D0j*3A-@J!Ac&*BZTH zhPJwjJ?|eli^Tggp0vtp;h$P2)uBBDmZ&2*od0cSMlWXax|7f1wK5K5ziFfb$x_I92Js;7jRIqrNuww29-nF(d zb9(&TT!J&X@86im8pC=q>)~Wa*?Ic*ENoxn7Vu7siMaAvcIm@M^3jvN)pLBiw9oXc zOz+?Kdd`1%`DR*9oWU74v2Oh;eWQcEx;p=lY{~ukYgOcTTh4_gt3}uDVouyU`Ha)j zP&ei!#VeLr1RT>y@VOwHx-4nho-?%$ooh1PcOUz_e@)|WjgL;3+ST7bpTy~QamMbz zJ73O5XHAjrHZuRvWAvwF&fUVQ-HReJ<|Y4*xGHTWz9HPEJ!b3dffh%8|vzq5!nyaE}a)U{hb9H1H&v)1_oPVvY$(8T4HHVi5I8|?om=w z;FOt{l9`td&VhR)qVsQ?iPZ5=_+OAE(t3Ag(X}-P1k8`#ITE*LS()H&-A^GGgmgDg z^_;rojnv_Pzxh^nt9lpB&7CW!)A?v;?Q^g4`F6Ipjmry8+nf^p>d1Y;o9k~!MaAr{ z)_Ve;i5f}ogwL|Hm(^RnVb~YM*%T}w6y_9k`j~Kxw^_fbUK^*kLgSJW*PUT{2c`s_ zuD6-lyN+!`f+Fkul`R}c^Jm0G`Bj}1$!Yn+#QnszX1?S@6_#U#iBnf7WjZW5U(wLC zcx}qTpynF|T308zu6t^1e9WhPrkPe^&eKIJzbpCaYD&yadU$|6CFO`s`FWl7+iqU* zvfplHdqe4GS56~0@5V)}_rA<_SMEKvC~dVyN=x;Yj2Jyu!=3&+J9eshIIJ;L5IdUd zuw~(vE8n8BWMfNq&pvxhH7qy$#Ddw8H}|@h9KU>Ub4aQ8_j&Chnk;X#&!{BX-e>9z zFz-JT_;^B2kM`Q_IT8!Bq&ru9KEOEjSmV>+FW33@_yoEv*unTvStjbQX3sL+io5gs zmi0aTRA{n$=AQWnkN>+HTW=%HyUbu`^Xij7s!XJPkNq%f`S(NaUeB@Xd;u+dtQYeq znwTwEbmoB9-y^3ZBT~I)%rJbfwMZ`7fPd{{M;|7x#)#mPz9(El*3B^D3tO=$|7T0i z(Jj5Yp{8fMKn=k=@jTirHiz#iYfJ4qc6Eke%!?vx}9AiqMROkT)Z>ZSDubO(k^pnWAJ5`iPg>a=2I4IbQa6fS{^0j z+x+&hg^z$A_nip|e}0>Wh3#0;vGX{$*lN+Lqr9#H3%=ip7L?hY?_smXz0-PE=HB1A zbDw>CY`rV(*-NH6+xo(~e=>6Ed411kNIz(0VSYDD&qL;weNTMv&h?VpOOLxG2Hjck z>8-!=g(q1mH>Gr$Q=Lv9W=eb|A$3~R*~>xnVc93^m_vS%<_o0m-{LKbT^+hS{8>D^ zn$Bx6{l?3@CYAg4p0Chz@i6TD8r0?c?pEj5Qk_hFbCbp#-5LB7J01yizF%=DB5=#x zqw7}oemm%?u=~)wMuR8weLYh3=ejIuido?(dZ}Bn!YH*~wWcdgw3D}O<`+#TdF||o z#yZAamV2qMW}SPSaKKmb%k8;-fgL-~sNK)W+@6=Vxm6xZ{Pftj4ubiRjYWLl4`}3|}$k{NpYmc~Yj@+`|6AbNBd!EOg6!p86E%8pw z#>8>z&+wX^#fgFi%af)s{|Jyz@-t3zaK4g!-i_JohFSmNpEqlo z0=gzWc({$R`Q+?Bd%dbm7<&FIPo91DoXGi8+0VjN%gRJ*bSAZ|{Iub;<;jIzcQbA~ zKJ`|df6vQx;Wi6Xr_dJ1AX)FY=o3|6H{~z}@$TtgH%V3XOvZDwE0@?ariET&z8RZb zReaYrrFL@5`;gD8Zt_ZB{FE#@*(vyZPxJrS?1EK>apiBb)&jKGkjR;s>{6gI8t$iaEq$(bvzGxB23QeG6}Yt8?_)zRpu(`nNg* z?x}Z|?UY!zPHa1q;%+60sVh!hpV6}F?x#r>HOsaO&ikD;+j~`To{(HhTJy&@m*4!m zyI^Nn+NRA4E$$XGkKX9rxZ3uVSZuM^ZM8&e;pY5`!;D7EXE@4)tjqsyk2~%aAetc` zbm4Q3-4(aK*QWLcpXG~eO}_F=`EjSu?@{1A9whL}YE`RZ!evk2xVicGNtwqH8{|zc7dA50s2NT#T4(R|`pNeV z>+a7!a8|Qf{V4l!?ww};k9%aEsx2~RXRm0S7@+n$o=0Qu=1VIx?fJ90BBU0Va(-Ih zx0*Lqd3MToqXVa2i)=kIe?NTeih}`EC9SW^Hq_x@V3;OFWQ!177lDQ+Qu9h&E0Qx3 z^U_lx^-*MQ@oh7qfA1v!x7+&K2dwm3`ZDF#t>@XIk#?)qy(PW#^yXU`aC&xVHn2AZ znVA24zn!~5NHeH!((cu28(oVwR(yMVll5-x$47s7;tqJY#H87B<#1n+q=&y5Us3@6n|c#RF4{ zSJ&Ijdl(Hf47w5AT-A6YrI2+02^r&}g^P-RQw6~BAv)H{y7*7NxGeZKH^7yHZ)I?l`gYKu$N z{@uYkO=(+)tSZ@zt!$o9VK`}e&cb1Y^YdLs90^2e_QW^;NzzGAC-{QX1!!ymht zWn$ZI2w*PR}#nOL6k#HMTZABl0vm>csX=V0Q(YcbwlGpD?sdP3uX zq*Kq@c`j>OHtw8y)pv7r>G|^)?)op`l8yUem!v(fMI>ttN9G~^J2T!s{dx1JAV61{@@Hmg*+$j8Y| ze|_2CB)>E9F>l&6F_BH`9Re3BCe04M5~bWeIeK2gHj~pUuX1fx^|_MNsL1J_Rk-R7 zZ}$ZC?V*Kos!B&=HcN^;YUOS*`LX-viDRPMJ@{*Xe|32nTq68D;$if;4Q893rx+&R zfAV?f*IPd$uWz4u|HaLHT08HHn0X88KJ5G~!WosEC-TMpf9HmZv=ts7tJ_qcWnWzN zr}S;)ui4f6#J;>`s;m3^>*{&?gXXRWpY@+85>Vw?dDzLKK!fSvX^ZB=zyGU!aM^xW z?~K~@$=nquWL9{oIlq4^&{X$6&*0a)tNrWiGQ>{@>0Uddz%RJc<%ZOX=7o($%Ey`2 z7<<&}+qG{jci!=UZGDs4oQ0+fYb#gWdwI0!pZ2D9)tv9Y^EZ@CJS3}f-=S5QFO~UH z^tD}KoQsZK3n;p*=PAXy+OP9l={=2H-6bVe%1d$|nHB#zy3zIbk+u~l-tW?0b%xdO ztmZk^tLg{8tETVL$^29u@Y&&c<(Iiu=gd@vfA9xcUT?f;d0dmJxZ9{+T>H&w!}*(S z41cqlM7HcM+G*8u#BT`?(@`m#UBaas0#-aa?$7=%LR--Jn6Kc~1(wG|U(fmF^yHO+ zU|IAZtAn?$Dm`=MnEFtVm$xif^?mI|>s_2O^BY{!-Zkux*vwMfVV$-04I z=h~|;eC{HcdmdSblp#>7wo6^3D~GDI3m5{Kkwl( z!TPDZrmFwNgTLKiz4W1tvv~0r)3Q~a%W{ij{mON;*M6ST_Fq}&qvH8FVm1zHha{{n zX}%FCX*no7WA>g2dKE^?FW*(>Q_VT2tu@15R(j3^Q6b*CR0DS%mCW;-&dgtHv~|(W zp43$rWVGMSSfTKHZ(7sF%aL28rHa$u$<6wyyQl8wr>E;gFSmPeyi^vs$;0ksH$lYZ z%o{1$i2`SPY%=yHf7_F#cZhP~+_JXJA_WCJCXTz>OD^{)$T0C`Osfg!IYsZ%* zf{V)2n?JtkKe)qwr(B=*+$B%aY+~2$IJ+=xyLaKy*?TRPeP>xwe}C28$?d-v{*|f- z*mv@v{)JzyV!v$q0SrCR2mb`8E`D`_3T~pTlMqZlZAihA5l&EqTYD?Z7V;w>T%gg?9l~Q zp6@1$HqJMRn|CMZ#pMfOUUGJq68oOMo-bAM=c7Dox46n=r^O*=1_mZB1_m=?y2ao& z2zr0`YS_iR+h!uQ{1fVTaQ}M1GEYQB!oVa_(0r?Sd24LMyC$1Um!=+ZRWhB_l_c`_ zd+el1k5r1f?at{>OZjxC_?+$ZqKcxT3I_ELoyRpy)Dl!?$Rq}BoUu=7=Bzf&mYHi@ z5AjTAa+{n{##7SGwZvfpm)FV*2ag0v95vs%u)VdNWt!#@q1KCx4lOS}h@bxYr;1Bc zUqEQxUp1}!1(U5+CKvPehJ2qOB<3xY*S(o(#{%}H%NH3WYdut2eCTS}M;&to=|->T zd$?rI-RkO0la+qk7#lmOO8s@%$-WoYx()yMI&3==S@3FuTiM0H-=8mjWX;K}KDkX{ zNn_MwJ~O*x5t2&YXHKnp;B#b$_PX^>^X_cbC`y*dP4MG6QBp2xkX*j&?z_p-!FzcR zFUw?lmcbsBnz-EPkIOr~MK9OumTrIFtr3uI^!ENN?N3#kS;GXk&&cg4JScVB>$O{Iuy^nnC29gYln_wi_x$y0?DV7!<}V`1D$sPtEk*5v3|Q zX>azfGkB)i?>YBG)-=VGPmEJHOk5c-HRd*3_M#aUbDE~#*^%?|`lXnaA3ij^*|$9) zrQ&(*8802C+gYL5V zm-GeJzW!YD^}@O1vqkL+s=tcW+5dn0=MT@llCZ1Nr^H=5Uo7u&ThLy8U+8bv(Hjoc zj^B!z=IfUJom0Ik<>kDJqlTvQJ<6hgtqoV1J+jAqRVHW zYhdQKnHYvJvaUP#6+ZSV^8$ep}~SATW;zekRrmOS5; zb-ky`YVN6x=>@*a^$lOt-&CMR|NQb=fAxph`r^~wOhP`9u|I-;9lyB!7^~S*XPNzP zPsiA)T-nr@ovWc){io3OTJ;|Zll&DIHWY5R+*N#e@70xm?HAX2vM;gbO7FRs;W>YH z-2Up_hDKB3LjU?4F>?Izl;6VI_OA7uKCk}mC9GM$CKqO&v0j|Dhv(&^PUAA|?-JYP z+N5)r=uGIWefm$nZ|mo;ldqLr+IcU%FWmpkKcvAj8I$ieG6(FFokbZK=0`IySddgI zIKw8r!TplAHrd6uEhgO$p8CJxV(!~O$<}$hSFOBTd~If-O#0d*>o>od>l+)pR6}Tz z#X=8V$D7yAKHVQ*&aA*FwBW@|pR08i%e1zsF4%qXg}IbX#m7fKjlVU`U2b@u)juM1 zL)OuoAJw`Z9$ym?!XJ3@=I*4~>VZ?mEV=vA-yh@o_e52@=v>#NwcV41XY4q!+GuXR z_78)}3XxlMEaN}#5mHPxKF9g*>D9Mio=nlb)U#Pdv`A<{y~k=%$5mk~6ZlvQAcBWpqsJ2{DTvzBWPR?_>dTHPMf|XSg4sm<` zjmWv`)#Iui=X2vegTSJn-#=J4i9T2`@mG~e-O)0GTG_V|aUnU{I~Zr%AFByw+~{z# zYVy)Rx#HqNQ?Ump-C38;2p9C}$S_&tP<|MKn4t9M6#yZrI&*^f`( zeknP&F7L+4t50vgeEa2<(7&qVefsvB_%EN{E_|%9w4uX3&nt#mV3tyJrBZoh_f$2e zRJQ+O(sIkYP1>$LJ)OJdNlxUQ&qnSOZ+n7D*-pV2D=jSu- zwpZ3j*zv4ZW^JX|qp)VTC!s%#*RQ&}`uX{J_RL1zo09C^zX#3`duT1t7yfOz<@!Ur zXJ@{?oI5q`VWdi!_{C#iuUdY%@pY$6UhPMTb&F*<++=z5?|smi|50d1Lf`8(Pg(xk zGnPKqF|KyVOuLjL(5ZQUA=Ckd!nJg$w1+I;T8e)G(} zZ4Wai`+afupF6Gl?W~GlEs@MS)Xg;Cth~4HajJdlw-=G2Zldw;s?;W&nd7o(S9AQ4 zeT~5z-m$(C$$OZy`{2Ug&tlHjw|z{vx&5W6{aBOK7bo3o*$;|mh@Mu>$*G8|FxzhZ zE>@)3KdZ3mc;qg|y=u9<5BcxRd930nY@DF-*81-)^B>Q@E)KB@QQPo7SMSDR*32}H zW`>79>v0a?o+&Z_=rG&|# z$S9%tCr6&}TtDOiR^nRSwGy6Ly-EXT_<&>8HJD*0+yK_nYy6Z&Vx#?#s z{=IQ%-E`b?Gmm9;#L|ylom^tg^X7g0I!B%Jh}wI>B|V~CYOQ?A5e82r;x`rvP ztVW#L+a9cV@kn3jUdz=*)rZB`8w%~VvE8|M*G$H?Ird-p`Hu-LcAIgp`T53+jmD=~ zqrBO^&6peiSM-6|G|QMzT>rRs@o;q(bM2Gf^613x%eQa$&rjR@*YmJ=bLW>& zNrTC~j+U)uKHpZjrS}9*Q@Z(BH1gPkZj4tkt&MzC8c>(pvH8h`HJHM*g&Er|viSl!t}zuY7n&i~@HoELQvtx-u zP_~(EybQNno5bSVQ>O2^HO=z(x9H}~-v?A{vyf6Sg|D=MPR=)T|71 zt@GZ!hD}1PuRd_$;q0ehz5WQiXg;w0#Jit`^X_~wRXL?_XwQ?%Gar9v_iANK@VnvR zD6p6_I3TyVw|`>q#+|=zHlJ-@*~sK982{N({JC_hNk;f9+nuNGyJl`{f|B=L^~V>%&>BZ|Phy`uW2` zoSj9gd-4ReGy6}3%X+6JcPd0g6EquL(`Mb^I%IS(y z?z+pA6h7N^oYU70WIeU2NIG0&O~ysV+!@7Y{Vh5riw>H0ocXcH$ty9@vvIe;!TOMh z-p#p6Z;dVMzf|ry603LOTnF3ByJx3V6uAFeyt2Qgs5yVj^@e;Vo=YFq1I&(Xa1t#& zBvEJFlAp6K;FoHv;u@}(_nX#D@~XV_uEmv`!PWZ8N9QG*i}{3>{}I(vd=hkQ23v{j zyX$R}%*BMouSg0!IOe~kKdfXnH`B^1%I6i{Jz07tzEo4^!h^S>i`cYdf4HqGcUS%D zGNpQ{TG6o`(v2At+RAxdf7#0%ntA=r?zju5+PR9?u`}nKUgk2t)2a11zv=6&$y`aD zg2{{3&YGJo-5UOFja-3l!uIEZe_Q2-q;@OpAV#kbce2kB9pLB8Sq~8;sZ8LoEfpuQ_!<*6D z`3zeogqZB_-#hQfw>eUiUQRxha0`5%5#n}i<=_iGF8wrMMU zp72gs%p`P6pGI_O_l-Y~PiX8@>}~Y)u_@lI|!omyV2_+Kc^RkN!p&L=;^AXZ=uz@m*br^WqC)o>Fd$ zP2aB(__oJbaxqKtFXsKFOp5c;U1d_WB^Lj*i+wiXva`nV?}xtR9sPMV{&4$>GtGjf z)(qy^CPp7(TnzuW`D$-#Q}OjkJ;S}qJ2+s~HTU*M{F*H_0-xQ!KiG8PQme9g*x#Dd zZf|lY{?B$jD`dsurnQgzrThhkD%r+$2_`c?cg?cPI&|a*d&39a$9%`HZk`_YkT*L~ zWdAAuxt|p7_9t!3JyzSZcCVkpMIII3xl)dK*F7?Hown&-^gnI2U`2GQTWq|^s;;w5 z#&LVKPq9r;-k=(7#UN|_bjv!|i;rennHYEZhupt)I==M8vQ0Dh`sDGN{}e2{_Sj(3 zytM@fCVsVC-eGYjGkKYL^lcx1od>@U{^XT?I+xqV?%<8;qtXYe#h&Orw2El_dACdZ zMU{K&lhW%qZA!)WpX1x+@$Ss=U_aTuD}o)H&F*}No39$Eb2(#ks`VPxt><)-{@%_l zJUo5Eio&Pw^kyCA>HdByyj<<)qF9r=H{Of&JPCaIyL-R0N$AIzGF`_tDl7f0u8OLj zF-o~OWx-j?z3hz#mP~r=&X*)pIxEuaZuXpAS2Xst;|KkY>>D_V~Ua8SK1)@xkH%vKK@bLDOS2l~B)Tcaq;d;pI&aque zzYbW06?r#@3q>*AwmMnp(((7>y3a4>sc`%|VsOr1wl zk_kUoyqKGi)3jt;x%?OAL)zZ&uWXD<33|t6_}47~e5 z;mOTztR?8|FSv30x37$vVNecKyE>Pp?pTgmnE&6+!!JInwk9()w zPT@bY`1kInywlVBZNH?RmELT9=KKt)-umQf#!|1sc}%jagpc`(NgdBIDB?Ggc{8ue zTI%|qXRF&D&v5xSwd3Rb=odeKA6R|Lqx|5y!_9fOg5I4ddHv6^L*>A|^@jhPTJJw> z%s=vBPR{O`D~>fUdB9|>eDLS3sqBdw+Waa~8b&2qM;`~VnY_xj{n2r@gCq6Ei^B_U z^StcxwA%1%PIpRTMpsq!KIK29c{7BhEv!hycUdyB>ReNb~L2n&k-(RMoi7tysTw=AD9F+hUfT zta>VydF#cr!gpDzxz)e6Uc8lkdEVdstNzHXdi0}o{iz=@akpF8#4ome-7a~3;hYWE zo)|rHD_{BHLekO*H}TNbS5F*qu@ye+F<;ZX{lvAB`qz^#-cs%nz4Ok@CSzG^so2NN zvMRp)HCC3^ZT{zWf2~+@QPH_1POK@w?wvuLOz+l;4fg*osumxs;8B|W(XTM*kx#mr zpWwR%*tz~dGe4hSL54w<{9X4f z-8Era)v_s0xmE{MPV3#9a5u0tVEb3wcOCZaIqy3~HVX1Dn;_jDB9e7n>{p?R{x+9b z<)o~=LE^`mTI?n=RPR-^OStkuqbKix#M++|ecZQxp85D`c7W0u`Jc<46t=KGWW3>F zw)@BLlUI*^Jzf9%pa0`^bD~yVJMdof=flhU`VaqOWntC)lQ2Z)=ha-uvjyNvLeHFbraYNrcr=IGyy)SQUzV^*`C1ZAO!uPv-Ud3i7bNAQr z8v4$5dEOT$zP7UYz@Af2ofaI7oGWo|R-C%Ivq;uIe8PHA3X8*orc+T5sVndsuYvJbMASM#T=XkT~dF5?n`y}Ik>eoxQ1 z)#Lx=@1JYW?2Qj6CrjocbN5+xPM0czqB*xOH&>gT zFMe?QB-45irnB$Yc0P+(QZ#G%vA6dF4>fxAAZV<5#!+cl;U;Ph(R0wp8oy=`hKE9DFVg6F48PJMftCW@o2ve#yT8|MQ7@)^~z$ z7unw5r2b)r`2(XrhYOe9`ykfyMEh8eoR3tq48tQwhY7s%SoZ2>1SvH~{eGcpGW(aR z$u?Ch3x@1u)~9RBuW5Xkd;8EVml^9G%qm$>T+5hJ|NK*rf$QowrzCQ%?M3rvTD`S- zm=!0e^q6P2du={T;_!b)5ffiu^Vd?4<|UzJ@V0S|LslOtU%FmZ<^8LFQzq?NzIb|yPq_Qbd#ZQ+3&P!JFL~3V*S<(mEllIko0{jICuc5pxOJK7 zRjqU9oAWwpMfFv=jW-tcuRXp^X5;3zbdSlOtCd^U-G6p9*YEoM4LZlz(vnmBTLbJP z-w5pc_VwkmU0F{Bd~0|3|2b<^B(K&yd7sID&fl$byO_7HzIvrY+iaF(^}FuiwkP>M zwkFj|spp&2r~TZeJKsO|dri>l=i&J`{>aWUoqub^&)c(2>WiC~+0Q?8e1h_W!Vo*( z$ls=$ww{m6_}`MYdj1zhp@iQF<~Bb*KK;*tI$g7%-DzqU3j@OfUIqqpk_Kj7^HK`( zGxH!@S$e~6=RGzP0L|A(u>4kFUl+6Gg!A>gNqZxu3#D$fJ}sH(9wl}A4ru-2njNnH z_By{xIvF%a!c(Vfj&b_Am>CDZetpUsbC{VwFr(*yhe32p;3219Tu*ML_$d0MXep)b z5P8ts$B;GQ!bnw-i#rx$S-|)=P=}2jw z%RA$|ZG0zlcDDJflHZ`FBj$R?D&4TaQNPSmv{ibUlAhTU3rmfCH>D=bbXdCG=A-Pn zOKieEUS?M8Wp$cY)MtuKywaq%<;CIqEGc*YJo^7;gH82|RX6s%;(h4w%({$0k#~ty z_KhDhNl6_#hPPD>)0K`?6-*Vs^kk*OMD4>T8g?c)tb2XDK{EU0n!D-QKA#E=PHZ}p z-nUKvYFdDsWrad%`oSN|n|5uk7BS57UG#Tyk!#d?z5_y!#5Rc<_C=-zzuffnRKtpt zt`PCrb}tt3$@tmEyMOdrw8Y^r!^z_;F}+MP*up=giug3|bN*=-d+)6L^bfgPB6`wJ zzqDxh$&~ke^ZLtAOY9b3WpUfA{-fCH_bqmnmnQ`6)K49AaM?Lkbg|9p)X1qSIcINd z^)q;qEf-XhGH8cW+v_bmd~W+eM~QDXWu?yl{P~u) z9skGtGKxJ{aEI!>mwZ=0d{wU3l$_M`sne-j(4^XA(f$~WJC@6MeA z?MB;Qc1bZEnh`klZu9{w&sFx#N|!EF{G9(avDzrG<~+|KuTv5$U#%2eJ6XY3=X&Dj z3BJ$Xv!1q3m~H=Jvh(o?iaN^c--q+;FL?ND!Q}-JJi8+oZuncbzgjMA&*ufv538=u zzHL+(uyg}Iqp9UiAJO;Bq8p?=`@7razV=L-*;W=9y>h{i7gMAz6dyA^BeeLzzo4K$ zHp}m5$|agVR^HD$E9>FcSA3$gLN0#2YWC`B%AaL#e``$H%e2rbXlG2-RIa%P!)3IJ z)k@sr=Q|`^yZ7zQ*-PaIcN%@DQnmekGI!-C--(s|eD|(vEv(!lptQXzeoAV-c;Gbe z^|RDMQjcE#d4T)A*@<6gG#*(uP1*9|`x3A3liaUFs%4l=5C0moFE3@^&Gsc5^Gcqa z?raz8dMzv;`}E4q$NKM9Gv3N6Kjr^%jdh^^v4fh2gPOS(SI;n+u=Y^hPG_k-4;PtL zW`%~cKgs^^X(7w}6*-qJ@^Y>(%KSDpceC=Y@bzb=PZQ`}`F$1-YfyH?w#WKE=N-Sw zE*Qki{ZIcd^JS@xYwuZ!F12fppSrB_gz1s+n9U|;%lV|a=FYmcY`?SH|CK%!IRO`a zmi@aU^M>U`&HZZb+|1qEU)|j~!$591m+iXv+b`$(Cmx^rB}z$p*Sx*AZ>_Wy{309I zUu&ng{>Ztsk`G^_KgV#mueerw`&mq`;6pz4FQ4sEi?^m-0q?(aFfhEAVIZ-13nEQ%a*C~yS8(O@0-}$JCD{`T@cbOR_?Z% z)Ripq^Znd~8l6*8)VWRMg`%a-oi<)SCuU!LeVyCA$<}fkeKyX>aQrfDVxgb%kIf>| zdzVj|C>@w$cr_+PMM6KHjb)#ar^~U92`TC-#yLt8Gf!S`ZEMdwIq8Cn(YEB7VTy|0 z$9VqVtTEj?ZvwBsWamyT{>C4+*P{=6=I>OhR+K-Di85HulUrtHHv-_SU zm!4RZJ!@I^hTJb)chxnO3YsRUbErqo;hy(0Smpdhu|0?UCfsS3sG78>QASv4Piy>l zpM2Lf_v$iE2X(L(i}`eScbts={DOtMXWs|q+ZU9sUR@~sMC5aDvg@-~^I8`Dl)F*AfboT;B zlp8mn*ixJJEygEB4vBw}sCs#;#>SQBWJ&3T9355L7}43i8{htUbE#~1{Jfmh|A`0Z zS=9Y<`1f=B{{N4c@1G>UN=5%#fTZV?APw{XZp-p&92764`hdg`Kucff9scTn|c>RX>sN+pX z=grffD!2d4!N^I+*Tk=ll4e->OQzzH>gCp!jZ2GD0P!~My z&%;)1@$w=LDK)LQ6CzBjZm&EX^y%=UbDX;RD`F+)YBs((bAM_@z#Eb0lm1A2R%F2f|E@Ln` z9G34MI$inLy3jROeuyakV!A57RY`dA^Zq7B&66uxHYZ30@iH#k`>$uc{ndQg+}khT z7e15b`5mLt8(f{Ha&YccGZzOzi*x+;XQ!_gSm!M8s_}7i<4T#jTanXURVS==?)&j; z@wAn*&;DKzdnHyk#xAsB%jr=0RooY*Y5MmZUZwkTX)f!67FQYlMN?fvoL^7y`aY}s zL*rcc#k*BLKNq;}Q~YmAt>~I)t&6eyG)}lQgv!5C5{kRuCw}_mtM4~|)ETKPUvk|c z`rPs<6|yfFj8~clNEBz5wU3_O`(A1Bo6WLP1}qO5&ty;7_94T)Fr7tsP3;b$#=~pA+`f>>bG$oa{>kMJ zqr05kbRNt-P%t6O-1p6swC|ft!%bbyg5I1cVf%XXjNbz*VgDP3rREYP zMn|mwNc(cHsd@Ku!NY1Rbwl~=$GJ|E=N*A3Qoe_uwYk z6IU}tzMMT)W>tK?B+sY9^SJ3v@hr1gtsNQ(my$0kck8qLGre#pyJ~jc`3K)#od`T% zaChyL*D`Oe3T!Il2}rGR^szsv%b%Xv99A0d5|?(refGsmo=2?CJ?^Nsja=e$Rh@lq z<7tj9^MCK2#oKdBc1Fnl`nnl9`{ej@d9wRIPYiqP{eGDp!%v0EpGPYWYpcdRS?Ez- zEL>!I^XUamS;@OC8p+R(taY@x#C$GbW-O!gA&K~kzD@rX9kw5cJ+bg#mD} zp(f?E(#(_}{@pv+WmUQ+s_bxBYH-dceM;)nc89+X0-ODAoV+sMSmyqXyNj9X9PhI& z+Pm(h&hu`>C_#5)}^NF z4`_PIGMs)Jb@s{c)b2l`7kgP$WWT<6V#9t=|3A_i9?51(9W&=tR~%}=_Wb4^f(F4tn_29ZJ) zkG{w~cb!j4w=`vkyZo^=-`Z?sdi{d;S8gw+WY>ebw%HBbRvB|8T1A6d#YGLvn;(Vd zI(%cAx~@{(V!@eTp8T8T-cE2&E2^G${p6WL-$jl~)d@^``cq&}dBXN@)68qXzq32& z@KsmZ!Gk%xm%E_m^hRTq>07qO9-evPqkMgRg~s&HEXw+AfvnPh8+4{$ZlYhcNO!>RRv~}c0qeQcYRNPy6%Oi$qLh>--@1gJ=(`}!0OVp&D@%K5&5?* z&2nT|gDz>GiVexWa9PJ=+q6xmltO3+~#{tWmACzZ~jh6b)Wz5`%cvSuPfcW()V_c z_NGJY9{wqsc+}zbtF(4i@yACLb0n^Coj!l>ip4bPe_d}+Z>qM;-pEkLKTtfq@9;FY&VN>kW{T39W)F|JeepY=kJ@mbe_B7jhM$2!OBd~!86Qt)SHECa zy^@NOyHUCM(#Hk=#VPzx^j@%nWlpNP@2z7$mqZjDy0(zVbDcEH&kcKSD{r^EXSBO~ z(T(`~>1px(OH#%EhAC#Oz5Mpwn>{w4&z!0KX#H{J{L^dKT=&{@aqFwOzaFh*{U2~G z^K$oky||D^`J3dI-tAr=x97*N$E&X$-cbAV&(FN=yC>9KXx+H_`CR)mw*McM@A>lY z*SF=?g*$f$t@d98U9 z{wL_dQ5UwYljiPtcDMhDMD;G!ct_62&vt-;h) zc5{dCDV!3gwZyj{ndg1gS#WEcqxx;}Nz<17zu9A4*mm`czO}Xf+W!9@hWxuEGtITV z>^rSjxO=RTJ;`*_{FY@|eVL`aP|jT8xbk-9>?10Va*JP-M6ZrY)irytf7_ZL{3R!j znMi$~ER%Zj(ysNpCyF+$5ZNo~vfO+YOM~Ow%y!wzS&xMi=dihT96VutwDym5XiH1j zdbiX12W;lfN;q})Q~Zan?^HzzEM&WDF_ujH_7~( z(T=HSA_N2ZcOAIR`EAd>58Kk7o=RNs=5SWmr(?F~3fRADm`Bg)oqC|QVsE_X`nbI9 zTxULDT~pU!CO<`C?T(uZ^)DDM7Zo%S*#4=jsU;JzKsNQLlSvFm|RIYb@qu;ivrs@+``7H9>?4C5SZAzy1>-|b|_M6<8e483F?n;|H$f*;`?2Yf(;p5U*9#C8Gz#!Cu-NV0@$Q)F z1C)3EhJZkb!>abUmKY42o|9l@+)rE>Xo_#*~bvhSU?!sPmk8{rrnGC(R z&pLY6M%|;JH*}S=MHKUdbtgo;Z*FvctE2m7=AxcjgT@67Gcw{*Qzx!to6g+c`(Ty& z<&d_`pG5vlU&`e5sxPcuVZn`cC(=6&ckY$Ga?E#utY>A&l$b2Pg%3sFvrZAWUGBML z&6S$aL#K{Na!sB5?m*}3i-!CUl+AkV%VSvAq1 zxVT_lg!8WHCN5< z((HedyBiK~eR)0ofm@lY>GYeY^KRH@uRWA6CGz3mm6rF%Z`y@SC`nm!Wdn=gcGdZI zO#7LhZGSA(z0lj@?Y7Auetls{`fc;(hvx#h)U)QAyh2XKd+n?~yKGC}&{_5?IC1&* zNgICrKkShnv3wgdtBlrEMIp_O7d5J-dfWc(Y87<+u<>@3okm)-r^>pczPE)GUCIJv z18)A;cQ|(A;B9q9=LJ_A?TkJxIXzKo&&o$Ti*~!#2Qj!TnHF~pVcP`GA&AH$uFn46~ia}J99uh>;L9Cr;UWS zAKRI}#&nlwu3J*%zjBKPk-2wv2J)BO_FG$1)^Kgn57u;xhEvNO`X{%F-))WBdt=2p zwOhw$yROceaXCr;{PkseGc!VUQk}0HxukMD+M|79<Z zeOFP?t}N2idHMXswn@gv6F+{O>%aNsjnu+5@0n9y`F<5QWvuBxG0A%2lMA*#d)C{; zYBDm$e=4{&<NXn~S5g;_#<8C23`ST}gWB=d~)T zT?=k%Bt?XJTHZ)*muYy|v~Oym(<0?HOXr{YWV7a&Z^WKs28?c8i)K#>s^z)0&?Ebw z(eayq0!q(XE{y!t8elf*YI^tV-#=HsmSp-=n6Nikr7gK*>2&w0AHx_9cV4i(q(6J@ z9qnoBgtkrLoxb8G^HtBMLSde-RHpxC*^<2HL;1t#kok-67R|rhWw$c6%sS_i=F1fV zvwK($&5}8g5Mc2wRV2hsbMv9i)0X{vI&aFO-9j(a-6OrP6OOY> zM9&S_+OucFi`lJRk6M=9I=mrqTH~jSvw5sK_2$gPA5k`?e1VluZcVQ^)99dhN#f|Y$&wCUnwv6T+@Hp^^pff6+(lm;z2^&y zOf_$8HdVX+D5z(bitplIX?I*ES$~|38{+38&iPyR`33IHzab64|m?@TQ8d`aHk2Sv;m0-YkeOL4MPE7cHPv>A={>u$c$N2ybQ?dfjajN|100nkgkxDqS<$0(}R1xi4L+hzWQkaOa2+0_$;ID>+__os<88WfU@sR_E|D5@rq#| z(*GBgJkTg9ni=yf>g(+lhxc>|?Q71|c)B_BAkUdLwx=rmCA?`tk0%{e*cq`_Xook&Z+I{PmqBd$3fza_sYo5sZ!N}i3lETVfu#{W+9 zRKeZfG$u#J#(3QnKEd64@BI7wG2sFK9^I_@_^WK+kB7gOzdl;4TDNOo?N{X|d;Zk@ zORM{D{QJ`DpMM|yI#++TK+?Rjx{~|w-s<8??R)!n*H#yozumlXesGz|!2_b(EW$pQ zG%t79x5DOww8Vv3Yp))8{_~RVpPqY({%0Iwz9iL(U$zub-&NRD_*UZ6+?A!Pw%Fck zH`L!=b=vZMp{dN?59`G%ghahh-^t=P{)Yl8cSNk}O>V*wXZBw* zhdxgESF)zUXYLcxtPd)uOK0`-^|G36ymR7eNszPh{-8r|LxTM# zg;|fSkD0LW>~?#w%uG&YdE1V!ldDgCvYdYT#;*+lX;b?+OWppvd_TB^^@iUszI1=S zXNzM>KA)?&9xHkIO^NwSk2;5QX1CWaxu?9bZDLCP(sypJg{Qu`wedVlhwzh?`N0`C z9O`0T9g$xvBhw)>iQ{i#zJA^$sc)MqFWAh>J^WpzqisRQkCm=B?A;D;7k{*AS&HMT zjtZal_-8J0EGK@O7XHorBFC#aU*@Chp{Vt}AOD8tE%bB$cjr9o!E8}wo(KJ@Q)<`# zaox7>pp-!2dASv4wzcnqzTDVTv|D4J!D+oMTW8$1QCCo!_2#+N4xyud8mCK|u7*tc zlTj98|5M9Evv+IMn>p)G+`suH*0RD=#MUQahqH{F@UFC+)Xtf_PaAz1zwCS)^27Os zMexd{(fzkX{@eYDw9mcfzc}iOMIC2FN%0~}{kLrkHG@7bIjOYEJ^OQup2@PtD;lp> zUikX==Bpjrd+)HD1>MQ?k2=xi`=ma6N9sZS$tD-4uNM!WQtDs3QT*PHn%`pjXaE14 zlyg#+o#CxrjaOh@wnu$(VcF3yT=w7R?_9zaU+NPr)Y&fWGSOAl{>VFzsk<51hQ&T+ zDPn(ge|fX2uZQTJl5eNiZ|-To^MK=IfxK+@MYAbAuDW%K=hpfBKmO&ZljN4d-}mQp zulup{Oz8rJ00#SeexOgeh;l;o4g&ny~0_k220@=j{s2}Q?;tycA7 z0$0SJ?^}6!@@&;h*Rp5La$kR<_)Pq_A3sC?9NOf3t=aJX`b5VM)0b&%Up6mfYW(Id z<0{2k&8mO0?*+Lfo7m^ycbab(RDZYKYMP<3W%x5ErSE)aCP^0*U1INv(`|qAcmA)G zZ@d!!AHDk}d4#XquKjv_&ytq)k1OUc3NHV{D|S}nl(?PO?f>rQ`F356k{$wft_hQpo<&9C ze*Phz&fw1a+KGdr7EP zi2vQwPBZ=*onffham7b{g-OECU3D|<4_f(O&~ef%GSJJJC|T+5v1Ie(25X58M`v0t zyxM$xMM)(0a!r+459g|c9>^^>wl4o?ezujVgfmLDDb@1m`K#=e64N*BI2#~a_WzRJ zwCKlcSFhE`VVm3S`T1u?9wA|U{9`NR*%?|wcyH;(3(px4Yn|k~EX;U;UFPP5FrQlii+Pzd-h@~LOgp+q-Bi2z;Zuf9LS5GqodP#4%TE+ijZWC(_VV#d%ca*p z)bKqvu~I3qy8KVX-X*i7tI#S)BL0QDh<#4yMB$7dYfa%5RF#(tn5DexA*^X>#e8n(mXQ4l7fY@9uE;Rv)||GIi^QZ`zOMPCn;y zxb(s8Bb&6v|D-%`d$7CSZqc;Ae;(@xcr!AIFylU&8FEas0K;2H5DV#`W|%hYM>T^K zgYc3@b>x)ii#WI$*>@dRtZ9M zF+i*eLe&TvYev=%8k~mfU|?VX9i9x~gIwB(O*>+!8rdLhhbbcr+J)aB$e1^>ap>*> z9j=Tp?k6KsISJ4G`1FGgTSn;DWWuH&RC?euLl$BHG-zXSnt>&j(7gjXj2U7YD41su zGKz4#fhH9Y2HqsjKx{FI{jg?;(F_br8daDfi5Kcgh|3TLL1Gf`(ane;#(owj!mf>+ z#M*`JWKLvzK;e&m=pe!#170HRalvy0A-YxT(GHVBSan#K2&=%yI$%3m3f&&`10xXj zxXTc0j|bXuipX|g+kTF)BUXVFJ5V>HBijOs9Q3u62wT3Hl41+W%1U%g&{s4eEV*h$ ziX|xPo6s#mpXx(cqUb_|CCC$h=tiSY>>!Npb3-c7kfwRiO+asKB22IeLoxx;^h7rR ny$yyiAT1op0C<@UDpTl#F%P-SzeRldXN{EYo~A+y8|q?n+C%K1G_b?@^gcgFnmxA=FUSg2BIzVe)h6^;Qt!G{8LF8LH3 z60K7A%GIAf>BNhy2ajBCy{}yPK*-Q=ez2YVyVWz~Rnkl*A9=;lt$k{GgrnZ!@;!&7 zRXATf(RLGw(wJ%*BH(Krmc+ZE)9`0gpXbggE061)_;eu9*5JjPl2o_Z2d8z(?U7zA zaM#kn>RV6Ov=)zh^IpDVDUs4S((kc|^%*B~=I<=cX8}(`_805!m-W2Ad{xEnRa3s* z`W3hJ^Y@a=YOBR851vf)y<<+$u&8*14Eebl?^H#rdyxXuKSzsGO^XaK?zpi%d z*teLWm;LX(zjM0hl;l?=I9xwCyD+utYW>14#`o!wf9{9h$q zX~NND&~mX_u*vnFssA4a1NG&?y_c?jl6N%u za#C9~j?>>ou2R22`@#7~zH1Bp_RME8Q1hQ1_Q+mE{ubZ4fDh$0&oWH(7=Zi=gkT`Eavu{_kOnK!z{0bHoH`f&Sfq;lmEHmUh}?%>eFYIEfTU=YWPrS zp5t|6sora^zpnEO*d)05c#+B8{X45`_I-Bt2+Y;`x3;7H|Ez5neUD}x3zrwj__yo) zm3>;%8`_FzFVEUx{~_bBz}!0Nnrmm<7PJ4(-jc-eO{vL`JGwf3`myn+=VM9QWyQG*J_<4n4rorK-N`zBmEw?mujMM;9^w@87#33F_3SgP;6 z8@nNnC-=v%OV)BuuT9FLCI{`h@Y(FI`hnGJ7Mr`@+WMpJy?uZ;JBQy>XQA6n3=B&+ z85nS95KaaLL^>g-g4SqT!H~+So!14RP zgYR@Ru5I+(bT^0j%Q{n`C9a!93wC{tbv!LTd!37r%F}kf-|wu0Ch2l+OV)R04q^M` za8I`K|NX#CC4nplH{0*kXktIx@^IREfwUC?X984Ycu%-*;LdZ%+GEr?KmK5 zlQnaqU~I*)Fb#)`Emw-wewc6a-+r|rQqT3ppMUKs)ydNmxe9sYFWkyqe|`5tm!yiL zEKeS-o{)X<#`jQug$948fEzvkqBn`&ZejbX;3k(X;T(KAFRM-CwI>&nxJ@QQK8* zzwcjdk!;T)$Nx$!XIZ(wPHxifIkbB2eVMHyHj}^J?LBnljgDhvpT5YqqceZ4yEXN{ z-aYoC?#(uRi55A`l?sZvwo5;z{}A4)7&_&{1Er9KcW>CPn|VVfn`WrqL61R?IOnFZli8gWxLd=kMoFJEwW3 z^q2oaxtC|On-|XS|NDMHndBe0(*0cFiw_nU{3xx6sNDT)%BlL)3;Ap6W1q0ef7Y~= zkEpv5w=d}NwQ_sonNMc!7hT}he6>JeRcqEorF|^s-@_kXJZdvz#gSlc3&xGlu8K~1 zr^Y*9$KSH|yyMH5KIJdmB`kM;+v_nMe_EImQ^tC${rCCyci)#E(A|8tuqfpX*Dg-A zop#^1%)Io|V&|#F)<3>*nbww1XqwF8uUPC|!a1Y5X>aNm5!drZ>GQ1ROJ*&se*c2w z$SdhZEtw4ohj{&8+Fp)fx?P)UMA8RxW)718=I3; zi}ZD$H^lt@@K}SpIy|9n-~Q%5i<)s^zXovRpL*a|F(aQ@?!mKZ8`t?{tmt^ zlTYb6Oc7hRl`Y6pc>A&4$F3LeQWd?NrvD^n=UOMz*~-b5hnHLxH}pOFB;fMP4-M~+DQn{vtbaN+MEB;g&B>3_q+1Jw8yB5z)n(^oHLF1prpR}!Y&UD$Cr#87=b%Vlowhbrr6uSO? zwVl4VaY;(~uQ1-TMTW|;H*ogKdZ+wZ?Im&}Tjx38DFcWQ4{Blr9D@9UzvkG}HS zvo|tU_x*J9)mtmdi`DJctmiH)udOaG{`ye2F7`rj`01~I?|y3M|G~@oBTH{x$XaXL zhN8TGhq8@7tIy)xKG|0}O4Zu%fG2xuw0cT-=cN+S^+H=WCY7ub2>W_1B)KzQJWj+e zI@3I2ujI#S#kngAyhA(BI<5&l>9mjO=e3^ObAR~Fkh06DI5#DE^{$5z`pNzx+P?K0 zs&-4a+$=xE6~HO>>Y>6Di#I)2|1bNyXHKzp+gurzoLyUm#LA+pPTW=ucF0XtUg!Cx zQz*HeUFGf6396o)Q4Nw0BK40QV2*QKE0fR5Cc7q+OK~liyj0Mx1D79cPYyr0>C%?9 zFZZbYUvT4f;_;%2!#gX|bzWZV-)1ggcyiUnhX>t_^;6y43m-Yfe+t?hzK!8~ac zl9-GOEq5N5?Q-|ry6)hty_;0K_Wk(w^}T+kHS@E?!|aZaAFyq(`o(Z3Wh%Fj;}f^i zgqEOYZS_mWwv$iSn?3f4IS}<{`rO!Oaqa&vsPXTT3Y;cdSyRFIN^r|nK2gTK(Qjo~ zZH`K+Gwyt2FXiiOzmsjQ7qw+)7u4#SxCEHi*e@pb1WtR#}JR?PA*6iLSc~WFT z%Od0EjFQ!bm5r2C2Q{F{9|2M zuxi&EzCW@%l5;fdv$CUpY`k-lZwntMQ{Y9*nxM9ZMfp zc3iTPWY9VJV(y6y=?&}E+0R|%_WO0<#oGYB=XtBObdMIi_?%pC^6fIG#+!%Umu3`j zDC;h5cz4J!iD|>jKO3VW87J6y+&$qd{K@|CQl^U{%p0cIO-VV@+K`vPR$*~SI+{!F zT1uEDPek+yC&y_0M@)PRgtu(7ljCeYw*+cQQ_l+|qQ$#lSWLRusCz9eow9QB_4`UweoNI~dwkqdAlU4-zSITvm=#L{ z`9;h=avm*sI@4o9$_=wETy^zcKb5?@7z6JgxaQlCYo5noZBxN=&+($`tjSe&q8ZAE zJ_<((?(up0?q=3RVNsXVTXK(U7ay2mI^$91r%$O@<12UE$T$-Zzd-tQ8K_VNq?=%1NwqjIz#U^g< zpy?PDwn<5}h~0d}wWk7nrsW|KPF|}f{^KmO53@_to|ygAP2Wgjri)`*?iT5SJ4GcS zPcx5C`*7*6dNFZ`uP~ zPccT;M*n#1~Sn$r2JKi`b8maLMeCnGTJN#C;P&>9KN=%Dzn(aH_4uosX=>h^ zWu}UTcuth`P-tm5cjQrrID=(NFw^1JR~e>pK4iaeJ*2ufX0h>I?@xQ0g&!ZEexT}& zn6!HFgtG+|knHLTiB3%>QX zIP~9dI2V&8Tl=`v_1^ZUCiY2&6Q53&JwK)RkXYFTd1LmwUMzS2Grx~HV04v#M#6<6 zo<^m{ratLK-WNYd8oy_ZWlyyJxuD}IYwL=Bv(jE0{;q~BhPt2ijDbC}Hw*>YZ34fo znUJ71hsXDT9oOzt`|>y3HIcQLyQb&H(@<^cl?U(r$tkngpu~A{t#sk$<~OB&QNA}L zqaEg7xTqnU6+iEX_&cFn370kF1sVS}OmqqJKiwzZ!d%$?dbRF~^D6nP=G;%}U&paE zPj8y(FZ*v!d=t2mt*lZnM29)%ss8g(crN|DJ7j~>_HD;@PERqgam#dj;{Qj|M&DKW zd)^ghxvhcGdQ1r$7t}mrabNL6=0Kot!qK_;TPM#kvV1PkC;I22P%x{Z&(UQQB{YIF z+-jG#xG6uKpFwJj8 zxl%7WckE+-QziWBP3xW~llufRqpyfxeO$+UXVt?Fjws8oy>}J=&6NoWsfBv5fS2tfh`}fn^ zuRN397b;XI-}-4gp(y?Llbcf=56twj+^F+YTUa#8pVMxN=+_yVFRnyxR?_gC^EoZa zW`&^92ges2N2lK~6)wJaDE+P1K{g{PRoQL9Kd0Q&_q@q>_{tQ=<0-FG7J7#4 zOfUUm$Nt%K!qZAySqIKo^*IM8?erD>5VCLM(UntEA5`6(a{4=4`kD~=R4ze|7YsKe z6)uG7f1J?%Vm9CN;tK}K8v}%9UHC0qp4bt;Jnh^c-zSaHFD;%l%PErrPZ$jHUFPiZx_tVSI^_OQ=&T`F4V?3-hV^`S2 zZxgStKhx0t=q>Nn>Aeq^@mwzRek(goFz9S=0NJ z?YnrEPy8X%ww%H|F-cy(y;Eur%-r{%!|JERvv%hTY`xA)mY7{#b>Ho6e*cCA)*m>h zl@w`;)Lnk`)g+5KjO||FA;!JhNtYWZ-}{OR9*bNP2ij~~5zH>q_0p1AJWyZ=P}dp0*>O`TYM z{JM1w?=to=)*X4d!dv}fi*~4)ny;iwagb!eD+XV^nO#y!)m$4B&isD*_xEe2HT$Y| z#_Zi4z3yMt-^*WL?Gvz%y}$Rb;Fg#_8*29N`9IU?#obSJrF)-UXBUe*_Vy8<%(sVs zANk#>+p&9ZWPI_~r?(HW<%>D|movLs^4h`N_>QRGVOE=T-+a?c#a0Ep7hC%S{-_=~ z`)sLAZV8`-pq%-Etz|85&P}n}c9Q4Szj;%aZT#u_I@9>{#_!WDYxvZTy1w6f=S7>| z`RNgrtQY3zDcDA^)m*)>LAa#F&sutG%WNHv1&Z>LC0VyK65^Nc(s`6yZYcTm*va$h zkN-AxGM)P(y;sr6{ZwwDoZx%iL(`b|H9mMz_NS)KpvvzQJ6~$kX(?an-<=FQ!?qP! z&wcp#)dw$!D$4_3x!zyfd^_DkLt$IZ)CQKe^j#H-&s*7Aj?I*Q(fc^-bosN0qseQJ zML&M*HhqnyTaV;V>ARKbX**{5^XSdnE6gADaHI5L#@(jNZoO8UFI(5NDCbw)qbUNG z2Rpj12bnK^nx!(k>W$FOg-R9AdJpO^e_H%7;64QEDc!=4?Vl|*0ZXxhD-u*?7Q*B_fc+G&gPCf!kTG6-)u{Qm591)O5@{zCi9TpGf(tw;!%fG7(7LZ01;=Xx2O5 zNie^%bwl%+>Fc8&*v!!1xBn8OV{-Gy#W$1HkE~5Gk+^9rJm;Ky{+1HoGHD^p?fbG1sVk*HRSHMUDWRJ?C;?yHR1URN)y`@ofO?CQ*m zJGba61}a>?*rhqwJ^OO*%=t3RYR=((XSMhPyD#tj`0T++H>(Sbx)XAwPX4j$KGtLA z7HiS4K0G`k{QO=v_x<{L`41;PwZFfBJ2Q%*qw2$Y{U__+J4HBpj2^DOtH>g} zaMk-?oBXQu^w#-&Z~w8+VcKHHAMf>8OJ84EX0nRoAe#Mkh= z|D)2BSyf>S1x#XQeEKVXWZJ9qYWSTmy5lfKG5P7X?u<0~uEHHrcUOEl#dUWAo3D)C zoW>%P9d11H64%bSSMzIne1I>9jqLl!d!HWKn=NyGiDLVfr+oQqEF~_bKGJ9Z@jLX7 zQ&sak_w8%;UwUlkv1(2FtTz9N`vtW0J~aL~_w?y^4W%#294s;W{`|1HP;vLC*^~u_ zZXru7luG}mIbSxil)TyMFwL3c`}w^^zvOoO&Z_+@6tYY;{?LW_kL3Q%H5QrNd&Td5 z!6EPFKaI;Je*E{?&-_ts^V+GiRtPlB$>2T0BeV8)pFn{F=K`IQ(5|{(Nkz%ssN8(%9uRFd+oWn_0`;8k5;n&54e_jxqH1{T*#yRP4Y|ccCU}y^W)d! z)z=PhsQvlpXWsVR6KXEBZe0C*uKgL?|BuS|eEIk5+j8r|ojZiq=ZS@X{{8dpBfmZS zc8b1#w@$mT`tP@I&tBctu8R2>9sYUu@7q7WzklI*i!^Nzqw%Z z%!2HjrAdoZ^x5uI1e85)c_SS-d*8>`F4=1&=B{c9jn1C6aoO?EJKb@4Tcp>-^?hMi zoSX3?%k`D3!K%fA?z} zN(6dG%)i%t`^Wx`Vry=kh+8KTInl2yc`x6h(4_5QYZ!Mh%Ij2q?kp>tCBuDtPUeY2 zVMW<{m#&Sv>$EgFHT%}@H?zg-EuMeo33;-0ewh@zxx@DqPKnc6;@gkR^S@hBEyZS}n+FE~Y|9=ld{#}xp=GtENoz^SdJ=VycWV&g7%d)J#%u-$` zXRdHuc{_9V5tT=|#V<;tS4XAlnmyRRZOsqFq`pse1g-FI69_v6s6_wZ5tc=w{4-3;?p7lU|yzy0#=eed4_77=Tkl$Db6PP{Mj zcwrZ(%H9&5u;aFynZtDUmDW4oD5;4QgbJRUWPZ(P$J8?sf`R|Zs^qv!NaJy2V*H{Nr7T;6uBbbF;;R-3K$LkpL#scSHkpQ5mK z$IXTM7Yvt+3YrLP|J2oSNPnra_BWY1ys}OQ8Qeb!xTSBrsbNx<9lPGUrQs@D3J1&T zQ2trDUUs~HTXqO?RhgOnYqM?Id-_G!?m)Q^KEK0m6D-b^$S6lF58rj%@c1@+w^uCj zZ&`%23RfIj;P~lHg3~?w6p__tLC+gPqcd-&dYIQt?%lNNwz9@A{xy44@3hG*n=V}{ z*So&aZ`)K;^$Dwd7I|)VPny^^CDZ%$ex*75J`a{WcTDwx$^*|O>Tl9@Y`7&JHTfrX*el7O zyfue^zK^QvLd6}=KA-$Lor^1XVXwN!x#xyVhThv}9X)HK?orSiy2{xiih07i6C&O> zH#)!7(S0*>QBSQw79l<_ex(m=DR@Fvod5#OqSomhobLUr-<7w_gu2(N=@jYQ%5AZrcQo$p!4-bL;eTK z<~<7=i}$7T=xmx+)zdX2&fH2Z@A0->a%W!%oRZG87m&E+vq;E1*l&H+InEEBn?$m| zFYy+tIx7~iOCD~Tza)RrpNDKNRI@AvZRkny?GYxk9HyKN-vRLAh9txkNR ztU=w<{Y=lcKNjj<=xyk= z8r4$0ZU1()3Oat+cst5YBdys}W!+KV+d_&iWdX7QH~;H99J_Jwwz{J8f~$>oMxU0P zo+!0v<)fWNyWg&eFtzPDze>%9`_R?7R|0m`Z{H&ya&q?+Ex(Lg%CqK94lCZUO{_tL zTXAV{oX*4tXXY;MGuz8`Q)mXqrAen4;>vd@+&vk7LQ(uN+dLk>qul9lPRJSZ$8}VC z=S}d|VE>}@-*1`Zms8w|;gkNIIUt_(fAgHvM#9^V?Mz=|y2~@yEh+L}xkZD>+&eo1 z`Acs5t*t3*xVGpAYq~|lspSs+lUv2_wnpu}vErQCt>d#@SLe*QoFsq#`ZB$l8KF9< z&R33HQaK*&(LS;A=NiY4US>Xa%CSpIdFQ$5`)D023rR8)l-jpXVEd{Zlh_Y0rFWjs zDCh7w;3oU?yvU+?3C%f@kEUDXvV7R+Ecp81|JidkE-&4F{-eC(cCG9FYo;DLY35Z~ zynUIo>QhdKmd(>G`RAW3uD>f7w_Rzbr%U|e0|%tOt0-t!7U}7{eEwqFB;(_WA3x6Z z-~94MYT=sq%&D(@zlxhO*7Tp4WWDgo1>2uJ>uq8+85!e072KL~>c8k~m!G|S{Oh|9 zuay!g3RSt~D&L^Z#Zg*u_|uz`w6eagB)#GJPsc*c+_UmfW#)y8G0RVGM^mFIZmEpS|{u_Ox|E+oteNUvZQ9s^?RoFwa*i z(|@yUN#66J{9$y+{Ka>R=3nlzTNztsopVX^JuHW2$s9-su=tiL65^)0`OxNR z%l$Jr&K=LT%;*|Xur?AESFEz52l-jF!0 z@zcfGJl40KN!~4ZJ1&!~ zKhEhe*;moyX4_{gwgQz-lcXhnRHkv{N{&rs<3L+e5<1TKoMC=NY}_tX!qk7PZdwyZp+8Q*H5G+V>`$ z)3a`gY*{RLQ^i+(p5NN6XZM~2T;}uFD&Sky&b+(kaA?pB%O6qZ#ct(__r9Lk)R((l zt}txv%7$mQ-Gx5yro7?zOus0reJe>mw^j5hJ4P zm+$hORr`xqENww(X3UY9>6taQ?umOIU7GNToBO%j63*pPPu=}RgqNls3Y^#Q8#C=&&yl6q4hQx|@AK=u z*g5t5%HXyXgWY?CKkuITgxVKKD)d6;O=i4lOtneylx7g;O@P5{{8)! z@PL1hZq|JKRkrWP!(Yo^AFWlb+qJLutMZdQf9n3F)%`dAed+bjzmI;Mt3O*HX0nu$1VV_HympklRVe>&+;=-)8SC2gZc}e$A z&%H$dGY&Cdl4`{-TMDS}Dr_ozEAeUW%FTj<)ZTY^?RA%po_2LymqTZ+P zW$e5n%m4BDlv%7ELG~Lo>cnkc?daz+3|u=sceaIfvpR3;>xJQ~{hF6veYMBS`FqwS z&2zO&{D1wM`CQ1v^2L`)Gv&LtFWToOH{pmg`!AV8AE*2)SySON_laoM2bI&Mv-(k>zqHWS+|FpJl1D_(4n^>!G4p%tjE^JOjvk!yFFNDCa1EzZO7Ni z)u%pLPQQHP*M@+!sePQKZvS1rA6&wE!|xYgx#Qdd4ox?e^ z+iREHQ{LD%F(rTLJGa-uQ{UX$c%G$0_{qxr;EWp%buq7w$gh==>5!Sk@i#GFKW~!M zw@sB7Z06-2{;tx|wxHw3O4l3qZilyvKiae`#c@?fg-?6@GnY7)6TeLh|7L!X+IK-;ZtN-A zt+CJGwBDAjGj7|cD=5u+^W18O&{02)(~ob@N}-~1A5 zS>Y*S>yxmEHS6WVL=S<$GjlPUucD@by;rzlPc;(XQ{#zpd?fyjC=U($)9CgK_ zj?qvE$o#^s? zQXjq}^`QP_lZ(^Wi-%7s^{?G1es4$3Z!!I||9?)(IVsD|@Yb%zE3huxqdvK??C2LR z`|tC2F5!wV^@$ehY?pSK=&EXewNwn|MJvHa!cXw`}4Wi{n&Y?bb&$vR|u=;q<}z?%Dr=V zgWv41o$$}FH*u%o16PKUgw*F5YR~TT`QB)G|7X*8#T_yqqvJOis^2}9BCEdJd#e57 zhd*;B9ldx;^2y_87LA{KKAk9eC$;Z{qT|C>t9mhkE8@@ht-L&Ww(6y8*|TQ3uRl?I zCjQ%xpP_#aZF0WWZ1{eCqT`3@%QUtxn-?-Qesh;`m13=C)j!$yg4~i#?DOwC&9@7x zzuRs#&Cu8~{F#%|cfK=|qzj5JvG>I3w!is1|5wU4UWxyY-u;q1!q;ure!aeDNz3}j z74sJbm;d1vJF9U@+|KLvfA@28CwE=HH#bOFanWUC<|gKcWq-3;em7bvWPfRoS2}jh zJMHJYA6aiwAiekbr}g7&_!$_qbdh`S=&NY>ktf>y{6jpQU2D&5EUQVKvGMAoP(3VNAD!1|HT}KL&c6OKI$t>5`ONg zn`wX0%Kw6nlV*{DUd}|xN_USXn;$n=OKdng({ka}=Hn|$BDt4qs?2&gS0(g7Zn?2_ z`9JfstxP4HQL0U;mPgNDWv`T&zG=tV0NJwtm-MDZKVG|ftws*p+-~2u?9QB>xpGql zcxop-_h6g-H}HRQ%~##3XNnS6H|@RkRObEfI+^2srjf@ty|UORPn=|X{@3=9nM zOvtg0zA6zV)^iifQuFljExkh5u7Diy5bgOz>3WF;iOCtMddZ2osW~K>r$dB!U{iIo zQcFrINiy4tM6(O>bM*>}@(WUnN-|T6ea~#7Lhr7HSA+~nh)`@dYyYFlWleT;rr|_%{J*);^vvb`+jK8ZuN?^ z{0)xNo&!fwSCg`lyVe%G9YCDu6ui#Sh z%>D7n4<9(vY+O5bt}~nXebVfmrYX;2oHehqo;e}XotziDS!9QTV;E!L41-k8iTD3_ zeN4%7nAT)*zVcnPvG8dXo4gG#PObawWn+JO(Xxw4G3-g=b?cMZ^Z%?f{d($E$*bja z-_C!~RhIsStHmTBBWLC@*Or}%D_XQq2cL6k(M|J~7wJF0RnXG3=gZ7wrlMZscY&K5c~ zWvW@Jo~_>7C;LN0(kH%YTK75c?3T};{dY(exa?Z%z?jTr)hy7K$X+Mca=75S)K8N+ ze~kWFH2OF5%d;&$`9Y)QBfEu6|2RlXYV;N z@%hcq6SXV*CNf(2Imws2l1X_Zs=y^^1ITsSt3{q3cicEBiD3Nlv=8)4$hdOW9^l3Yp%vIFJ3%#g9w< zcKEY5toi-ZwMhBNzPGwp>RLa_7S}Hqzq7Ac^5C}Zs_SJ|esR4rZJpiDtiXDg6|9#wNE{r-18%YW~`*RxmJ-757zUeD?B{N|&b%3kJK1}omWa@~=AH1W*5 zYxC9|ufIBP&a`E})xT*+U;RHlcb8ST$g%vX*DZIaaN8%>=(5~o|%h$ZUyGel?aWtv37s- z=w8*dN>jmay;?7fHpcu*XZ>4J=5w!l;tzS_>J^-|wORev>sueBtu1$5T46r%IcJ^L zmu=E*#aVN1P5i_3CgkO>GfSTs zX838(Ih!%#+UmDUQh(0+V)Z_2&DGXJlHo5xtKW4t-}XP7a%{4bVe#f#y{S46f)Cx^ zt~`nRcF?A+J2!5;7f#5tbIuukFNdb@naE8})Eu1L0twe@Dl!uDKi_+@Q<@Z8OtH(MUu&fFlly>xvs zXH-hw5tSYKMJE1n=OdIaonDpoDn0vh@BDAhTxYOEzVSQ!}Rh~TR{g^&x{ z;?$zD%;eN!lIkQetS00arITceEKXA(6){PMDHAdbT>p|}q%LtrCgxenanqd1m!D`Y+aM|#*Qpny&vQAjTua<9%e6eQXpg$g%?V*X zw*nUPGOJuZC0Y4a#_p=QgV55%ya-Ea0o60gRW)9V|2A?(8b7^sPp@&$^mR;qtCuW| zn;jp*;Q3_dmm`bRR(@Ex^Q1ux*JSU|rfsr4I@<2L!gF#|Z!>7D+&)nzUG*EAb4TkmSN>h5JYHo1n&j_KvO{x!?zzy7Un@}NkWE$CKYdS&C8e97&6P77CMW^0BV zd%x|Up+fiRmWAv65@LGHJj72M3gvA*c=puJZ=dt7f3H<=TiR&$G|y~XwbP8kq8|pU zj{exZ>SmP6m)(=uHpa0F=^jaW#MQa=MQwVrVeJu?U!UbdS2JcJsrh z44Z_yt|dAJZd#U~D5M&lu*dD?RlBA~||7vK`u<9LB#mV#EOosU`arX4qXcMEgX9gzQU^85y`kS(Y9KP=X%HgjCm zFzwR@TU%S(<<(Wc&eZ+>_fxwe&?ehi#@UNUJMlJ%?mk*M0VF5IYM>g?3S z8GDp+lrKljNq7-*ZrN*((<=)zck&$$*x)#0Tj;m%xBs5lw596P}-F9bFVUw zu(k5cyrr+K4o&2pvt^Un`}5rSSH*%3-q|4I?Ps*d?;Z1V{`SAilfUX4wp`Ae$aQ1l zRvE+i)gmq1PjH(>K8n2lf3B7I4ofm3g={_ucO%9rOSHE%q)BnNct? zCeuT2^^!$d)8fm0*tVS!IKA8SyvXHgUJtLtSsd1`nR?mNs4sK(zNb^3wdm}2<;|2W zpLnrQM!iJFaeLoli)D-1FI&A!bUVDJ?{~!liC%4&tr?crXl2a0UDh~TU-H<0Yo+FAlhbCFNbgJuI~r&F=hv*j zX`8anOvtc!eq{Bm4=dCEKYJFO6VGBR>7^z4c$sF6(p`>=?|#<(xb**Y-1eY_9&K-@ zd6i6eyQb^=Cv4qZIUaW1`iqa3ov`TQJgRW=>01@|&`E-EYq{F5wY>_>e5d4<)PHQz zi{sx_Ot$)Zo;Y*gDD@tBlIj;`sG?K|Yx9Fa@V>jV!i*+g~1i;k06N@JIdy6E!4yT)cjTZ@F;2dGeFet}ULk+B4sH z@#ZuvWi!7pN$Qq^##h0I<&EDnCkcLHoA`#u)Aqt{jcb-GuCEk-E*+6Cz;!`9=>0*v zg{8uRZQDJrF25!2GQZX(+U6VM+mx)EE$1A5vCG^za!_o7uE_fp>r2|2UaIjK<}AP1 z8#c+ZMBw!Cj*F5u2W=+)^4TEPlDA~(7VZ~|k2ra-{r)|1k)hB3gN}1lb=|T*9uT$% zcOiHDXSpBF%)sEvj$9(5=VE(Gaxo+iZ;iMaEqz_|f2^XR6Hi=3(&=@%GWkieb8fv& z_n6zDbGs-aMojpPMT*3_qX#nF=1C?#u8F<0hO||M zlG|9+o2m_@+O)r|*)daex%Q)9t0owz--w_5p@OCQ!^Nx`9(nNx>W6-`+?YS*Lx{wD zp2wMu-&bbUNX?)4;iiF|x`mDM!${8at{3{wd;e%^(KpKRwvn;Fd$(T8@Sd%W&5Spa zl72nk%fG8iWK}P}8X0OBV!V`R=eE3MyCkw6O?$ax)ysLoy*lYP9u-7~_ZHtND>*IW zIWHk0-RZ=C!?shuOM}b%jYE#iI%ml8_?k*!?z^kL_vZWh7gR^gHP|7LmU+ZYHSNn= z=H_=(-Wim9jVkjBG+t$PRMgkE*!kj`l4C|YUus>xQ~G?$j)qBD>+;e{R^5|bhoEymY96?g!pqs$KPsoKATX`Ue4Kl=+7!MS3RYF z*4JOn{GjjIzroGqrpb26TjoX?kx_S!t4Bp@8}u$byZHI6h3PWysuu`2YkpywXdJXo zQQr4%&?M$1qUV2<^Rfo&wRo4^ljLbX^+jrC#_xHF8gH}ixARO)-6-<9V^!vz!f)jz zB?d7)cU_;%4!aoj(&S?}kM`6>E@4%=6VEiRmem&G=kA=SsGXhtXNlgW{OeVFZnx$d z?Q79LZPDf@dH%7s&_1ol**|u*yf)g`nD6ytT2KCCR!;p>KltJjEH)eyvz===MflI8 zS*CZE`b_*7TjPJ|d+HwsdyzNwDi2j9?ZsrIY+BpWzMNT^U8RAMA5Uj0Ufy2mRPLf!nOB~>ZrNie3ukZ3m)G6>0$c5lf6$iHf85qG+o(==M}BpF z@{5zNjx9Oy#@RVi{jl%Cu;fHHv#9A()45bFZ{E~+Ec(aon2lJ<9<6CIag#S{)clP8 z)93ZC@A1C>28)j|TV~F>(iTL@V)dbIy1NaNqm?W_zu99n z`J>pseJ)#fWl5H;*R#5>dYa=9|NjJwvg7AcGjyj~{S=9HTEC!4dHNJR*DUkC)H9Rj zyPtl0$#?s0SN>_&CrPZ5@k-QZ_`-H{(xS8X%cW(@HD;fTFpJ!8dGzj&Rp;)0k9*v8 zE2J)6U$W0h+#uw2U;KiaOVyLk|316Gr}K%_UC&F+e*Sia%AbXvr5wBDYqU){EY4w? zhR5$?rKjJnd9~|~TIIqemJ?LpeP8!~+pir*-XBzYe{|E1OFS-fP8YrCx)@!u{P;EX z;2PE~rAv*fbxuFfiWHQQlUdlgYF+tR+059t1>e`?rtWxqE|9%%-etP1J7noicxF zmfI4ov(~OPm$tAyv3E-H@csDoyNTzQuN$}CNQx<3`)6iPL2F7?V)D^iUCW=F7Jd+V zpO=2_%DHFJn_me2?ppdUOGW7Wm%Bd3(nr6PMYS2E`E$mejQM{z(PCesnP|F5IB&Ak z)wEqM)eGAm+Rjm0u<65GZ@u{^c0GC1ta|9x@A=D&7QMc>cV&~K=H~N1SYlKAtWW>R zUU%X5*>Jh$$>pK`t*wVX>w6VXl+kYB@xOUZG>}p5;Hu#DIZxiyF+KeE@PE*pC_zOE;b2?E*73$bR(wGro>xrS1G3yukNBU z9jUC$Sch1?uZ$-9nWi~6Kd5n-BVKs^2Gh2ydGp;(q)sKWFZMLH>Yr=5N1tKgQ9ZR8 z@5R=9>oIkAzW9Jis`y59W1#=(YS#5TGd7gP^ZjNvF_U}2vsV3SLZIgBM0u?)-&02x zExaZ(OY4JB(%+^<+m`CKhkZJhJ1E(L(yxtLn3pnzG=(~>{q^5Cz4;|Lf$^T_kdw=k|tEvXI1g-1~T0T!Gon6(J`{-YeMA@Y=6%C&f7;Gh+ zWn?%bEIN-DN}YeiGxMjw%4_b2zeeuq{anE={!zc@ajZ?-f2Y*ygOSpD8yS5za-Wz` zb~#7JIERfbb5fd`PZ_URwb1mvGBqrrDz7Cci7of35fA>ia#HUDmXqrg_{%2$3FZ)* z@4LiRNc70kM!)nI(~7Q~k1wp^*sHYs<(2ljO;ra@|6sUvagVBxRDFeS;e_My_cmCt zu@)=I?MhDCCI9W3U`@+6j=OJ9{(ting_-uagu1pb-nw;x+L;S*Qx<$zx&R1YEP|}z_&+MJn z%@Z3BR|QXvKQc2olrLuDkHC&d>n4t^j!e<_X3qVawy$!{{{KHdi5_s?680cLx&JJa z){RZGvlzc`c>7>qvuxWPVNs3GQxs!Yf0s0x`ys+;O;!->(?{pSz22vSJo(( z&Q`3KQL{Q6xYk-s{m~Tnp!q*8eTY-Kf0Ex=a^|WFiNrYKDc3D%lyQrM^~yZcbho5IhMUTc}vAt?|8N#F?I68i}t>a3lsk?dA>SR<@te1Nx}Yu`Qit% z&9v7!{d@HxJn+gD?%!J&ZbV!wVJp`-Tb#T_>I~1W_MbVpAvWGXmhaf5 z&6~C2Z>Yy3V-)+NJsy|MiRCH}P&;zh;@dBOP;$F1apfW#69a=X3%=xL zM@({aNli;E%_;E$P55|}loU8+=A~rjr9)EO)^N^hX?MxG>(jPu+L9^!eAOh2Cpoo8 z0@ul%I4ELWw)jY|_oEqVnisZiooF7q<Auso@vZk6_S|2$Wm@jd!rSWo^5@T-tNDD^`h9utyr1ur{TU+q{~y`F=_=ZuyuxuK zpLBsr+hPl~#nz8^aIX*k_)B7uhTBKBm+z-NlgqrPaXP>2@!1ORo=f>tpXFZK6FaNC zqpkeZtKE+(%cUnezS2?F4r?&$*N-; zcAuS-ePee_bb0R^Lss3#Wv|$KV=igVIJq{oWo61j>y&8sU448~tk<`E+WRx_?itZs z=f+LpjwzdGn%^yJ%F1~aF7RrLQOwRw$InPxcd@hc?Dm&GQMhd1aj7fCe|P1cD$g`} z!Z)+8=}L;t9{+=}Z_I5w ztjl-xUEZ8E6MnRRskxT1`%C0K#kpbko`!7j)e|@MisusZFK%MW?GV__^ze23gP9>I z)AgQSUbRH@%8W|ZZnf+^Hw$F$-WK7`dAg!v2HP2_Jk#4+8M!%Cb?YAZEX~XnJ+(YU zB}UC>dA`>EMcNlPi+$Xn>FU&5?Rxs}^n;gzgMZtsoAIql(ON;SdKkNL#1Ro$~py1^yZ!@obdwTNR|sCB~Ulp~YVZ`}^DS(FfJ`AZ5#d`)!MD(-k18On&t0~jM-cv_MFy}M2{Dq z)m_M_?Q9%tU6M3aJ>Y;Mul)q!x)l%Ie{AfU zpYcPpZrP*fQgw>$e}&EqWlSx&@7Ty+2S5A1&e56^$HuKrkj#(_=8SN&Msw*TRKF0=hJ6a;Snb3Sa(dZC1E-nM0{ ze@t(C{^5P0_&ZsP1fE@7*Uq1*)xI)S^Xrum6_xsHTPD4{*L5>HKA=Kl#$l;wvwwQw z<=uVZ$0F8G_xtaae9K_2?lA|$+f%3a%$c|(Rzu=v&y?pU1I;Z3yzS0a#9W#&FVFH- z)ISkz_vEV$eCaG4vb#Pd%&*#?;XgBc$8?@0pP3eUg~?UVanZOIy+n2WEU%7}Dis?h z9JNecA)0CYEQI5VxnG3%lHy|@mS?V7^Mv85_RhV(BYBSthfbPMC7=;j;4AuV_2orH z)8|*E_c|--yLH}=ZL|I;Hz!M4{oP5Ivq7Tb9llprSO0wyxzcdg=H{ag_hjPC?;TKG zWB2*Ph4=d%9<95Y{Bh!im8Wl8Cdp{MvP|caf3SH?=COW-Ure@^K^-f_TnA&;~&g~4KH}8oOQW*X#dt5C+@%2TyvbS@7u(= z)+aih&7RoJt~s;x_lXtUckju@-f3BTMXIgUWZT4*y;E-W$rTkEUw58z>tOvp7q1+( zo2Sned|u39E8@^qG5M|NmsaLqah-D;HM4A1DWBC1<+*UscJ913)_oxi7LOz&_@3=v z!8M_h-;d!^tmuinFaAuMe&{^&W!cnQz0IG|#ipmyZ(iy?e+{$!k7A^kMLxfLVWP{D zQW0(uySHN36a-i9&#L=jBeXaouzS3gVmHNoHI(19T z!QhCAU22OKM`%6{U1=q`{@d}5E_XTBt=pf*(yPAUnt7pNi6C!hz#=_CaS)^yu^@(%q?qxA-SL(Oj!ChTwo_Dx#j}-rd ztro4fZT-0Ryk&U&I_%Vyz#`eF-zMy=tGZ;jr_CzA#qa0sgphRssXqZI*bKM@*Bdg&wl03aX~QvRvcc>X%$s88)-d=pk#<`8QGL z#d#Lp^FI@Lrnytpq9M%f3EPtj=I$C|qxTxp4Ui3}Jhc(tKRC#`Wop9Lk+?mCtM>b_0Sg}8?aP6ePe-Ro_cl({|C~Z0Y zRe14VKmI>P@d^#%d=FZ^KO75j=iD-9T6l#K&(57U3go2a9iQ}wFG>CtUbO!4+?SK| z?ANY8P`g7n=sUQbuJde)%~=ixhI&za4JV@7>EIRX~vEm=})+{q|6SAY9>7m*et`zyF_Thq-)8WtW~_ttWUqwagW}(HrMvm z#lulovevF$^wmYt@RHNjuB*4Q-g{Ty|6Y6j*Z+HGO389QmF4nNiYC<8XV*j=(m4?vuWbH7vVV7aHer z3YBFu$WPsTyJ?54yl{&(%b&u?yPAj9Q+|6!-W5G^_eL=1-~2~m--PRU|bN( z@cm@Xejff48>0K<*Bo-Lh$y+G9U~{G*MBN2p5b@%i{lMBa>9QOGRRFo+o)jIdw0_> z9|m@23zaMLMbrFQJ}gPF6FuYU;R;LU&4c*3ez5SZ~8f@QJks5 zu;cTGr&%?u@w^YR9cyIo3!E_LtA!lRYv z&A&Ob$E}7ZX?AqZ^}9D^{EumPBp&qOnl-y?@O%S`GY3?V=vuBAxoXM?OTaEKt($sUNTRi1G zw8Q6)@yTvG%dKj`k<)kPMc1Z;M;k105HFadUAE*=kmJ=&UsyGLay3>>|7x3=zWa#7 z>iD$xC%h%g)-1j7-qTtuCoJk?i)`?W9e2BSYtQ{sbZmvKZb0njkX=(n-yQp%qkh^X zd^PVLpX%MY+f~EAK9+vgx8k?!;l$%HZ`mTvtvAjM(LBCb;^=|z5u!(KPVg(3xam?@ zyxXKg7PVrtXKS__?X?WQV0qak##4x&g8o;v|n3FF5=LIYF3Fi1)E;3*lVPh z85gcq?JvGh&FW)qt0wE?NQ=E?YmT1!a)Gz#PWB?+>=}2CUtnVS&#rc_#aHcK2e;3f z<7~p>NsBv6Ul<6wo;kqp`-fvU&z~Dd{67Q>+aEsva&HY&ma6Sr-!;didHx(aqW@7_ z*z@93E=d{5pc`7ze0tlYer)Z$|6n^?UHYT%Kb+4kQxZ2%f6N)1yRg?sj_H-T^~( zQEi=^_@9;9lLFmuO>6u=v!}->bf%WNc<8|x{&wHcmB%Db8H6(IuBcnb)zlrP$aEoAypk(nD*HXL7-ez|vZ4G~WBS6~fs*1DkG@Zm}XEhpS zw{DW$y)XN@<=3`ZNvl>qdf*p&T>Gc#)=cNQ8LKk0b~zmu%%7O3VyW(RI$M9++6TA7 zgqB>sDZ;&#kwXdATA{f%C%0}8TwC{y<9v2&)a~duE?!xyjAj)W zrChu;;kkfdN8TgVSuX?UWj>lVx&Pt0?^VBl#q3Z2A8+e(bK)7%W5=s=wh=CGe5uF zzHIB-wOf;2m(;%f#Mc_RR6g0VMlj>#SB>`*ueu);-MspR<4%`NMTRf$oVfea%5uj1 z)|N=g?ZSqS&L%GF;qm8xyr}u{!obNl-CdJRw$v2PY}1%i*MGi|PX_tLjKQ*D;2RNKqf>Rh@a&wIR{cg^G6Skbe0=UORGza4w?U5%Sx zdbWh_(xj%f2LE@=zr>S%$}?5?&C#6>+BrY$ZLYW5_o;4v-FISY)-pcL#J3~JA2kX0DGgviEV#}i+N8~=5+N6K^ zw)IliF2Abf(>-?0)zuJ_@r*cgWT$)fh8btqzYk+z%bOT37QXerP+jORGFo zcvmOi-1f8S@^rfwCU*BL=lCo5s^2^FQTI-4H`hP*Sx%zN0SlQmZksfG`n%%6rXu0Q z}n#rH+$N*5km#yDeP?TU;y?!LnH%@Waly{zAoO&@7($~+jdE5_wY^^r=! z(hVCUX9u+Btvhw$a4D-|VPEux*WGUw=4zNLUODf7=h$Hb>FndSO&|LgZd2G0_B&no zZKk_uZLs%W?lRvGtzkhMS$=6OiU={%f2HJP6UZEO=ZG!Gwv%@%GS=Iza4-}Rfe5)Iu#W~ zc55b2baPAZi;jACVO|1P|w;HSr|*%R6SU`pMYn46*k>mXKPF>5bn(G1wEKIMSTim|G zZm)b|ekq&!wB*=xt)ElR%g63upSm@@>U5J=-1(jJKJ&Vs+jSt^`=8M-zg>Y!6|U25Dpu&Rztv|3fgyF?{keIk#jYmwqpzt_hjw|3i@p8xhm;>hdM2Dx(z z+5MCzYyD$d=r||1&-O*6^6q7hI+~By72n!%Kz4@i0_KQap2}4(jT=(!&P6iGve+l_ zD?dq`w_S7jfuH-B{ze5QFr1y`6{0Wi;_~A7THQC#HZq*5wbR_`t{lNXVR{JcPsk&j-9SEPrHgu^vTMRA^hp=H=es#W~2&lcxAZ7rt4!-`HDqBGtYm_()~Uw9K1*1 z*B*|$r??mxR-+swh(4ulPRv*%xXFw$$k-d`>(68;Q0tl?xZ1eS(*T3)gXULu7YSCGs6;OWd ztdZ!8iACwYeoW^-Hh*0i;-{KCsdHA4+WUKxHyUY{URy6@{nX9K(NCkLb&vj|wWf^= zL!&>tE;uH-b3vt7OWOfguZ8YeF8fw*cBm7u`RyUjbiJ^+*6-bxJ1*}x1nu)(x%HuL zbSu~7aGkFv-@fIhZp+{0m2P}~w&wA}O~oreubnb?hvk#yd~eREANj>ISKs^+_rbdv z#+TG`eXqoDZu!6clzs1?Sl88ODwc2hZ?#Z`!=!HE)P<`W95|1zoN`m-R805|t)i(D zId;czyji&I%x{Z`XU;N)-VbIZbAFWv4f{H-er=(~$iQHLvgrUlD%?nl3TN1|Ko#fw zyu8%plKi5e)HFy(W@&J4_T>Nx+wEs(ZFLKOetM4n?Af8WbFxJ)>UVW876z$B+`PcQ z%VckC@TDb7UON2o{N=iVtL_8)kHtrd^LH!l_!-1(`Q0x6x#f4yciZ2`?_=80nI*S5 zLRX<*J1ab>AoSo?riZ(3P4&H@c8#T|cIKPYE(uG;)T{fx9A0pJx}W>9m(uAX#jmP% zYESt7SYuM1l=1$Ol6}<^jtT|;behQ(QrdX^^Pg=cHS4vVkN5B1YcVPC)t1X!p6@sn zDgShHiP=P5b2*naqO(J0ZELQ3*>>RVeZk%qo4_A4=Dc%ksM%TVD6-@`>%FPVlYTsI z_?M>i->l`-wuXntd^HWixs`UBzA#JqbSJyz%bDv*_qn(4RSEcZBXfl&XT;>b^C{iW z)Ycy1-CGxL^s8Xj=jnCJLhPLdes;d``dYi`DcAmheVXd?oNVP(_SJ}J1aj}+6l#5M zUwWe4a-BKHcC|9~MQ$j#bBOay`8x=o1sDH{O5^AshWs&Xk%*D?8#m;`b zH>*i{dS&aUJ=w-Jnli5zmhBDN7pFNdAjEyi)Yb=<=LODRs_O1p7rX6xo4~j9ls8`$ zH+?%M(6%>&$1u6xDepORuu+7!>MUwh{b6yugV*`u#qvP&_-mVt zs+PB;e)aP-)@VE|%e`}PYv7*0kCc6qzdsdt_S^INoW89k?AcSy-zl6ZV{!j%(05Kz zMzSyPA(!3@!%xQ+ADaA#9h52`>EAl8#KgdGl7#{3{9*J|X-QtHge1hR(VR6QSFhSX z_nTxs(?&rhhq>dhQp*~S9RdO^3~DnNgan$RWGA^BS53pU+8 zsXTYi>nHNNeu({>*poN?+S*IMHXgGtycn?W?9uI?W%ceIEcg1Z*IWN;(ZrhVXMWDy z@=o(X^-sIZw^KI8Ub^*m5z{^8wZET!Y_M7M>4tXjx08!cALTFFzNKzn|8Zx%s_F9A zD)vw2KXJsprNe#c*BNJiwjSGGa?xbpz6SnJijs9P8!DZ4`CI+eocVXlfuB>4o!^l$ z?Zd;!N_+MG_|uQqG1bkB7f8@QRVCaxJ?0C~f45!xr@nh16LL`B`}_Bw8GDtI>nCWg z=PFx&^7{3sho$xECf}d5KHvJMY~$~BXR6L0ZU0%@Yd_(feC(D<_E&!R>qVWt?)_Z3 z_y3zG`**z1F%bQ`pKD4#>x=s=FYc#awQpJAzvOFY&QE{Em+^YH&duNT*yXnWpKmEA0)T6L5=)v+L2JfklLw4#-U2Y;?s--U16tMi%^mcCV zkj7;t;qXL6Eg~)A9DF8Z9zT)1sK-|;KsBqVQ7bf+ zbyZAg#wwvLtF?Zb9bMU1x@u*@oLS3OzI-s*%FpV!^WQ6+pDZ>yoDI18X~xQxkq;JH zopk-a;^w7UYgbz8-BM+F7o?t@wXXZ!^Vg=P=UoFOdsa#Lo-Gd)7jf4uSk;=bDwt(% z)bdruD_viO_+H)pLQwFo@~VR?#hQioon1MNL&)2-bXK>VxJPW(%wW?~4~i<+T)6U5 z$?wh9ORncn_PqTw(I!sxQds7ylPklx^UpW@TxD!p8pgO+N8bGOma~_BIn?@2VKn=; z&T6;A+{J!VriJgTQ<`iqSTH{$tM|+yx3hXz7xDP6O}&)e)Yx!QhO=#&diCl*_Z+fAlU1H@Z#kDD)o}D-hq-{|-Pi9;X2h6! zi|NM&Y_2)E$!%Fuwrl#4=j&H}ZM!YCM>b;8{TJE170PoJeZGI4W4QXc+1G;s*;BV4 zzI`Vx#I*W0Z+&R-hP}!X222xImAa{HTA4M`CR=%8->e($oF_xh&grd{{p#(P_-P3P z_qOfK|F!BjY!#Iby~^IYY>_MXH2r+5-5WRldlM{fV%ju~)ra|T;{TP$mMu*<-IlPT zbtMDyO4}N~WcvxBJ#on!e#R&Z9cNl2GsR`i(Js-I$|sjxXH{}rEx0MeeAeH6eH#*m zrOljP_Xdc5TaoocyMT(uSr*Av8ZBNZKc#*Dk zcEcSPizL5QUT1t;FFxRon186y)k9IIbW?e9O_AeosQ}@RzZSIl2pi|@UsszPdf4W$ zbjNw&twv1uOzV;Zf4iy0ot4jDC62HaO8m9@axqj^jlkT%!UH4Xq zNY1P>IzOv#>S4v7587CzXZQAX=u1QhMZEa>)3?}f+Gm>#78jK}5yGFgZc!^-yy32N zW?r;Vgy1J#Udim*2@!Fd*RGwFv%|?lI)jm0V&W>%)2|qgXC6`Xv1dA{@-Zi3)f)5C zBTs5$%ADV5u2s#xcJPXi^Xz%Yu1DTHyY&m4nZ?{CWcB7E?ksYmv3-HK+8oE31x8QQcCZF|PQ?~WTp~Bi%^2L)w z3Ino(IE;TQ7*A{ zqt6LH?VnmZ__))RWbHPrP_g~icy`^hC6cSX{>2xm-b`m;37S2{!1t6#^s*_M%XKv_ zPIX=7`Qymm-7POaE6Mr<|MFPm_u9m&ciNPYEC&nG)suYAEmRM3y6{1yY0~7KpL&+0 z`aW-K-^{q`M2oMOg>9hMIo|eVH(huxnrXV$col(b_{u3X&5R^4m(@m|E$cf1wRy=4>USQ^WH{&f3c zYC_>!gGW3Yt?xW+es%oXv1MKfx$|#lX`MW>Pi*Grv?w|4))^;fvdn4}d)RmT8+VvS zganVOWt;bJ!Nb2M>MVJ_T5`ukG2X0{3vQl&cFz5Ojpc7$LyO_DO~-nyZ*NYHj7ply za%@{fgzWY5s^d#)gauM3ajbAY^F4~sAbqX>C12~UUs+d+Ez;JBf zzou5mZxnjT=_;;u{JYqfM{YeErUvYc%jjGglchCvQDy7H4)ZBl%TE@j?YxrsXsL^5 zbW^X9q%pSQZ_$)$)todb+*o z$V;cC%M7GKWUb~OJ6%#bkBKdjHSXm})nylq+=J)tidt`$k+pc8*~-tQUrX&eGha=- zKAT~=-i52JS)14CJyP?HU9&oWMgFT-(XWJJV^`^2zWVePS8VLb1y671ym)2(X$Kd7 z-o)ckKMUslTDNT7wX3GDqUNryT;^B5aQ~~U?p=K^pZw4DJTgT)hU@jKDm%|`^A*yi zUu_qh_*}_Yv}a8c&w*l7sYT08FFa~^DWS7q)~|i*@`9pExBA{)vs#|xhWsa)7PI|R z?oHBv`AY2Svdi~h$_K3e@~0|p`T0*8_p`ams;myTsqZ_-JWp!j)_ZBmYnJOh%4}b8 zc%H{>^GBR4wgw8yA|HO)mYvgBx;4G|{QK`~3~g>4elBjk^2-^1HZ@n9*$maq<^msG znx4r8Yn`=!)9~xe?MIp)lN7fwo&2-2GxzZ1=M^PimAA&qZO?jjeAlneUB1sx|0tSU zT-miQFTDIkR{O5t=K}4n|H@y!T0TL^|5?!7<)2Jq@1FIG{p)jg@#<<<@pq5U&bqbo zv!PAkbF*&;zt1xItdkY-G?HNvQ{rTi_#4Srdvtf*YW2OEx79uP`|DSXTl-hO;&^Qu zTe_0H^y=EWd8N76yaL1d3$-u!cpZGOF=}t!j`}z3F_Hv)ztXJF5lc- zT=JE>boR2k&X7G(EyV%L>o2)m{q>fcf9mo5FEf|%y?j;pwPo47H&b8rENwcsyvWwb zLTB}s>7lbuYZ>l03Tw)Ir5S6xwr=TXn|X^@r$70qBlji#m(0V(@;`U4n-?6Ndp_c( zAXnaLk|%>Y@$on?5gT`mjYpaDrM< zgkam#ne%O*rT5Q>-pcNHRC&^hHkr7P?Wtd0n=uwgM>$QHx8jfYu3x>s)}CAalP5*r zJ?z^H0fpDE%9AAZ4|i^u^zMDD@=?iC+D~@d+C12F&f&=Qycvx)nMpsJ0yHExh4^>) zTDVPS=x-G`!TZZm??i>`bK{>nv40u)e>LqB;XZ%)>grdfzI)fLHor1^R+V>n{_1j* zuj|&`3vQpO_C>u}?7{oje{wlzZ%ultyKlqN|N9!$El;odqGHoH@dL}U;LU!ukG-`I zZr5V`!&uZ-GJVx*`!4Z+0e?Nik(P_ke-KS?*T3*`>eP>0DuV2bqhtR@*QUMpy#G>jQ=3@J z){dE9TAoTNTetX0BrSB9ke?xllV^M;m_xo*Zv0W3lN zTU2%V6V@)D^-^Q=f;C$*S8nnDpq1+Gb4~Wt!vw2!^)-1fzPQ)OZs6}$-lcqeVt3A_ zRUze1EKTk{EO~PH?e~fQZw3AJ;#~i(pmVzBxd{)9bk}m0{fhR{o9UJ#?Y=5kw)3Py zg*8{nKCd?$w){W2>D+aNPZlM|8O|C8l=Dn_+FTuzbnE10!Dnf+76+8`l!+LIetBPT zOU`Ls-Y1nkLQ#{R-Y7EdVbHUB5ubmCcZ-hkt>)LfDGhEXI83C29CdqRs7tslGZ8ai2(+85;Noeu+%Y3 z618smb%fF9g|zjRazyqTcqGDP+sN*Wb4)^heDqnOa_RjeF6(1#|PHv;8k+ z?|FEF%jC#G(`wb-AHG=By)6uVdy?YuMI3I%Ue8`Oh2^PnpI&>z$GO&2t7G=3C5PqkPd0wGa(?LYt4bfF6;HoZ?Yn<0<%Uh+O@;6A41(6PWoNAV{UG~B z`MyLsnQM{L8Ml7?JonKgx%B97Q=NheyC=k4`kv|fYU>*A+efDRzr6p|GiU391?xAy zO8-4wMwv0Ma$9%YPTiT)%T`D0xOds=m8pNp<=RyFbK;$2k>*;RbC-Xa9DZ{9^R<&) zea&u5XzRa0q_4(Q1 zYiyt8_H0|T>2Gvf15Yc%$_;^ z()0e8f6Yx7WH+0OoH(Q(Xq)ftEo86uwa8_L1*6INm(i1bSFccU7TNV%yK3V9$e`_eS~mxnfQ`95D-^_|F>)rH!e9r3?s?Z51?Q%h>L=C@_BVzO6XvuKyT zuUvmJWEyALHSY_af9G^rOx!fTwlwO}_q2_tFLVB#nI12p{;pj0?7TbIc|Y8kbT7Rl z;MupN?;jUgJmY3m;cF||C`@Z zyI!2pzr=siv)lzTJHs8V-PeVk`M&(y@B3dOYyQ?>_^)4^*H`Zte=3^q+u7}#?(>~9 zyuWi!`*(|)Yd1R6?W!&_c&0s__D=Pls>03I<=hK8#TZ^_={b0BSKD}w*(ZRxQoxd> zVOK{HXR^)WH6E@fH%{I1Np?zbSbS9AlwhBofu~lVbBxwjOP}(If5K)f@z`)fQ5R2p z2iB{VFZeu4OiS3+cKMaCtM2+4^LCYn)*bie?Uznm(hv>Zedn6P$5WS#Oct3encZeK z_3hF`(cc+A?4$x?9~{dnuQl(@(b6pzf3r03YSqf<{!1C#Un}gqv+K6#(#3ZyV@=v# ziWMuUd%5o}<`1;n_95i?uHvz%3hpXJICAp;Jxi11#TV8+cjDJ(%l%>@1H)F%-8(kt@H3! z)AX=~E0X~K~?Rvq3z4wt}43CFp$f@QE4gTh=GYwU|&jqKjYuTllM@eN=cDpZn z%Hpc;pzR)D_oAxL-LXIRz(;qRS^bNc7P1TUtIf5&Q5BJ+FDHFJTPCD%&&uCE<`H5C zg%{jB-oTf-N}bW{p3M>+ugUxuPPAS6v^Qi|h51y|(C0Q?;w=Gn4O%WI+Fx8;bn25v zsB7k_FfAR|&o?xD*Pd&>vnw;|a@?%AxzEo{eyC^VH}R&8otJva#m=s-v>SUhLi3jz z?#@gzKYM7_Zc1WT)u&s%jgbi{)aQ^Xyz@ zPP>HYy}alDViV2>ly%M7*}&~v8U0MYX}Z#jiIaCdIG7OdrMO~Cdxp}NEG^jumR~fU z{N&DB54lLKGGnyc z3s}RQ*yl(H_6C|v_`Kk_JY$%X{ggjN2fkImHaOn+J%b}T()p*O6j!6DY1zdh*9TX) zK79DnVlCpUR>gn*@P%dHS4!-w75RJf$j#(~oe!I)C3I=H9{w3o5%=@`{*^XoFS+j$ z-@&owXX?={MqaD=E}S|VaB!Kk$==yv&avlKoOAr|lM!G(_o_(n!u63_ChS^Urk}eP zuPFCw4oh9~0m-I+;ti`^JJc5o1RhhIH>c%Bp!58h6@JI}End;G{Bxno$AmhW$3M-E zU0P+7yNjW$+GhTQL$=fIvqgk_P&qSEcD=~zS7(>-U3xX+Q>Clr^_<04!MaZ`$}AQ8 zeAm@uR!(bNHe*I?WR?9^*(HIWHrfA7%GLRDbJZO6Rddo;6$!>XKI-r)Y1fsS=ruFl zTOA@4%PdzgoC<4EuxK-t>KBOMOIntEEymzQ$hDP%JeJISdAu>v41RBGc5KjourKM2 zv~&8gDgEnuHoy0Z{#o==NaH@wQ}+gDxa z{Wf<^hMn(wCQnKKb$_B-)L|Wm!W1nZ5f#=MN7ZlM4n3Ou=dXwlyRn&bP5QjE#cz&o z&W-u(by{vgLR8y<;|XVvsJMK3)bV8I%Wj3DA~zSSOM)}!2u|ENQ}CsS`x2&Xt<4Ib z^ra_O&P<#;o$qzTfmyRyuPrxQGpomC?sUH^g_51K&U3#xYJZ3=sYktld0IQ)C4tJ` zTka3_x-=?ooooB#9KxW!bzdU8sA%pDcWLo(8I^R)oRr|oq}`oqQ)Vk>x%~{-GVwq@ z&-rDYHvCy}&cPLSvd6coSuMS>NoKQHSJ$lB$6r`C`ag_PSZ%PqPyFH8PsuXUH`i`E z?~?Gk<<`9Tc(tOQOV^*u_FQ5;)YxniuJyYC1 zWR{rdJHINhnh?vmJBC%gB<;>ozm0-ojc2w9mR&Lt_7(JC*54NU=2FVTwz8v_wY_&d zci_8s<`Aoz$C|S#hbPVG`J+B9i~0D*PqW>+C2M5g#LoE0*Rl75z}}!+zOxTb>6Tl- zoyxNB-J?bM4L_Q%gnaS+Ts!OLdh_bvFQU~IACw$SZCE>b(xg^z-No~ROC;qM>t24p z==4NWhAi{giy>xJ`mvHr^PScA6?cS{UJi};ez&S-->qkVuLkZ?^SZuh>ruIzNqsTw zJFdT1@OL)9E77lWfAhD=PgwH){Qm8Iai`}up&x;_w9d|baPV%4{9CiXGd>iV?r^{3 zBqjY}MfSqH+zE5|Cq=WboZId2Xt^2RB{#myt}+Wx@0`5u+1D*o%`cVRYf<^kq%uSN zV&1+9-#(;OP19c{{&V&ht9YUB+k#h2llCp1?O5z{G{hs{{c}-VscLW;WhhdRXc!!`(T2ugwnZvgOuU*~WS;D(|erm9zHV%CFAxxb#k) zKk-)g?uQ{qC(qaNJf%46_*a7k@+BAfXG)#g{X$Ib#wq9Zb%d?)3E< z`wHIT`aR8T9(=!qSGzGxVTsrFEc#NNkoWx%@4F>QQ(h@on%n%5vuc~z{4uWLO|40{ z{F2r`1$RzAzwEh(@7akH5z9BuzkRTEVh20pjAa(viRl^I=jC&sjTsKM;Obdg<>|ODb;dY(7?c zSrH`~44$hF!wHE6;6J0G9!y<1|RW)m>?wr`-xH!cTHpYNSpR&C9Db?8O& ziV1UE@4DLeUvkb{+bx%-bt|9kNo`4j_Q7(yOH-`s8s6RT?hkwJz4ZSLvsFIdHtcU` ze`{zx?ezbm{npE0EYPujQdV~Pal}WLDf3F6Gc+!j39OP@yJykzMPIbb^ByfxXz-c$ zqfqLAze0u`Yp0!W_mA)`J@Xf?|G4?esr}3N>gJh!&~oSbgjO(?BnY%3i}<;f0+HnZog~&)9sZa`;QC%sGWDH-sRLUMWea>kJK4uO?s3I zo=WL9ty}w?*P!p^mL~H&n|1X0=j&$=>@$d)t=khSp5bY_{LD308x|>xhP778 z?dul*{^`Wh6thdxX+Ot9h5mOfS8JFZ9T&%zDA#xEJ8lx-Kd07HsHwS4beVoDTimhf zw@)@)KNs0ne%biJ+s$9^ev!GiKW{=!N_vo8kjk~w^2y!%73F_gb3LwCnOc7MvE*@u z*>jvE9*fqfhN%mjm^gpdt+W!$Yn_cgn_tcFs&sw%GuPx`)?Nku)juEcNrmVy`#*b= z-mkUHSB!XI;uVp1W^2_sW(Z ziFZRCPCYudH7(D*r08YbuemJ7s}J1z#<6$LR5tI|40~hvb?VNi?Mr;RSlsR9)Z8bV zqUr_0r+(mid_X9Ob;{xrsa0$j0<#o0XfJu0WpFmcIipWX>i9d2A06*MT~#YnkG`?g z;QcI#c`E{RSKei{iNCAM`ZIfbz~-A3d%N!muxI^lyJd9SG{j`eVh^3|t4@822#n0T zI%OKqoljc+Qzl(Yx!U9!Se3)m;We7&k?UC`5#=2Z)FS9Rru2EXt# zHPwu?zqrO)bZ6$q%$!3TSd8DlI_RSwFMa)p=CTu>d~Ww!U+v%CeyZ!`2fM0z{9y^L*)-g_)9FS}zR#3OWbct@-xs>3@FEwD$*Nu7U}23=B`b@J)ML zkTmV>nwL_LpP5$znf0C<7F~QfOyJ)Xi$Wc3aVC{k2ThT#WOkPwmzQWJOlrI0&~aGx zPS*zhZ3m{sdbTYwzxDqzyH)UsfHbSx&F=Yp)9<(2tINK>xc~p( zFX;m&b(1%8Z~wVf?C4yLcc*@^d{1#HnD5SC@g-J-KlR9hqZv;H_ZR&+wYg!!#qQ%a zx-NlJHu75O+jl?Vd?KOIOXRA?zUc-joTo2oyKM_w8|D+;RN{WfA<+1fYGRa- zo00#P^jT4xzfPKUQMcO7NoTb<&)Ib|oerHm@GWOql32(@?U$k6EBsq>^H)qWn9ms; zyC(VE89^6&PLAd^vRo6_zhBwCE!NlCIVfPx+U{KwulF{!2=~njyISPB@Y$A48Y_2t z?Tj*v*x0w}NdB>csWWyMY;jlJ7!s$>wt3gW+r>h8>bnkjnVY4(s+(@IctKk3+?jE^tx&P3ooMk6xM$KG! zu5}6f$|ozbw4V8J%x}}0@3~b`Bk}z21eKi4EpvH8l2i)YH)~{>in*0&Yh0c^V@XwS z@Cos~lVq0~Y!!L?a@tWoZ_~V=8@H=BUGOQ)$+pW6k+!T=)3`S=u&t+1Y^U#|4b|`D z^Mnmoubk>pvgF9Iwv#t5O=BxwwR%nNwi$`q9VNSF|GUJH6jXS3R{l5b)`r^4{)d13 z>~=pFmX+qG^P+|)Sy%S4hJ1IE^9Ip5M|fYYkPloe)K?y#&b80AP4~J;%;8N<=@AnR zzRD@&*?tu+_U_&~U;9QcCu{YF@Pp|$&gabu+Hmd$`-hz^o8_03dD>jdQni+-al0Sz zfw`{dkvgmWV{umf31J_!&uLq9bgsLT$Fj#+eD)*Ze`d4q8sy~O&E68yepc>nbgXAf zjQ3pEve$c`?LT@+k@HQgjqLOpK0jYyJu>zCH5YFKrI=<)jZdTr1lD#z}Y+ki` z?b(P6UnYHK-ZuNpmYYZFeqFrnT0gD!#lxh9f&ACGSJYZOuKg15(js}4T)}Fb|>;GKAUwkUdgWSy&|336kd!c(-+(WTT)8~>#a0i$*x|#YeVysdy#XLf3RKE ze>wBun(VA|rmFj0b986kYLQW~e(gMU?}8IQx=OY$s_Xrn$MDQ!*3;jUh1U!4xBaq_ zea0%EwZHwA|7&5t4|+;(lUC*#{GL>=^sl<%j%vKh?>!!IhxWXl7az%4wM}ACjQ=Xu zsNZehUMrlQXTCB#;KuB@`R02M5+3A-~&v5zP@%nj_cPV?IY)!kx z+;11MdG+tzt8T;ieVqTPRa%f1|#`=+LOW=6N{H#NQ&ml4Gg$)`^h%mC7wQc6Z7nr70*6*d|95> z<%O3ucWv|yxD<9}=h=nD@4x^4JFj}z_UawQ@AhU+R-1C@k8=FJ_chPI&b?l~@As$r z`E`5;gkF7K!2Dj{L7MO68%9?Cst=4dPZCcYmb3WaIMY_?@M12$>W>m~-yb>u*ud`o zK`^rJN_YQ5&Pchh45K0#y>Bmc65fHpW z&cx52=60$!@c|z)`JX*nlCw`^^K_O!lKOGS(nV{|b)SFCz3IDa;74z#U#a^0n$}l+ zG_ASYo&R9AQH{6RzPCrqKg2rzo5yp%{4u-J7ia#k$L?}}B2DWQP8jaQ2fWK zEuQOe{LYWr{9YfV9cx?__J@A3=Fj?AE%{HOqkhWG`7I|`Cmpx1{wV(EYVUr|C+|1? zXlMU_Bzx0${h5EGdH%{v{?k5vU9_pavWApTD0VvC*pd6pL57 zhEPh?p-nvRqSniaNp8$=$wg~R`NW^CnZ|!Z$(_A~Z|RNqjXTy!RynsN9s6H;VYA)TLz^p{%vGe^ z&s|G9vNq(zQm|c?lm!G=V6nej$A2kVH?e}bIwNP^g8(+atSmNlHpu; z`tK4H%`yvnTXxG7@Ru<)qms?VoW-%ctu zanm@tG%U)tczx>Xh@}2d+=pVQnYSa_{Me-(cK%OUB&r?rp>Dq4Lz}T zQ9DyK*R*)Ts!J@hR$Ne-%9Xjv$yLjD;Yuyv#V@(e24t%J z46$nO5}l>`UzO`@SSH`pP4VYW9o2ewB(~_rPOY>)%RCUlv|G zu>Mlz7MHX&$AY4kT_~CwcHz{Nl}4+lIIRw`njf}0#5p@8%3FNJmcDD+TO616hO7>l z>ot2t+`_Y3xeM8*N*yhVUKzEJJ2Y!i+SDkQCuUhsw-}X*-=Fz&{iU*73xlMmYF$|u z#I75Xx%@_isc7emw*ATOi=D(*mKeSb$~2E%bZP09_Vts#YQ?%uUtPkQ>2$+khT*Na zt+fjaF4!2o3tTywNsF~}?N!&MTBY4T^$#88`np0ysA|57&E%R?WNv>qKNeJb=+?^75}<-wcKl&O!yq5O!j$^^U9L9e?PJ~ z+><@?)I8g={R-1fe^2>;s+{}RtIKyc+b#?J^D@t0a@B#XG^;Wb!EbZk>RQyy?6=Sf zH-D5e+3eHF^rx#HDNp}>Civ~gqYC9ACMT}{yYi_-@V3?WSBx9?XUQ(V`A+56{T;$@ zI@4tLp zmn~Y*wPeejX{VJg@fh?;uIsy&oBMXpv!s=+!izcHbWBh`^5;&ga_NE)HJ>Rh{_i{f zCfjuu-OQC*z3uR-yOMLnmSl&CUlZyywOkw?S2}0Gn!baI`?T5_j~!2ccw= z8rnA&mCi1jJ$w2N&u5-DUokvBe|GA*u=xoKH@K-LD;2~ayk{?D7s=FUEOFdFg$&ZSI`boBkSx9Y}W%)mwc2gwfKgjeQ}%0`(0HpYYg~uUpQw ze_oMneb4mX^clj-4?PKqMs#zkF?QH)pv|er#Jo$~m#~CKu@=`7H zmtIuS>wDRoSodFiYX2=`dzq8zY`QA(&0WTy`s4+3lU{lpFxtC1__qt9o2Dn}=d?IT)as7kBMLW03_^oMR*IxK>)fFdqb*2VOZm0A#BVor%o9Eki zpRLpUe|p~TB!-{o4}UyjkUyPsyq3jxmRVBklIL>$6nC6rs&y>oNP+74i0;I-t8>?;in%u}-4WRqVLIQC_e*5h$=$QJ zhTjZ`om$l3=#ycnKGk`Khr}V3L!KIahYOzYFWPYIVX=;1(kFo~4%2hOGd6i|SRQ86 zx`)wcb>Yt#yL6$;wR*>91qQw>=1q8J_@kyz<(y@Q^^FflO}qRpIr)>dJkM-;;^TNy zAnp0X$|+ZN)V`Y>5gloAoMqax*$0^74|*n6GZmNrytA)~@r?JPHwJ3U9hhh2Gp(BW zkSXv_%)?z9jNZyPYm^&oZas76skTSb#I50rBj&A6IC)Ayi*=({+tEG8i`oNxEjoCO zK2KiRdwls1n`KqcBVSdzK2Hie^Z2vTbydD|5>uCcFzQ^|9$$a#`J)99&x(7Gys4Y= z;l{bR_X+#o95M3SQ1#7UxH^Mf{i@zEu1)6OH`y*|d=GD%4Yd0 zh=1AvGuF*duPzk6cf{c6lrL%XcFuI?T=#6|bjz^EQu8V^td2k3y2DRt+O8nMJwO;eRl9nd|fd&V8-ve9vy3`MrIkYp~gF z*=O#4yWhD=Mr+ObFCo=-LF1s!^yS|!c5VBVsWo}W1*tvsHwPJPBB$!EXbM8t5LpAvtsv$!y(-z=(>Z}CpctoIu`pUw7&sU>7z|Cn z+xR_o7P`&Ez_5gqfkA|Ug#i`#x`sIFdiuHP`#So0y1532==r++JB4WqNEZ``U|?Y2 zgwha7k(q%3Zc2bR!gA1kJ*(Dle>;nrfx%FMfk70a9!f?bYjbf8aP@O>^>g-g4MsNt z`6^!lsAdRd&W>a=^!i?8-JpZlk*^XGfoOx0kHj!_gYMu#HUZ=XH8dQOD4XZaXOUK&oNkj%xcf4I~2~H`yTDj;G` z8RHrpe5Qe}y@8knB2_gpoPuFma$;_34)hWnbd!;9iLnA12*-^inv8k{4zfLIV z5SJu??wo;J!;qy#nh!wsROIF$TYw(mpt}|j7F^axvY;4t^8!BoVhGI)3=E!W;$$h82X20!KGqx9Or7_?tKblk;;6AU7@`yA_nv zkPpr`LNPkR5LeJay$x|I!f5ar^2p|+M=fe0I@=g>7(YH8+$b(O57hy+AD>3h(fbI! zTqY2!pc)|#$EO{1@IFGjH#Y4Ef8#Sq5n&1g1H&}@27v<*CGrhSzuW9UI>;Mz=sv>4 z=foK23@SiChXdg_f*;xSAnTCN4+WhLj<9a61(r}m1OvqNxU7TBBcWS{e0n74s3U}B zOC5-{4C?`<=oTTLwq%E}g@J)V#F+?-@E%QxZWr=4byQFJ`Ve6kcxyT+!cx&sb3(TW zc@s8h*E_;r4dKLE + + + + 4.0.0 + + + org.apache.camel + camel-parent + 2.4.0 + + + camel-jetty + bundle + Camel :: Jetty + Camel Jetty support + 2.4.0.1 + + + org.apache.camel.component.jetty.* + + + + + + org.apache.camel + camel-core + 2.4.0 + + + org.apache.camel + camel-http + 2.4.0 + + + org.eclipse.jetty + jetty-server + + + org.eclipse.jetty + jetty-security + + + org.eclipse.jetty + jetty-servlet + + + org.eclipse.jetty + jetty-servlets + ${jetty-version} + + + org.eclipse.jetty + jetty-client + + + org.eclipse.jetty + jetty-jmx + ${jetty-version} + + + + org.apache.camel + camel-test + 2.4.0 + test + + + org.apache.camel + camel-spring + 2.4.0 + test + + + javax.mail + mail + ${javax-mail-version} + test + + + + org.springframework + spring-context + true + test + + + org.springframework + spring-aop + true + test + + + org.springframework + spring-test + true + test + + + + junit + junit + test + + + log4j + log4j + test + + + + + + + + maven-surefire-plugin + + pertest + + + + **/*XXXTest.* + + + + + + + diff --git a/embedded-repo/org/apache/camel/camel-jetty/2.4.0.1/camel-jetty-2.4.0.1.pom.md5 b/embedded-repo/org/apache/camel/camel-jetty/2.4.0.1/camel-jetty-2.4.0.1.pom.md5 new file mode 100644 index 0000000000..295aae7a23 --- /dev/null +++ b/embedded-repo/org/apache/camel/camel-jetty/2.4.0.1/camel-jetty-2.4.0.1.pom.md5 @@ -0,0 +1 @@ +fba57baa166195ac2b2a013c3cc6d3f1 \ No newline at end of file diff --git a/embedded-repo/org/apache/camel/camel-jetty/2.4.0.1/camel-jetty-2.4.0.1.pom.sha1 b/embedded-repo/org/apache/camel/camel-jetty/2.4.0.1/camel-jetty-2.4.0.1.pom.sha1 new file mode 100644 index 0000000000..7fb0b3347f --- /dev/null +++ b/embedded-repo/org/apache/camel/camel-jetty/2.4.0.1/camel-jetty-2.4.0.1.pom.sha1 @@ -0,0 +1 @@ +c41ff483ac35754c1d41b1823561935849b362ed \ No newline at end of file diff --git a/embedded-repo/org/apache/camel/camel-jetty/maven-metadata.xml b/embedded-repo/org/apache/camel/camel-jetty/maven-metadata.xml new file mode 100644 index 0000000000..0e25837b64 --- /dev/null +++ b/embedded-repo/org/apache/camel/camel-jetty/maven-metadata.xml @@ -0,0 +1,11 @@ + + org.apache.camel + camel-jetty + 2.4.0.1 + + + 2.4.0.1 + + 20100723102939 + + \ No newline at end of file diff --git a/embedded-repo/org/apache/camel/camel-jetty/maven-metadata.xml.md5 b/embedded-repo/org/apache/camel/camel-jetty/maven-metadata.xml.md5 new file mode 100644 index 0000000000..fcff48b3ce --- /dev/null +++ b/embedded-repo/org/apache/camel/camel-jetty/maven-metadata.xml.md5 @@ -0,0 +1 @@ +34f1efbcb11f7251390994d8f81598b2 \ No newline at end of file diff --git a/embedded-repo/org/apache/camel/camel-jetty/maven-metadata.xml.sha1 b/embedded-repo/org/apache/camel/camel-jetty/maven-metadata.xml.sha1 new file mode 100644 index 0000000000..64ef58e71f --- /dev/null +++ b/embedded-repo/org/apache/camel/camel-jetty/maven-metadata.xml.sha1 @@ -0,0 +1 @@ +2e1bb47c5a8c19f98b70e5e6af450861933deacc \ No newline at end of file diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 7af21abe06..3967bf81ce 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -637,7 +637,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { - + From 552ee564e990e633bddb74f1734158ea66cdbb4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bon=C3=A9r?= Date: Mon, 26 Jul 2010 12:19:17 +0200 Subject: [PATCH 060/188] Fixed broken tests for Active Objects + added logging to Scheduler + fixed problem with SchedulerSpec --- akka-core/src/main/scala/actor/ActorRef.scala | 1 + .../src/main/scala/actor/Scheduler.scala | 16 ++- .../src/main/scala/remote/RemoteServer.scala | 1 + ...NestedTransactionalActiveObjectSpec.scala} | 80 +++--------- ...tNestedTransactionalActiveObjectSpec.scala | 114 ++++++++++++++++++ ...RestartTransactionalActiveObjectSpec.scala | 92 ++++++++++++++ akka-core/src/test/scala/SchedulerSpec.scala | 8 +- ...la => TransactionalActiveObjectSpec.scala} | 44 ++----- 8 files changed, 251 insertions(+), 105 deletions(-) rename akka-core/src/test/scala/{DeclarativelySupervisedNestedTransactionalActiveObjectSpec.scala => NestedTransactionalActiveObjectSpec.scala} (61%) create mode 100644 akka-core/src/test/scala/RestartNestedTransactionalActiveObjectSpec.scala create mode 100644 akka-core/src/test/scala/RestartTransactionalActiveObjectSpec.scala rename akka-core/src/test/scala/{DeclarativelySupervisedTransactionalActiveObjectSpec.scala => TransactionalActiveObjectSpec.scala} (67%) diff --git a/akka-core/src/main/scala/actor/ActorRef.scala b/akka-core/src/main/scala/actor/ActorRef.scala index 45ff0edd3f..9824e8b2b6 100644 --- a/akka-core/src/main/scala/actor/ActorRef.scala +++ b/akka-core/src/main/scala/actor/ActorRef.scala @@ -1151,6 +1151,7 @@ sealed class LocalActorRef private[akka]( handleExceptionInDispatch( new TransactionSetAbortedException("Transaction set has been aborted by another participant"), message, topLevelTransaction) + case e: InterruptedException => {} // received message while actor is shutting down, ignore case e => handleExceptionInDispatch(e, message, topLevelTransaction) } finally { diff --git a/akka-core/src/main/scala/actor/Scheduler.scala b/akka-core/src/main/scala/actor/Scheduler.scala index 6a7187afdc..6f4f099bb2 100644 --- a/akka-core/src/main/scala/actor/Scheduler.scala +++ b/akka-core/src/main/scala/actor/Scheduler.scala @@ -20,7 +20,7 @@ import java.util.concurrent._ import se.scalablesolutions.akka.util.Logging -object Scheduler { +object Scheduler extends Logging { import Actor._ case object UnSchedule @@ -28,8 +28,12 @@ object Scheduler { private var service = Executors.newSingleThreadScheduledExecutor(SchedulerThreadFactory) private val schedulers = new ConcurrentHashMap[ActorRef, ActorRef] + log.info("Starting up Scheduler") def schedule(receiver: ActorRef, message: AnyRef, initialDelay: Long, delay: Long, timeUnit: TimeUnit): ActorRef = { + log.trace( + "Schedule scheduled event\n\tevent = [%s]\n\treceiver = [%s]\n\tinitialDelay = [%s]\n\tdelay = [%s]\n\ttimeUnit = [%s]", + message, receiver, initialDelay, delay, timeUnit) try { val future = service.scheduleAtFixedRate( new Runnable { def run = receiver ! message }, @@ -44,6 +48,9 @@ object Scheduler { } def scheduleOnce(receiver: ActorRef, message: AnyRef, delay: Long, timeUnit: TimeUnit): ActorRef = { + log.trace( + "Schedule one-time event\n\tevent = [%s]\n\treceiver = [%s]\n\tdelay = [%s]\n\ttimeUnit = [%s]", + message, receiver, delay, timeUnit) try { val future = service.schedule( new Runnable { def run = receiver ! message }, delay, timeUnit).asInstanceOf[ScheduledFuture[AnyRef]] @@ -65,6 +72,7 @@ object Scheduler { } def shutdown = { + log.info("Shutting down Scheduler") import scala.collection.JavaConversions._ schedulers.values.foreach(_ ! UnSchedule) schedulers.clear @@ -72,14 +80,16 @@ object Scheduler { } def restart = { + log.info("Restarting Scheduler") shutdown service = Executors.newSingleThreadScheduledExecutor(SchedulerThreadFactory) } } -private class ScheduleActor(future: ScheduledFuture[AnyRef]) extends Actor with Logging { +private class ScheduleActor(future: ScheduledFuture[AnyRef]) extends Actor { def receive = { case Scheduler.UnSchedule => + Scheduler.log.trace("Unschedule event handled by scheduleActor\n\tactorRef = [%s]", self.toString) future.cancel(true) self.stop } @@ -91,7 +101,7 @@ private object SchedulerThreadFactory extends ThreadFactory { def newThread(r: Runnable): Thread = { val thread = threadFactory.newThread(r) - thread.setName("Scheduler-" + count) + thread.setName("akka:scheduler-" + count) thread.setDaemon(true) thread } diff --git a/akka-core/src/main/scala/remote/RemoteServer.scala b/akka-core/src/main/scala/remote/RemoteServer.scala index 4283945de9..a5277c0924 100644 --- a/akka-core/src/main/scala/remote/RemoteServer.scala +++ b/akka-core/src/main/scala/remote/RemoteServer.scala @@ -222,6 +222,7 @@ class RemoteServer extends Logging { bootstrap.releaseExternalResources Cluster.deregisterLocalNode(hostname, port) } catch { + case e: java.nio.channels.ClosedChannelException => {} case e => log.warning("Could not close remote server channel in a graceful way") } } diff --git a/akka-core/src/test/scala/DeclarativelySupervisedNestedTransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/NestedTransactionalActiveObjectSpec.scala similarity index 61% rename from akka-core/src/test/scala/DeclarativelySupervisedNestedTransactionalActiveObjectSpec.scala rename to akka-core/src/test/scala/NestedTransactionalActiveObjectSpec.scala index ea244bf966..afb9f9523e 100644 --- a/akka-core/src/test/scala/DeclarativelySupervisedNestedTransactionalActiveObjectSpec.scala +++ b/akka-core/src/test/scala/NestedTransactionalActiveObjectSpec.scala @@ -11,149 +11,103 @@ import org.scalatest.BeforeAndAfterAll import org.scalatest.junit.JUnitRunner import org.junit.runner.RunWith -import se.scalablesolutions.akka.config.Config -import se.scalablesolutions.akka.config._ -import se.scalablesolutions.akka.config.ActiveObjectConfigurator -import se.scalablesolutions.akka.config.JavaConfig._ import se.scalablesolutions.akka.actor._ @RunWith(classOf[JUnitRunner]) -class DeclarativelySupervisedNestedTransactionalActiveObjectSpec extends +class NestedTransactionalActiveObjectSpec extends Spec with ShouldMatchers with BeforeAndAfterAll { - private val conf = new ActiveObjectConfigurator private var messageLog = "" - override def beforeAll { - Config.config - conf.configure( - new RestartStrategy(new AllForOne, 3, 5000, List(classOf[Exception]).toArray), - List( - new Component(classOf[TransactionalActiveObject], - new LifeCycle(new Permanent), - 10000), - new Component(classOf[NestedTransactionalActiveObject], - new LifeCycle(new Permanent), - 10000), - new Component(classOf[ActiveObjectFailer], - new LifeCycle(new Permanent), - 10000) - ).toArray).supervise - } - override def afterAll { - conf.stop + // ActorRegistry.shutdownAll } describe("Declaratively nested supervised transactional in-memory Active Object") { it("map should not rollback state for stateful server in case of success") { - val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) stateful.init stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init") // set init state - Thread.sleep(100) - val nested = conf.getInstance(classOf[NestedTransactionalActiveObject]) + val nested = ActiveObject.newInstance(classOf[NestedTransactionalActiveObject]) nested.init nested.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init") // set init state - Thread.sleep(100) stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state", nested) // transactionrequired - Thread.sleep(100) stateful.getMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess") should equal("new state") nested.getMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess") should equal("new state") } it("map should rollback state for stateful server in case of failure") { - val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) stateful.init stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state - Thread.sleep(100) - val nested = conf.getInstance(classOf[NestedTransactionalActiveObject]) + val nested = ActiveObject.newInstance(classOf[NestedTransactionalActiveObject]) nested.init nested.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state - Thread.sleep(100) - val failer = conf.getInstance(classOf[ActiveObjectFailer]) + val failer = ActiveObject.newInstance(classOf[ActiveObjectFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) - Thread.sleep(100) fail("should have thrown an exception") } catch { case e => {} } stateful.getMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure") should equal("init") - Thread.sleep(100) nested.getMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure") should equal("init") } it("vector should not rollback state for stateful server in case of success") { - val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) stateful.init stateful.setVectorState("init") // set init state - Thread.sleep(100) - val nested = conf.getInstance(classOf[NestedTransactionalActiveObject]) + val nested = ActiveObject.newInstance(classOf[NestedTransactionalActiveObject]) nested.init - Thread.sleep(100) nested.setVectorState("init") // set init state - Thread.sleep(100) stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state", nested) // transactionrequired - Thread.sleep(100) stateful.getVectorState should equal("new state") - Thread.sleep(100) nested.getVectorState should equal("new state") } it("vector should rollback state for stateful server in case of failure") { - val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) stateful.init stateful.setVectorState("init") // set init state - Thread.sleep(100) - val nested = conf.getInstance(classOf[NestedTransactionalActiveObject]) + val nested = ActiveObject.newInstance(classOf[NestedTransactionalActiveObject]) nested.init nested.setVectorState("init") // set init state - Thread.sleep(100) - val failer = conf.getInstance(classOf[ActiveObjectFailer]) + val failer = ActiveObject.newInstance(classOf[ActiveObjectFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) - Thread.sleep(100) fail("should have thrown an exception") } catch { case e => {} } stateful.getVectorState should equal("init") - Thread.sleep(100) nested.getVectorState should equal("init") } it("ref should not rollback state for stateful server in case of success") { - val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) stateful.init - val nested = conf.getInstance(classOf[NestedTransactionalActiveObject]) + val nested = ActiveObject.newInstance(classOf[NestedTransactionalActiveObject]) nested.init stateful.setRefState("init") // set init state - Thread.sleep(100) nested.setRefState("init") // set init state - Thread.sleep(100) stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state", nested) - Thread.sleep(100) stateful.getRefState should equal("new state") - Thread.sleep(100) nested.getRefState should equal("new state") } it("ref should rollback state for stateful server in case of failure") { - val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) stateful.init - val nested = conf.getInstance(classOf[NestedTransactionalActiveObject]) + val nested = ActiveObject.newInstance(classOf[NestedTransactionalActiveObject]) nested.init stateful.setRefState("init") // set init state - Thread.sleep(100) nested.setRefState("init") // set init state - Thread.sleep(100) - val failer = conf.getInstance(classOf[ActiveObjectFailer]) + val failer = ActiveObject.newInstance(classOf[ActiveObjectFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) - Thread.sleep(100) fail("should have thrown an exception") } catch { case e => {} } stateful.getRefState should equal("init") - Thread.sleep(100) nested.getRefState should equal("init") } } diff --git a/akka-core/src/test/scala/RestartNestedTransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/RestartNestedTransactionalActiveObjectSpec.scala new file mode 100644 index 0000000000..67076aff7c --- /dev/null +++ b/akka-core/src/test/scala/RestartNestedTransactionalActiveObjectSpec.scala @@ -0,0 +1,114 @@ +/** + * Copyright (C) 2009-2010 Scalable Solutions AB + */ + +package se.scalablesolutions.akka.actor + +import org.scalatest.Spec +import org.scalatest.Assertions +import org.scalatest.matchers.ShouldMatchers +import org.scalatest.BeforeAndAfterAll +import org.scalatest.junit.JUnitRunner +import org.junit.runner.RunWith + +import se.scalablesolutions.akka.config.Config +import se.scalablesolutions.akka.config._ +import se.scalablesolutions.akka.config.ActiveObjectConfigurator +import se.scalablesolutions.akka.config.JavaConfig._ +import se.scalablesolutions.akka.actor._ + +@RunWith(classOf[JUnitRunner]) +class RestartNestedTransactionalActiveObjectSpec extends + Spec with + ShouldMatchers with + BeforeAndAfterAll { + + private val conf = new ActiveObjectConfigurator + private var messageLog = "" + + override def beforeAll { + Config.config + conf.configure( + new RestartStrategy(new AllForOne, 3, 5000, List(classOf[Exception]).toArray), + List( + new Component(classOf[TransactionalActiveObject], + new LifeCycle(new Permanent), + 10000), + new Component(classOf[NestedTransactionalActiveObject], + new LifeCycle(new Permanent), + 10000), + new Component(classOf[ActiveObjectFailer], + new LifeCycle(new Permanent), + 10000) + ).toArray).supervise + } + + override def afterAll { + conf.stop + ActorRegistry.shutdownAll + } + + describe("Restart nested supervised transactional Active Object") { +/* + it("map should rollback state for stateful server in case of failure") { + val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + stateful.init + stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state + + val nested = conf.getInstance(classOf[NestedTransactionalActiveObject]) + nested.init + nested.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state + + val failer = conf.getInstance(classOf[ActiveObjectFailer]) + try { + stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) + + fail("should have thrown an exception") + } catch { case e => {} } + stateful.getMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure") should equal("init") + + nested.getMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure") should equal("init") + } + + it("vector should rollback state for stateful server in case of failure") { + val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + stateful.init + stateful.setVectorState("init") // set init state + + val nested = conf.getInstance(classOf[NestedTransactionalActiveObject]) + nested.init + nested.setVectorState("init") // set init state + + val failer = conf.getInstance(classOf[ActiveObjectFailer]) + try { + stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) + + fail("should have thrown an exception") + } catch { case e => {} } + stateful.getVectorState should equal("init") + + nested.getVectorState should equal("init") + } + + it("ref should rollback state for stateful server in case of failure") { + val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + stateful.init + val nested = conf.getInstance(classOf[NestedTransactionalActiveObject]) + nested.init + stateful.setRefState("init") // set init state + + nested.setRefState("init") // set init state + + val failer = conf.getInstance(classOf[ActiveObjectFailer]) + try { + stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) + + fail("should have thrown an exception") + } catch { case e => {} } + stateful.getRefState should equal("init") + + nested.getRefState should equal("init") + } + */ + } +} \ No newline at end of file diff --git a/akka-core/src/test/scala/RestartTransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/RestartTransactionalActiveObjectSpec.scala new file mode 100644 index 0000000000..a1a2f8b507 --- /dev/null +++ b/akka-core/src/test/scala/RestartTransactionalActiveObjectSpec.scala @@ -0,0 +1,92 @@ +/** + * Copyright (C) 2009-2010 Scalable Solutions AB + */ + +package se.scalablesolutions.akka.actor + +import org.scalatest.Spec +import org.scalatest.Assertions +import org.scalatest.matchers.ShouldMatchers +import org.scalatest.BeforeAndAfterAll +import org.scalatest.junit.JUnitRunner +import org.junit.runner.RunWith + +import se.scalablesolutions.akka.config.Config +import se.scalablesolutions.akka.config._ +import se.scalablesolutions.akka.config.ActiveObjectConfigurator +import se.scalablesolutions.akka.config.JavaConfig._ +import se.scalablesolutions.akka.actor._ + +@RunWith(classOf[JUnitRunner]) +class RestartTransactionalActiveObjectSpec extends + Spec with + ShouldMatchers with + BeforeAndAfterAll { + + private val conf = new ActiveObjectConfigurator + private var messageLog = "" + + def before { + Config.config + conf.configure( + new RestartStrategy(new AllForOne, 3, 5000, List(classOf[Exception]).toArray), + List( + new Component( + classOf[TransactionalActiveObject], + new LifeCycle(new Temporary), + 10000), + new Component( + classOf[ActiveObjectFailer], + new LifeCycle(new Temporary), + 10000) + ).toArray).supervise + } + + def after { + conf.stop + ActorRegistry.shutdownAll + } + + describe("Restart supervised transactional Active Object ") { +/* + it("map should rollback state for stateful server in case of failure") { + before + val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + stateful.init + stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") + val failer = conf.getInstance(classOf[ActiveObjectFailer]) + try { + stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) + fail("should have thrown an exception") + } catch { case e => {} } + stateful.getMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure") should equal("init") + after + } + + it("vector should rollback state for stateful server in case of failure") { + before + val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + stateful.init + stateful.setVectorState("init") // set init state + val failer = conf.getInstance(classOf[ActiveObjectFailer]) + try { + stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) + fail("should have thrown an exception") + } catch { case e => {} } + stateful.getVectorState should equal("init") + after + } + + it("ref should rollback state for stateful server in case of failure") { + val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + stateful.init + stateful.setRefState("init") // set init state + val failer = conf.getInstance(classOf[ActiveObjectFailer]) + try { + stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) + fail("should have thrown an exception") + } catch { case e => {} } + stateful.getRefState should equal("init") + } +*/ } +} diff --git a/akka-core/src/test/scala/SchedulerSpec.scala b/akka-core/src/test/scala/SchedulerSpec.scala index 7db5727834..0054e86a57 100644 --- a/akka-core/src/test/scala/SchedulerSpec.scala +++ b/akka-core/src/test/scala/SchedulerSpec.scala @@ -64,10 +64,7 @@ class SchedulerSpec extends JUnitSuite { SupervisorConfig( RestartStrategy(AllForOne, 3, 1000, List(classOf[Exception])), - Supervise( - actor, - LifeCycle(Permanent)) - :: Nil)).start + Supervise(actor, LifeCycle(Permanent)) :: Nil)).start Scheduler.schedule(actor, Ping, 500, 500, TimeUnit.MILLISECONDS) // appx 2 pings before crash @@ -78,8 +75,7 @@ class SchedulerSpec extends JUnitSuite { assert(pingLatch.await(4, TimeUnit.SECONDS)) } finally { - - Scheduler.shutdown + Scheduler.restart } } } diff --git a/akka-core/src/test/scala/DeclarativelySupervisedTransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/TransactionalActiveObjectSpec.scala similarity index 67% rename from akka-core/src/test/scala/DeclarativelySupervisedTransactionalActiveObjectSpec.scala rename to akka-core/src/test/scala/TransactionalActiveObjectSpec.scala index 95d7b8e5df..1225df9a92 100644 --- a/akka-core/src/test/scala/DeclarativelySupervisedTransactionalActiveObjectSpec.scala +++ b/akka-core/src/test/scala/TransactionalActiveObjectSpec.scala @@ -11,45 +11,23 @@ import org.scalatest.BeforeAndAfterAll import org.scalatest.junit.JUnitRunner import org.junit.runner.RunWith -import se.scalablesolutions.akka.config.Config -import se.scalablesolutions.akka.config._ -import se.scalablesolutions.akka.config.ActiveObjectConfigurator -import se.scalablesolutions.akka.config.JavaConfig._ import se.scalablesolutions.akka.actor._ @RunWith(classOf[JUnitRunner]) -class DeclarativelySupervisedTransactionalActiveObjectSpec extends +class TransactionalActiveObjectSpec extends Spec with ShouldMatchers with BeforeAndAfterAll { - private val conf = new ActiveObjectConfigurator private var messageLog = "" - override def beforeAll { - Config.config - conf.configure( - new RestartStrategy(new AllForOne, 3, 5000, List(classOf[Exception]).toArray), - List( - new Component( - classOf[TransactionalActiveObject], - new LifeCycle(new Permanent), - 10000), - new Component( - classOf[ActiveObjectFailer], - new LifeCycle(new Permanent), - 10000) - ).toArray).supervise - } - override def afterAll { - conf.stop +// ActorRegistry.shutdownAll } describe("Declaratively supervised transactional in-memory Active Object ") { - it("map should not rollback state for stateful server in case of success") { - val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) stateful.init stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init") stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") @@ -57,10 +35,10 @@ class DeclarativelySupervisedTransactionalActiveObjectSpec extends } it("map should rollback state for stateful server in case of failure") { - val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) stateful.init stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") - val failer = conf.getInstance(classOf[ActiveObjectFailer]) + val failer = ActiveObject.newInstance(classOf[ActiveObjectFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) fail("should have thrown an exception") @@ -69,7 +47,7 @@ class DeclarativelySupervisedTransactionalActiveObjectSpec extends } it("vector should not rollback state for stateful server in case of success") { - val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) stateful.init stateful.setVectorState("init") // set init state stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") @@ -77,10 +55,10 @@ class DeclarativelySupervisedTransactionalActiveObjectSpec extends } it("vector should rollback state for stateful server in case of failure") { - val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) stateful.init stateful.setVectorState("init") // set init state - val failer = conf.getInstance(classOf[ActiveObjectFailer]) + val failer = ActiveObject.newInstance(classOf[ActiveObjectFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) fail("should have thrown an exception") @@ -89,7 +67,7 @@ class DeclarativelySupervisedTransactionalActiveObjectSpec extends } it("ref should not rollback state for stateful server in case of success") { - val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) stateful.init stateful.setRefState("init") // set init state stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") @@ -97,10 +75,10 @@ class DeclarativelySupervisedTransactionalActiveObjectSpec extends } it("ref should rollback state for stateful server in case of failure") { - val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) stateful.init stateful.setRefState("init") // set init state - val failer = conf.getInstance(classOf[ActiveObjectFailer]) + val failer = ActiveObject.newInstance(classOf[ActiveObjectFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) fail("should have thrown an exception") From add77029e004ac7467b47c18ba0d6937ff4e9ab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bon=C3=A9r?= Date: Mon, 26 Jul 2010 18:47:25 +0200 Subject: [PATCH 061/188] Added TypedActor and TypedTransactor base classes. Renamed ActiveObject factory object to TypedActor. Improved network protocol for TypedActor. Remote TypedActors now identified by UUID. --- akka-active-object-test/pom.xml | 2 +- .../ActiveObjectGuiceConfiguratorTest.java | 12 +- .../scalablesolutions/akka/api/AllTest.java | 2 +- .../akka/api/InMemNestedStateTest.java | 4 +- .../akka/api/InMemoryStateTest.java | 4 +- .../akka/api/MiscActiveObjectTest.java | 6 +- .../akka/api/RemoteInMemoryStateTest.java | 24 +- .../org/apache/camel/component/active-object | 2 +- .../main/scala/CamelContextLifecycle.scala | 18 +- akka-camel/src/main/scala/CamelService.scala | 8 +- .../src/main/scala/ConsumerPublisher.scala | 46 +- .../component/ActiveObjectComponent.scala | 30 +- .../akka/camel/PojoRemote.java | 2 +- .../test/scala/CamelServiceFeatureTest.scala | 24 +- .../scala/ConsumerMethodRegisteredTest.scala | 14 +- .../src/test/scala/PublishRequestorTest.scala | 4 +- .../src/test/scala/RemoteConsumerTest.scala | 10 +- .../ActiveObjectComponentFeatureTest.scala | 24 +- ...Module.java => TypedActorGuiceModule.java} | 4 +- .../akka/remote/protocol/RemoteProtocol.java | 1420 +++++++++++++---- .../src/main/protocol/RemoteProtocol.proto | 43 +- akka-core/src/main/resources/META-INF/aop.xml | 2 +- akka-core/src/main/scala/actor/ActorRef.scala | 8 +- .../scala/actor/SerializationProtocol.scala | 31 +- .../{ActiveObject.scala => TypedActor.scala} | 602 ++++--- .../src/main/scala/config/Configuration.scala | 4 +- .../src/main/scala/config/Configurator.scala | 8 +- ...tor.scala => TypedActorConfigurator.scala} | 33 +- ...cala => TypedActorGuiceConfigurator.scala} | 45 +- .../src/main/scala/remote/RemoteClient.scala | 10 +- .../src/main/scala/remote/RemoteServer.scala | 166 +- ...ava => NestedTransactionalTypedActor.java} | 6 +- .../akka/actor/SimpleJavaPojo.java | 4 +- ...ject.java => TransactionalTypedActor.java} | 10 +- ...bjectFailer.java => TypedAcotrFailer.java} | 2 +- akka-core/src/test/resources/META-INF/aop.xml | 2 +- .../NestedTransactionalActiveObjectSpec.scala | 36 +- .../RemoteTransactionalActiveObjectSpec.scala | 30 +- ...tNestedTransactionalActiveObjectSpec.scala | 30 +- ...RestartTransactionalActiveObjectSpec.scala | 22 +- .../scala/TransactionalActiveObjectSpec.scala | 20 +- ...Spec.scala => TypedActorContextSpec.scala} | 16 +- ... => TypedActorGuiceConfiguratorSpec.scala} | 14 +- ...ec.scala => TypedActorLifecycleSpec.scala} | 56 +- ...cala => TypedActorUtilFunctionsSpec.scala} | 0 .../src/main/java/sample/camel/BeanImpl.java | 3 +- .../main/java/sample/camel/ConsumerPojo1.java | 15 +- .../java/sample/camel/ConsumerPojo1Impl.java | 24 + .../main/java/sample/camel/ConsumerPojo2.java | 7 +- .../java/sample/camel/ConsumerPojo2Impl.java | 18 + .../sample/camel/RemoteConsumerPojo1.java | 7 +- .../sample/camel/RemoteConsumerPojo1Impl.java | 18 + .../src/main/scala/Boot.scala | 4 +- .../src/main/scala/ClientApplication.scala | 8 +- .../main/scala/StandaloneApplication.scala | 19 +- .../src/main/java/sample/rest/java/Boot.java | 4 +- .../rest/java/PersistentSimpleService.java | 40 +- .../java/PersistentSimpleServiceImpl.java | 42 + .../main/java/sample/rest/java/Receiver.java | 15 +- .../java/sample/rest/java/ReceiverImpl.java | 14 + .../java/sample/rest/java/SimpleService.java | 41 +- .../sample/rest/java/SimpleServiceImpl.java | 43 + .../akka/spring/foo/test-config.xml | 2 +- .../spring/ActiveObjectConfigurationTest.java | 14 +- .../spring/SupervisorConfigurationTest.java | 26 +- .../akka/spring/akka-0.10.xsd | 6 +- .../main/scala/ActiveObjectFactoryBean.scala | 198 --- .../src/main/scala/AkkaNamespaceHandler.scala | 2 +- .../scala/AkkaSpringConfigurationTags.scala | 2 +- .../DispatcherBeanDefinitionParser.scala | 2 +- .../SupervisionBeanDefinitionParser.scala | 8 +- .../main/scala/SupervisionFactoryBean.scala | 16 +- ...a => TypedActorBeanDefinitionParser.scala} | 6 +- .../main/scala/TypedActorFactoryBean.scala | 167 ++ ...ectParser.scala => TypedActorParser.scala} | 10 +- ...rties.scala => TypedActorProperties.scala} | 4 +- ...ActiveObjectBeanDefinitionParserTest.scala | 22 +- .../scala/ActiveObjectFactoryBeanTest.scala | 18 +- .../scala/CamelServiceSpringFeatureTest.scala | 10 +- .../DispatcherBeanDefinitionParserTest.scala | 2 +- .../SupervisionBeanDefinitionParserTest.scala | 10 +- .../scala/SupervisionFactoryBeanTest.scala | 12 +- config/akka-reference.conf | 2 +- project/build/AkkaProject.scala | 2 +- 84 files changed, 2278 insertions(+), 1445 deletions(-) rename akka-core/src/main/java/se/scalablesolutions/akka/config/{ActiveObjectGuiceModule.java => TypedActorGuiceModule.java} (85%) rename akka-core/src/main/scala/actor/{ActiveObject.scala => TypedActor.scala} (50%) rename akka-core/src/main/scala/config/{ActiveObjectConfigurator.scala => TypedActorConfigurator.scala} (56%) rename akka-core/src/main/scala/config/{ActiveObjectGuiceConfigurator.scala => TypedActorGuiceConfigurator.scala} (73%) rename akka-core/src/test/java/se/scalablesolutions/akka/actor/{NestedTransactionalActiveObject.java => NestedTransactionalTypedActor.java} (89%) rename akka-core/src/test/java/se/scalablesolutions/akka/actor/{TransactionalActiveObject.java => TransactionalTypedActor.java} (88%) rename akka-core/src/test/java/se/scalablesolutions/akka/actor/{ActiveObjectFailer.java => TypedAcotrFailer.java} (62%) rename akka-core/src/test/scala/{ActiveObjectContextSpec.scala => TypedActorContextSpec.scala} (64%) rename akka-core/src/test/scala/{ActiveObjectGuiceConfiguratorSpec.scala => TypedActorGuiceConfiguratorSpec.scala} (90%) rename akka-core/src/test/scala/{ActiveObjectLifecycleSpec.scala => TypedActorLifecycleSpec.scala} (68%) rename akka-core/src/test/scala/{ActorObjectUtilFunctionsSpec.scala => TypedActorUtilFunctionsSpec.scala} (100%) create mode 100644 akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo1Impl.java create mode 100644 akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo2Impl.java create mode 100644 akka-samples/akka-sample-camel/src/main/java/sample/camel/RemoteConsumerPojo1Impl.java create mode 100644 akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/PersistentSimpleServiceImpl.java create mode 100644 akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/ReceiverImpl.java create mode 100644 akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/SimpleServiceImpl.java delete mode 100644 akka-spring/src/main/scala/ActiveObjectFactoryBean.scala rename akka-spring/src/main/scala/{ActiveObjectBeanDefinitionParser.scala => TypedActorBeanDefinitionParser.scala} (84%) create mode 100644 akka-spring/src/main/scala/TypedActorFactoryBean.scala rename akka-spring/src/main/scala/{ActiveObjectParser.scala => TypedActorParser.scala} (90%) rename akka-spring/src/main/scala/{ActiveObjectProperties.scala => TypedActorProperties.scala} (94%) diff --git a/akka-active-object-test/pom.xml b/akka-active-object-test/pom.xml index dffacd8db0..e498c34d32 100644 --- a/akka-active-object-test/pom.xml +++ b/akka-active-object-test/pom.xml @@ -3,7 +3,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - Akka Active Object Tests in Java + Akka TypedActor Tests in Java akka-active-object-test se.scalablesolutions.akka 0.9 diff --git a/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java b/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java index 69f74ec537..e604b4da69 100644 --- a/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java +++ b/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java @@ -10,14 +10,14 @@ import com.google.inject.Scopes; import junit.framework.TestCase; import se.scalablesolutions.akka.config.Config; -import se.scalablesolutions.akka.config.ActiveObjectConfigurator; +import se.scalablesolutions.akka.config.TypedActorConfigurator; import static se.scalablesolutions.akka.config.JavaConfig.*; import se.scalablesolutions.akka.dispatch.*; -public class ActiveObjectGuiceConfiguratorTest extends TestCase { +public class TypedActorGuiceConfiguratorTest extends TestCase { static String messageLog = ""; - final private ActiveObjectConfigurator conf = new ActiveObjectConfigurator(); + final private TypedActorConfigurator conf = new TypedActorConfigurator(); protected void setUp() { Config.config(); @@ -46,7 +46,7 @@ public class ActiveObjectGuiceConfiguratorTest extends TestCase { } - public void testGuiceActiveObjectInjection() { + public void testGuiceTypedActorInjection() { messageLog = ""; Foo foo = conf.getInstance(Foo.class); Bar bar = conf.getInstance(Bar.class); @@ -69,7 +69,7 @@ public class ActiveObjectGuiceConfiguratorTest extends TestCase { } } - public void testActiveObjectInvocation() throws InterruptedException { + public void testTypedActorInvocation() throws InterruptedException { messageLog = ""; Foo foo = conf.getInstance(Foo.class); messageLog += foo.foo("foo "); @@ -79,7 +79,7 @@ public class ActiveObjectGuiceConfiguratorTest extends TestCase { assertEquals("foo return_foo before_bar ", messageLog); } - public void testActiveObjectInvocationsInvocation() throws InterruptedException { + public void testTypedActorInvocationsInvocation() throws InterruptedException { messageLog = ""; Foo foo = conf.getInstance(Foo.class); Bar bar = conf.getInstance(Bar.class); diff --git a/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/AllTest.java b/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/AllTest.java index 465c9da182..77739f6ff1 100644 --- a/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/AllTest.java +++ b/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/AllTest.java @@ -10,7 +10,7 @@ public class AllTest extends TestCase { suite.addTestSuite(InMemoryStateTest.class); suite.addTestSuite(InMemNestedStateTest.class); suite.addTestSuite(RemoteInMemoryStateTest.class); - suite.addTestSuite(ActiveObjectGuiceConfiguratorTest.class); + suite.addTestSuite(TypedActorGuiceConfiguratorTest.class); return suite; } diff --git a/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/InMemNestedStateTest.java b/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/InMemNestedStateTest.java index 746df950bf..db9d4d4146 100644 --- a/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/InMemNestedStateTest.java +++ b/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/InMemNestedStateTest.java @@ -6,7 +6,7 @@ package se.scalablesolutions.akka.api; import se.scalablesolutions.akka.config.*; import se.scalablesolutions.akka.config.Config; -import se.scalablesolutions.akka.config.ActiveObjectConfigurator; +import se.scalablesolutions.akka.config.TypedActorConfigurator; import static se.scalablesolutions.akka.config.JavaConfig.*; import se.scalablesolutions.akka.actor.*; import junit.framework.TestCase; @@ -14,7 +14,7 @@ import junit.framework.TestCase; public class InMemNestedStateTest extends TestCase { static String messageLog = ""; - final private ActiveObjectConfigurator conf = new ActiveObjectConfigurator(); + final private TypedActorConfigurator conf = new TypedActorConfigurator(); public InMemNestedStateTest() { conf.configure( diff --git a/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java b/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java index 3708d58acc..6562d0d611 100644 --- a/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java +++ b/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java @@ -8,7 +8,7 @@ import junit.framework.TestCase; import se.scalablesolutions.akka.config.Config; import se.scalablesolutions.akka.config.*; -import se.scalablesolutions.akka.config.ActiveObjectConfigurator; +import se.scalablesolutions.akka.config.TypedActorConfigurator; import static se.scalablesolutions.akka.config.JavaConfig.*; @@ -17,7 +17,7 @@ import se.scalablesolutions.akka.actor.*; public class InMemoryStateTest extends TestCase { static String messageLog = ""; - final private ActiveObjectConfigurator conf = new ActiveObjectConfigurator(); + final private TypedActorConfigurator conf = new TypedActorConfigurator(); public InMemoryStateTest() { Config.config(); diff --git a/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/MiscActiveObjectTest.java b/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/MiscActiveObjectTest.java index e61b8ac07d..aaa97d3587 100644 --- a/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/MiscActiveObjectTest.java +++ b/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/MiscActiveObjectTest.java @@ -1,7 +1,7 @@ package se.scalablesolutions.akka.api; -import static se.scalablesolutions.akka.actor.ActiveObject.link; -import static se.scalablesolutions.akka.actor.ActiveObject.newInstance; +import static se.scalablesolutions.akka.actor.TypedActor.link; +import static se.scalablesolutions.akka.actor.TypedActor.newInstance; import org.junit.Assert; import org.junit.Test; @@ -15,7 +15,7 @@ import junit.framework.TestCase; * @author johanrask * */ -public class MiscActiveObjectTest extends TestCase { +public class MiscTypedActorTest extends TestCase { /** diff --git a/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/RemoteInMemoryStateTest.java b/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/RemoteInMemoryStateTest.java index d4b4fd7687..3ae8b647ab 100644 --- a/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/RemoteInMemoryStateTest.java +++ b/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/RemoteInMemoryStateTest.java @@ -5,8 +5,8 @@ package se.scalablesolutions.akka.api; import se.scalablesolutions.akka.config.Config; -import se.scalablesolutions.akka.actor.ActiveObject; -import se.scalablesolutions.akka.config.ActiveObjectConfigurator; +import se.scalablesolutions.akka.actor.TypedActor; +import se.scalablesolutions.akka.config.TypedActorConfigurator; import se.scalablesolutions.akka.remote.RemoteNode; import junit.framework.TestCase; @@ -23,14 +23,14 @@ public class RemoteInMemoryStateTest extends TestCase { try { Thread.currentThread().sleep(1000); } catch (Exception e) {} Config.config(); } - final ActiveObjectConfigurator conf = new ActiveObjectConfigurator(); + final TypedActorConfigurator conf = new TypedActorConfigurator(); protected void tearDown() { conf.stop(); } public void testMapShouldNotRollbackStateForStatefulServerInCaseOfSuccess() { - InMemStateful stateful = ActiveObject.newRemoteInstance(InMemStateful.class, 1000, "localhost", 9999); + InMemStateful stateful = TypedActor.newRemoteInstance(InMemStateful.class, 1000, "localhost", 9999); stateful.init(); stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init"); // set init state stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // transactionrequired @@ -38,10 +38,10 @@ public class RemoteInMemoryStateTest extends TestCase { } public void testMapShouldRollbackStateForStatefulServerInCaseOfFailure() { - InMemStateful stateful = ActiveObject.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999); + InMemStateful stateful = TypedActor.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999); stateful.init(); stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init"); // set init state - InMemFailer failer = ActiveObject.newRemoteInstance(InMemFailer.class, 1000, "localhost", 9999); //conf.getInstance(InMemFailer.class); + InMemFailer failer = TypedActor.newRemoteInstance(InMemFailer.class, 1000, "localhost", 9999); //conf.getInstance(InMemFailer.class); try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer); // call failing transactionrequired method fail("should have thrown an exception"); @@ -51,7 +51,7 @@ public class RemoteInMemoryStateTest extends TestCase { } public void testVectorShouldNotRollbackStateForStatefulServerInCaseOfSuccess() { - InMemStateful stateful = ActiveObject.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999); + InMemStateful stateful = TypedActor.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999); stateful.init(); stateful.setVectorState("init"); // set init state stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // transactionrequired @@ -59,10 +59,10 @@ public class RemoteInMemoryStateTest extends TestCase { } public void testVectorShouldRollbackStateForStatefulServerInCaseOfFailure() { - InMemStateful stateful = ActiveObject.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999); + InMemStateful stateful = TypedActor.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999); stateful.init(); stateful.setVectorState("init"); // set init state - InMemFailer failer = ActiveObject.newRemoteInstance(InMemFailer.class, 10000, "localhost", 9999); //conf.getInstance(InMemFailer.class); + InMemFailer failer = TypedActor.newRemoteInstance(InMemFailer.class, 10000, "localhost", 9999); //conf.getInstance(InMemFailer.class); try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer); // call failing transactionrequired method fail("should have thrown an exception"); @@ -72,7 +72,7 @@ public class RemoteInMemoryStateTest extends TestCase { } public void testRefShouldNotRollbackStateForStatefulServerInCaseOfSuccess() { - InMemStateful stateful = ActiveObject.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999); + InMemStateful stateful = TypedActor.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999); stateful.init(); stateful.setRefState("init"); // set init state stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // transactionrequired @@ -80,10 +80,10 @@ public class RemoteInMemoryStateTest extends TestCase { } public void testRefShouldRollbackStateForStatefulServerInCaseOfFailure() { - InMemStateful stateful = ActiveObject.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999); + InMemStateful stateful = TypedActor.newRemoteInstance(InMemStateful.class, 10000, "localhost", 9999); stateful.init(); stateful.setRefState("init"); // set init state - InMemFailer failer = ActiveObject.newRemoteInstance(InMemFailer.class, 10000, "localhost", 9999); //conf.getInstance(InMemFailer.class); + InMemFailer failer = TypedActor.newRemoteInstance(InMemFailer.class, 10000, "localhost", 9999); //conf.getInstance(InMemFailer.class); try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer); // call failing transactionrequired method fail("should have thrown an exception"); diff --git a/akka-camel/src/main/resources/META-INF/services/org/apache/camel/component/active-object b/akka-camel/src/main/resources/META-INF/services/org/apache/camel/component/active-object index 5dd88a0671..e004d887b3 100644 --- a/akka-camel/src/main/resources/META-INF/services/org/apache/camel/component/active-object +++ b/akka-camel/src/main/resources/META-INF/services/org/apache/camel/component/active-object @@ -1 +1 @@ -class=se.scalablesolutions.akka.camel.component.ActiveObjectComponent \ No newline at end of file +class=se.scalablesolutions.akka.camel.component.TypedActorComponent \ No newline at end of file diff --git a/akka-camel/src/main/scala/CamelContextLifecycle.scala b/akka-camel/src/main/scala/CamelContextLifecycle.scala index 640ba14e36..d1683a9464 100644 --- a/akka-camel/src/main/scala/CamelContextLifecycle.scala +++ b/akka-camel/src/main/scala/CamelContextLifecycle.scala @@ -9,7 +9,7 @@ import java.util.Map import org.apache.camel.{ProducerTemplate, CamelContext} import org.apache.camel.impl.DefaultCamelContext -import se.scalablesolutions.akka.camel.component.ActiveObjectComponent +import se.scalablesolutions.akka.camel.component.TypedActorComponent import se.scalablesolutions.akka.util.Logging /** @@ -29,13 +29,13 @@ trait CamelContextLifecycle extends Logging { private var _started = false /** - * Camel component for accessing active objects. + * Camel component for accessing typed actors. */ - private[camel] var activeObjectComponent: ActiveObjectComponent = _ + private[camel] var activeObjectComponent: TypedActorComponent = _ /** - * Registry in which active objects are TEMPORARILY registered during - * creation of Camel routes to active objects. + * Registry in which typed actors are TEMPORARILY registered during + * creation of Camel routes to typed actors. */ private[camel] var activeObjectRegistry: Map[String, AnyRef] = _ @@ -93,15 +93,15 @@ trait CamelContextLifecycle extends Logging { * CamelContext stream-caching is enabled. If applications want to disable stream- * caching they can do so after this method returned and prior to calling start. * This method also registers a new - * {@link se.scalablesolutions.akka.camel.component.ActiveObjectComponent} at - * context under a name defined by ActiveObjectComponent.InternalSchema. + * {@link se.scalablesolutions.akka.camel.component.TypedActorComponent} at + * context under a name defined by TypedActorComponent.InternalSchema. */ def init(context: CamelContext) { - this.activeObjectComponent = new ActiveObjectComponent + this.activeObjectComponent = new TypedActorComponent this.activeObjectRegistry = activeObjectComponent.activeObjectRegistry this.context = context this.context.setStreamCaching(true) - this.context.addComponent(ActiveObjectComponent.InternalSchema, activeObjectComponent) + this.context.addComponent(TypedActorComponent.InternalSchema, activeObjectComponent) this.template = context.createProducerTemplate _initialized = true log.info("Camel context initialized") diff --git a/akka-camel/src/main/scala/CamelService.scala b/akka-camel/src/main/scala/CamelService.scala index 11f2907c4d..0fbbceee2e 100644 --- a/akka-camel/src/main/scala/CamelService.scala +++ b/akka-camel/src/main/scala/CamelService.scala @@ -10,7 +10,7 @@ import se.scalablesolutions.akka.actor.{AspectInitRegistry, ActorRegistry} import se.scalablesolutions.akka.util.{Bootable, Logging} /** - * Used by applications (and the Kernel) to publish consumer actors and active objects via + * Used by applications (and the Kernel) to publish consumer actors and typed actors via * Camel endpoints and to manage the life cycle of a a global CamelContext which can be * accessed via se.scalablesolutions.akka.camel.CamelContextManager.context. * @@ -33,8 +33,8 @@ trait CamelService extends Bootable with Logging { * Starts the CamelService. Any started actor that is a consumer actor will be (asynchronously) * published as Camel endpoint. Consumer actors that are started after this method returned will * be published as well. Actor publishing is done asynchronously. A started (loaded) CamelService - * also publishes @consume annotated methods of active objects that have been created - * with ActiveObject.newInstance(..) (and ActiveObject.newInstance(..) + * also publishes @consume annotated methods of typed actors that have been created + * with TypedActor.newInstance(..) (and TypedActor.newInstance(..) * on a remote node). */ abstract override def onLoad = { @@ -44,7 +44,7 @@ trait CamelService extends Bootable with Logging { if (!initialized) init if (!started) start - // start actor that exposes consumer actors and active objects via Camel endpoints + // start actor that exposes consumer actors and typed actors via Camel endpoints consumerPublisher.start // init publishRequestor so that buffered and future events are delivered to consumerPublisher diff --git a/akka-camel/src/main/scala/ConsumerPublisher.scala b/akka-camel/src/main/scala/ConsumerPublisher.scala index e50c625639..6ca863a561 100644 --- a/akka-camel/src/main/scala/ConsumerPublisher.scala +++ b/akka-camel/src/main/scala/ConsumerPublisher.scala @@ -13,7 +13,7 @@ import org.apache.camel.builder.RouteBuilder import se.scalablesolutions.akka.actor._ import se.scalablesolutions.akka.actor.annotation.consume -import se.scalablesolutions.akka.camel.component.ActiveObjectComponent +import se.scalablesolutions.akka.camel.component.TypedActorComponent import se.scalablesolutions.akka.util.Logging /** @@ -37,7 +37,7 @@ private[camel] object ConsumerPublisher extends Logging { } /** - * Creates a route to an active object method. + * Creates a route to an typed actor method. */ def handleConsumerMethodRegistered(event: ConsumerMethodRegistered) { val targetMethod = event.method.getName @@ -62,7 +62,7 @@ private[camel] object ConsumerPublisher extends Logging { } /** - * Actor that publishes consumer actors and active object methods at Camel endpoints. + * Actor that publishes consumer actors and typed actor methods at Camel endpoints. * The Camel context used for publishing is CamelContextManager.context. This actor * accepts messages of type * se.scalablesolutions.akka.camel.ConsumerRegistered, @@ -111,10 +111,10 @@ private[camel] case class SetExpectedRegistrationCount(num: Int) private[camel] case class SetExpectedUnregistrationCount(num: Int) /** - * Defines an abstract route to a target which is either an actor or an active object method.. + * Defines an abstract route to a target which is either an actor or an typed actor method.. * - * @param endpointUri endpoint URI of the consumer actor or active object method. - * @param id actor identifier or active object identifier (registry key). + * @param endpointUri endpoint URI of the consumer actor or typed actor method. + * @param id actor identifier or typed actor identifier (registry key). * * @author Martin Krasser */ @@ -149,20 +149,20 @@ private[camel] class ConsumerActorRoute(endpointUri: String, uuid: String, block } /** - * Defines the route to an active object method.. + * Defines the route to an typed actor method.. * * @param endpointUri endpoint URI of the consumer actor method - * @param id active object identifier + * @param id typed actor identifier * @param method name of the method to invoke. * * @author Martin Krasser */ private[camel] class ConsumerMethodRoute(val endpointUri: String, id: String, method: String) extends ConsumerRoute(endpointUri, id) { - protected override def targetUri = "%s:%s?method=%s" format (ActiveObjectComponent.InternalSchema, id, method) + protected override def targetUri = "%s:%s?method=%s" format (TypedActorComponent.InternalSchema, id, method) } /** - * A registration listener that triggers publication of consumer actors and active object + * A registration listener that triggers publication of consumer actors and typed actor * methods as well as un-publication of consumer actors. This actor needs to be initialized * with a PublishRequestorInit command message for obtaining a reference to * a publisher actor. Before initialization it buffers all outbound messages @@ -209,7 +209,7 @@ private[camel] class PublishRequestor extends Actor { /** * Command message to initialize a PublishRequestor to use consumerPublisher - * for publishing actors or active object methods. + * for publishing actors or typed actor methods. */ private[camel] case class PublishRequestorInit(consumerPublisher: ActorRef) @@ -244,13 +244,13 @@ private[camel] case class ConsumerRegistered(actorRef: ActorRef, uri: String, uu private[camel] case class ConsumerUnregistered(actorRef: ActorRef, uri: String, uuid: String) extends ConsumerEvent /** - * Event indicating that an active object proxy has been created for a POJO. For each + * Event indicating that an typed actor proxy has been created for a POJO. For each * @consume annotated POJO method a separate instance of this class is * created. * - * @param activeObject active object (proxy). + * @param activeObject typed actor (proxy). * @param init - * @param uri endpoint URI of the active object method + * @param uri endpoint URI of the typed actor method * @param method method to be published. * * @author Martin Krasser @@ -258,13 +258,13 @@ private[camel] case class ConsumerUnregistered(actorRef: ActorRef, uri: String, private[camel] case class ConsumerMethodRegistered(activeObject: AnyRef, init: AspectInit, uri: String, method: Method) extends ConsumerEvent /** - * Event indicating that an active object has been stopped. For each + * Event indicating that an typed actor has been stopped. For each * @consume annotated POJO method a separate instance of this class is * created. * - * @param activeObject active object (proxy). + * @param activeObject typed actor (proxy). * @param init - * @param uri endpoint URI of the active object method + * @param uri endpoint URI of the typed actor method * @param method method to be un-published. * * @author Martin Krasser @@ -308,14 +308,14 @@ private[camel] object ConsumerMethod { /** * Applies a function f to each consumer method of activeObject and * returns the function results as a list. A consumer method is one that is annotated with - * @consume. If activeObject is a proxy for a remote active object + * @consume. If activeObject is a proxy for a remote typed actor * f is never called and Nil is returned. */ def forConsumer[T](activeObject: AnyRef, init: AspectInit)(f: Method => T): List[T] = { // TODO: support consumer annotation inheritance // - visit overridden methods in superclasses // - visit implemented method declarations in interfaces - if (init.remoteAddress.isDefined) Nil // let remote node publish active object methods on endpoints + if (init.remoteAddress.isDefined) Nil // let remote node publish typed actor methods on endpoints else for (m <- activeObject.getClass.getMethods.toList; if (m.isAnnotationPresent(classOf[consume]))) yield f(m) } @@ -326,8 +326,8 @@ private[camel] object ConsumerMethod { */ private[camel] object ConsumerMethodRegistered { /** - * Creates a list of ConsumerMethodRegistered event messages for an active object or an empty - * list if the active object is a proxy for an remote active object or the active object doesn't + * Creates a list of ConsumerMethodRegistered event messages for an typed actor or an empty + * list if the typed actor is a proxy for an remote typed actor or the typed actor doesn't * have any @consume annotated methods. */ def forConsumer(activeObject: AnyRef, init: AspectInit): List[ConsumerMethodRegistered] = { @@ -342,8 +342,8 @@ private[camel] object ConsumerMethodRegistered { */ private[camel] object ConsumerMethodUnregistered { /** - * Creates a list of ConsumerMethodUnregistered event messages for an active object or an empty - * list if the active object is a proxy for an remote active object or the active object doesn't + * Creates a list of ConsumerMethodUnregistered event messages for an typed actor or an empty + * list if the typed actor is a proxy for an remote typed actor or the typed actor doesn't * have any @consume annotated methods. */ def forConsumer(activeObject: AnyRef, init: AspectInit): List[ConsumerMethodUnregistered] = { diff --git a/akka-camel/src/main/scala/component/ActiveObjectComponent.scala b/akka-camel/src/main/scala/component/ActiveObjectComponent.scala index 05fa026e04..aff6326beb 100644 --- a/akka-camel/src/main/scala/component/ActiveObjectComponent.scala +++ b/akka-camel/src/main/scala/component/ActiveObjectComponent.scala @@ -12,31 +12,31 @@ import org.apache.camel.component.bean._ /** * @author Martin Krasser */ -object ActiveObjectComponent { +object TypedActorComponent { /** - * Default schema name for active object endpoint URIs. + * Default schema name for typed actor endpoint URIs. */ val InternalSchema = "active-object-internal" } /** - * Camel component for exchanging messages with active objects. This component - * tries to obtain the active object from the activeObjectRegistry + * Camel component for exchanging messages with typed actors. This component + * tries to obtain the typed actor from the activeObjectRegistry * first. If it's not there it tries to obtain it from the CamelContext's registry. * * @see org.apache.camel.component.bean.BeanComponent * * @author Martin Krasser */ -class ActiveObjectComponent extends BeanComponent { +class TypedActorComponent extends BeanComponent { val activeObjectRegistry = new ConcurrentHashMap[String, AnyRef] /** * Creates a {@link org.apache.camel.component.bean.BeanEndpoint} with a custom * bean holder that uses activeObjectRegistry for getting access to - * active objects (beans). + * typed actors (beans). * - * @see se.scalablesolutions.akka.camel.component.ActiveObjectHolder + * @see se.scalablesolutions.akka.camel.component.TypedActorHolder */ override def createEndpoint(uri: String, remaining: String, parameters: Map[String, AnyRef]) = { val endpoint = new BeanEndpoint(uri, this) @@ -47,26 +47,26 @@ class ActiveObjectComponent extends BeanComponent { } private def createBeanHolder(beanName: String) = - new ActiveObjectHolder(activeObjectRegistry, getCamelContext, beanName).createCacheHolder + new TypedActorHolder(activeObjectRegistry, getCamelContext, beanName).createCacheHolder } /** * {@link org.apache.camel.component.bean.BeanHolder} implementation that uses a custom - * registry for getting access to active objects. + * registry for getting access to typed actors. * * @author Martin Krasser */ -class ActiveObjectHolder(activeObjectRegistry: Map[String, AnyRef], context: CamelContext, name: String) +class TypedActorHolder(activeObjectRegistry: Map[String, AnyRef], context: CamelContext, name: String) extends RegistryBean(context, name) { /** - * Returns an {@link se.scalablesolutions.akka.camel.component.ActiveObjectInfo} instance. + * Returns an {@link se.scalablesolutions.akka.camel.component.TypedActorInfo} instance. */ override def getBeanInfo: BeanInfo = - new ActiveObjectInfo(getContext, getBean.getClass, getParameterMappingStrategy) + new TypedActorInfo(getContext, getBean.getClass, getParameterMappingStrategy) /** - * Obtains an active object from activeObjectRegistry. + * Obtains an typed actor from activeObjectRegistry. */ override def getBean: AnyRef = { val bean = activeObjectRegistry.get(getName) @@ -75,11 +75,11 @@ class ActiveObjectHolder(activeObjectRegistry: Map[String, AnyRef], context: Cam } /** - * Provides active object meta information. + * Provides typed actor meta information. * * @author Martin Krasser */ -class ActiveObjectInfo(context: CamelContext, clazz: Class[_], strategy: ParameterMappingStrategy) +class TypedActorInfo(context: CamelContext, clazz: Class[_], strategy: ParameterMappingStrategy) extends BeanInfo(context, clazz, strategy) { /** diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemote.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemote.java index 57b0999b8f..e9d3377581 100644 --- a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemote.java +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemote.java @@ -9,7 +9,7 @@ public class PojoRemote { @consume("direct:remote-active-object") public String foo(String s) { - return String.format("remote active object: %s", s); + return String.format("remote typed actor: %s", s); } } diff --git a/akka-camel/src/test/scala/CamelServiceFeatureTest.scala b/akka-camel/src/test/scala/CamelServiceFeatureTest.scala index 09d386c383..c6c04531e3 100644 --- a/akka-camel/src/test/scala/CamelServiceFeatureTest.scala +++ b/akka-camel/src/test/scala/CamelServiceFeatureTest.scala @@ -7,7 +7,7 @@ import org.apache.camel.builder.RouteBuilder import org.scalatest.{GivenWhenThen, BeforeAndAfterAll, FeatureSpec} import se.scalablesolutions.akka.actor.Actor._ -import se.scalablesolutions.akka.actor.{ActiveObject, Actor, ActorRegistry} +import se.scalablesolutions.akka.actor.{TypedActor, Actor, ActorRegistry} class CamelServiceFeatureTest extends FeatureSpec with BeforeAndAfterAll with GivenWhenThen { import CamelServiceFeatureTest._ @@ -116,13 +116,13 @@ class CamelServiceFeatureTest extends FeatureSpec with BeforeAndAfterAll with Gi } } - feature("Publish active object methods in the global CamelContext") { + feature("Publish typed actor methods in the global CamelContext") { - scenario("access active object methods via Camel direct-endpoints") { + scenario("access typed actor methods via Camel direct-endpoints") { - given("an active object registered after CamelService startup") + given("an typed actor registered after CamelService startup") var latch = service.expectEndpointActivationCount(3) - val obj = ActiveObject.newInstance(classOf[PojoBase]) + val obj = TypedActor.newInstance(classOf[PojoBase]) assert(latch.await(5000, TimeUnit.MILLISECONDS)) when("requests are sent to published methods") @@ -137,23 +137,23 @@ class CamelServiceFeatureTest extends FeatureSpec with BeforeAndAfterAll with Gi // cleanup to avoid conflicts with next test (i.e. avoid multiple consumers on direct-endpoints) latch = service.expectEndpointDeactivationCount(3) - ActiveObject.stop(obj) + TypedActor.stop(obj) assert(latch.await(5000, TimeUnit.MILLISECONDS)) } } - feature("Unpublish active object method from the global CamelContext") { + feature("Unpublish typed actor method from the global CamelContext") { - scenario("access to unregistered active object method via Camel direct-endpoint fails") { + scenario("access to unregistered typed actor method via Camel direct-endpoint fails") { - given("an active object registered after CamelService startup") + given("an typed actor registered after CamelService startup") var latch = service.expectEndpointActivationCount(3) - val obj = ActiveObject.newInstance(classOf[PojoBase]) + val obj = TypedActor.newInstance(classOf[PojoBase]) assert(latch.await(5000, TimeUnit.MILLISECONDS)) - when("the active object is stopped") + when("the typed actor is stopped") latch = service.expectEndpointDeactivationCount(3) - ActiveObject.stop(obj) + TypedActor.stop(obj) assert(latch.await(5000, TimeUnit.MILLISECONDS)) then("the associated endpoints aren't accessible any more") diff --git a/akka-camel/src/test/scala/ConsumerMethodRegisteredTest.scala b/akka-camel/src/test/scala/ConsumerMethodRegisteredTest.scala index 7c28c7d8ee..41051b9335 100644 --- a/akka-camel/src/test/scala/ConsumerMethodRegisteredTest.scala +++ b/akka-camel/src/test/scala/ConsumerMethodRegisteredTest.scala @@ -4,7 +4,7 @@ import java.net.InetSocketAddress import org.scalatest.junit.JUnitSuite -import se.scalablesolutions.akka.actor.{AspectInit, ActiveObject} +import se.scalablesolutions.akka.actor.{AspectInit, TypedActor} import se.scalablesolutions.akka.camel.ConsumerMethodRegistered._ import org.junit.{AfterClass, Test} @@ -44,14 +44,14 @@ class ConsumerMethodRegisteredTest extends JUnitSuite { } object ConsumerMethodRegisteredTest { - val activePojoBase = ActiveObject.newInstance(classOf[PojoBase]) - val activePojoSub = ActiveObject.newInstance(classOf[PojoSub]) - val activePojoIntf = ActiveObject.newInstance(classOf[PojoIntf], new PojoImpl) + val activePojoBase = TypedActor.newInstance(classOf[PojoBase]) + val activePojoSub = TypedActor.newInstance(classOf[PojoSub]) + val activePojoIntf = TypedActor.newInstance(classOf[PojoIntf], new PojoImpl) @AfterClass def afterClass = { - ActiveObject.stop(activePojoBase) - ActiveObject.stop(activePojoSub) - ActiveObject.stop(activePojoIntf) + TypedActor.stop(activePojoBase) + TypedActor.stop(activePojoSub) + TypedActor.stop(activePojoIntf) } } diff --git a/akka-camel/src/test/scala/PublishRequestorTest.scala b/akka-camel/src/test/scala/PublishRequestorTest.scala index 131f4fe2b5..7ce8ef9c81 100644 --- a/akka-camel/src/test/scala/PublishRequestorTest.scala +++ b/akka-camel/src/test/scala/PublishRequestorTest.scala @@ -32,7 +32,7 @@ class PublishRequestorTest extends JUnitSuite { } @Test def shouldReceiveConsumerMethodRegisteredEvent = { - val obj = ActiveObject.newInstance(classOf[PojoSingle]) + val obj = TypedActor.newInstance(classOf[PojoSingle]) val init = AspectInit(classOf[PojoSingle], null, None, 1000) val latch = (publisher !! SetExpectedTestMessageCount(1)).as[CountDownLatch].get requestor ! AspectInitRegistered(obj, init) @@ -45,7 +45,7 @@ class PublishRequestorTest extends JUnitSuite { } @Test def shouldReceiveConsumerMethodUnregisteredEvent = { - val obj = ActiveObject.newInstance(classOf[PojoSingle]) + val obj = TypedActor.newInstance(classOf[PojoSingle]) val init = AspectInit(classOf[PojoSingle], null, None, 1000) val latch = (publisher !! SetExpectedTestMessageCount(1)).as[CountDownLatch].get requestor ! AspectInitUnregistered(obj, init) diff --git a/akka-camel/src/test/scala/RemoteConsumerTest.scala b/akka-camel/src/test/scala/RemoteConsumerTest.scala index 25c6d6b975..08f116bdda 100644 --- a/akka-camel/src/test/scala/RemoteConsumerTest.scala +++ b/akka-camel/src/test/scala/RemoteConsumerTest.scala @@ -5,7 +5,7 @@ import java.util.concurrent.{CountDownLatch, TimeUnit} import org.scalatest.{GivenWhenThen, BeforeAndAfterAll, FeatureSpec} import se.scalablesolutions.akka.actor.Actor._ -import se.scalablesolutions.akka.actor.{ActiveObject, ActorRegistry, RemoteActor} +import se.scalablesolutions.akka.actor.{TypedActor, ActorRegistry, RemoteActor} import se.scalablesolutions.akka.remote.{RemoteClient, RemoteServer} /** @@ -55,10 +55,10 @@ class RemoteConsumerTest extends FeatureSpec with BeforeAndAfterAll with GivenWh } } - feature("Client-initiated remote consumer active object") { + feature("Client-initiated remote consumer typed actor") { scenario("access published remote consumer method") { - given("a client-initiated remote consumer active object") - val consumer = ActiveObject.newRemoteInstance(classOf[PojoRemote], host, port) + given("a client-initiated remote consumer typed actor") + val consumer = TypedActor.newRemoteInstance(classOf[PojoRemote], host, port) when("remote consumer publication is triggered") var latch = service.expectEndpointActivationCount(1) @@ -67,7 +67,7 @@ class RemoteConsumerTest extends FeatureSpec with BeforeAndAfterAll with GivenWh then("the published method is accessible via its endpoint URI") val response = CamelContextManager.template.requestBody("direct:remote-active-object", "test") - assert(response === "remote active object: test") + assert(response === "remote typed actor: test") } } } diff --git a/akka-camel/src/test/scala/component/ActiveObjectComponentFeatureTest.scala b/akka-camel/src/test/scala/component/ActiveObjectComponentFeatureTest.scala index d80eedfd7a..79a35297df 100644 --- a/akka-camel/src/test/scala/component/ActiveObjectComponentFeatureTest.scala +++ b/akka-camel/src/test/scala/component/ActiveObjectComponentFeatureTest.scala @@ -4,7 +4,7 @@ import org.scalatest.{BeforeAndAfterEach, BeforeAndAfterAll, FeatureSpec} import org.apache.camel.builder.RouteBuilder import se.scalablesolutions.akka.actor.Actor._ -import se.scalablesolutions.akka.actor.{ActorRegistry, ActiveObject} +import se.scalablesolutions.akka.actor.{ActorRegistry, TypedActor} import se.scalablesolutions.akka.camel._ import org.apache.camel.impl.{DefaultCamelContext, SimpleRegistry} import org.apache.camel.{ResolveEndpointFailedException, ExchangePattern, Exchange, Processor} @@ -12,14 +12,14 @@ import org.apache.camel.{ResolveEndpointFailedException, ExchangePattern, Exchan /** * @author Martin Krasser */ -class ActiveObjectComponentFeatureTest extends FeatureSpec with BeforeAndAfterAll with BeforeAndAfterEach { - import ActiveObjectComponentFeatureTest._ +class TypedActorComponentFeatureTest extends FeatureSpec with BeforeAndAfterAll with BeforeAndAfterEach { + import TypedActorComponentFeatureTest._ import CamelContextManager.template override protected def beforeAll = { - val activePojo = ActiveObject.newInstance(classOf[Pojo]) // not a consumer - val activePojoBase = ActiveObject.newInstance(classOf[PojoBase]) - val activePojoIntf = ActiveObject.newInstance(classOf[PojoIntf], new PojoImpl) + val activePojo = TypedActor.newInstance(classOf[Pojo]) // not a consumer + val activePojoBase = TypedActor.newInstance(classOf[PojoBase]) + val activePojoIntf = TypedActor.newInstance(classOf[PojoIntf], new PojoImpl) val registry = new SimpleRegistry registry.put("pojo", activePojo) @@ -37,8 +37,8 @@ class ActiveObjectComponentFeatureTest extends FeatureSpec with BeforeAndAfterAl ActorRegistry.shutdownAll } - feature("Communicate with an active object from a Camel application using active object endpoint URIs") { - import ActiveObjectComponent.InternalSchema + feature("Communicate with an typed actor from a Camel application using typed actor endpoint URIs") { + import TypedActorComponent.InternalSchema import ExchangePattern._ scenario("in-out exchange with proxy created from interface and method returning String") { @@ -81,14 +81,14 @@ class ActiveObjectComponentFeatureTest extends FeatureSpec with BeforeAndAfterAl } } - feature("Communicate with an active object from a Camel application from a custom Camel route") { + feature("Communicate with an typed actor from a Camel application from a custom Camel route") { - scenario("in-out exchange with externally registered active object") { + scenario("in-out exchange with externally registered typed actor") { val result = template.requestBody("direct:test", "test") assert(result === "foo: test") } - scenario("in-out exchange with internally registered active object not possible") { + scenario("in-out exchange with internally registered typed actor not possible") { intercept[ResolveEndpointFailedException] { template.requestBodyAndHeader("active-object:intf?method=m2", "x", "test", "y") } @@ -96,7 +96,7 @@ class ActiveObjectComponentFeatureTest extends FeatureSpec with BeforeAndAfterAl } } -object ActiveObjectComponentFeatureTest { +object TypedActorComponentFeatureTest { class CustomRouteBuilder extends RouteBuilder { def configure = { from("direct:test").to("active-object:pojo?method=foo") diff --git a/akka-core/src/main/java/se/scalablesolutions/akka/config/ActiveObjectGuiceModule.java b/akka-core/src/main/java/se/scalablesolutions/akka/config/TypedActorGuiceModule.java similarity index 85% rename from akka-core/src/main/java/se/scalablesolutions/akka/config/ActiveObjectGuiceModule.java rename to akka-core/src/main/java/se/scalablesolutions/akka/config/TypedActorGuiceModule.java index 60dfd4cadd..0c2ed11402 100644 --- a/akka-core/src/main/java/se/scalablesolutions/akka/config/ActiveObjectGuiceModule.java +++ b/akka-core/src/main/java/se/scalablesolutions/akka/config/TypedActorGuiceModule.java @@ -13,10 +13,10 @@ import com.google.inject.Singleton; /** * @author Jonas Bonér */ -public class ActiveObjectGuiceModule extends AbstractModule { +public class TypedActorGuiceModule extends AbstractModule { private final List bindings; - public ActiveObjectGuiceModule(final List bindings) { + public TypedActorGuiceModule(final List bindings) { this.bindings = bindings; } diff --git a/akka-core/src/main/java/se/scalablesolutions/akka/remote/protocol/RemoteProtocol.java b/akka-core/src/main/java/se/scalablesolutions/akka/remote/protocol/RemoteProtocol.java index 9af73c6c77..8babc16770 100644 --- a/akka-core/src/main/java/se/scalablesolutions/akka/remote/protocol/RemoteProtocol.java +++ b/akka-core/src/main/java/se/scalablesolutions/akka/remote/protocol/RemoteProtocol.java @@ -8,6 +8,75 @@ public final class RemoteProtocol { public static void registerAllExtensions( com.google.protobuf.ExtensionRegistry registry) { } + public enum ActorType + implements com.google.protobuf.ProtocolMessageEnum { + SCALA_ACTOR(0, 1), + JAVA_ACTOR(1, 2), + TYPED_ACTOR(2, 3), + ; + + + public final int getNumber() { return value; } + + public static ActorType valueOf(int value) { + switch (value) { + case 1: return SCALA_ACTOR; + case 2: return JAVA_ACTOR; + case 3: return TYPED_ACTOR; + default: return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap + internalGetValueMap() { + return internalValueMap; + } + private static com.google.protobuf.Internal.EnumLiteMap + internalValueMap = + new com.google.protobuf.Internal.EnumLiteMap() { + public ActorType findValueByNumber(int number) { + return ActorType.valueOf(number) + ; } + }; + + public final com.google.protobuf.Descriptors.EnumValueDescriptor + getValueDescriptor() { + return getDescriptor().getValues().get(index); + } + public final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptorForType() { + return getDescriptor(); + } + public static final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptor() { + return se.scalablesolutions.akka.remote.protocol.RemoteProtocol.getDescriptor().getEnumTypes().get(0); + } + + private static final ActorType[] VALUES = { + SCALA_ACTOR, JAVA_ACTOR, TYPED_ACTOR, + }; + public static ActorType valueOf( + com.google.protobuf.Descriptors.EnumValueDescriptor desc) { + if (desc.getType() != getDescriptor()) { + throw new java.lang.IllegalArgumentException( + "EnumValueDescriptor is not for this type."); + } + return VALUES[desc.getIndex()]; + } + private final int index; + private final int value; + private ActorType(int index, int value) { + this.index = index; + this.value = value; + } + + static { + se.scalablesolutions.akka.remote.protocol.RemoteProtocol.getDescriptor(); + } + + // @@protoc_insertion_point(enum_scope:ActorType) + } + public enum SerializationSchemeType implements com.google.protobuf.ProtocolMessageEnum { JAVA(0, 1), @@ -53,7 +122,7 @@ public final class RemoteProtocol { } public static final com.google.protobuf.Descriptors.EnumDescriptor getDescriptor() { - return se.scalablesolutions.akka.remote.protocol.RemoteProtocol.getDescriptor().getEnumTypes().get(0); + return se.scalablesolutions.akka.remote.protocol.RemoteProtocol.getDescriptor().getEnumTypes().get(1); } private static final SerializationSchemeType[] VALUES = { @@ -120,7 +189,7 @@ public final class RemoteProtocol { } public static final com.google.protobuf.Descriptors.EnumDescriptor getDescriptor() { - return se.scalablesolutions.akka.remote.protocol.RemoteProtocol.getDescriptor().getEnumTypes().get(1); + return se.scalablesolutions.akka.remote.protocol.RemoteProtocol.getDescriptor().getEnumTypes().get(2); } private static final LifeCycleType[] VALUES = { @@ -1870,6 +1939,825 @@ public final class RemoteProtocol { // @@protoc_insertion_point(class_scope:MessageProtocol) } + public static final class ActorInfoProtocol extends + com.google.protobuf.GeneratedMessage { + // Use ActorInfoProtocol.newBuilder() to construct. + private ActorInfoProtocol() { + initFields(); + } + private ActorInfoProtocol(boolean noInit) {} + + private static final ActorInfoProtocol defaultInstance; + public static ActorInfoProtocol getDefaultInstance() { + return defaultInstance; + } + + public ActorInfoProtocol getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return se.scalablesolutions.akka.remote.protocol.RemoteProtocol.internal_static_ActorInfoProtocol_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return se.scalablesolutions.akka.remote.protocol.RemoteProtocol.internal_static_ActorInfoProtocol_fieldAccessorTable; + } + + // required string uuid = 1; + public static final int UUID_FIELD_NUMBER = 1; + private boolean hasUuid; + private java.lang.String uuid_ = ""; + public boolean hasUuid() { return hasUuid; } + public java.lang.String getUuid() { return uuid_; } + + // required string target = 2; + public static final int TARGET_FIELD_NUMBER = 2; + private boolean hasTarget; + private java.lang.String target_ = ""; + public boolean hasTarget() { return hasTarget; } + public java.lang.String getTarget() { return target_; } + + // required uint64 timeout = 3; + public static final int TIMEOUT_FIELD_NUMBER = 3; + private boolean hasTimeout; + private long timeout_ = 0L; + public boolean hasTimeout() { return hasTimeout; } + public long getTimeout() { return timeout_; } + + // required .ActorType actorType = 4; + public static final int ACTORTYPE_FIELD_NUMBER = 4; + private boolean hasActorType; + private se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorType actorType_; + public boolean hasActorType() { return hasActorType; } + public se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorType getActorType() { return actorType_; } + + // optional .TypedActorInfoProtocol typedActorInfo = 5; + public static final int TYPEDACTORINFO_FIELD_NUMBER = 5; + private boolean hasTypedActorInfo; + private se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol typedActorInfo_; + public boolean hasTypedActorInfo() { return hasTypedActorInfo; } + public se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol getTypedActorInfo() { return typedActorInfo_; } + + private void initFields() { + actorType_ = se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorType.SCALA_ACTOR; + typedActorInfo_ = se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol.getDefaultInstance(); + } + public final boolean isInitialized() { + if (!hasUuid) return false; + if (!hasTarget) return false; + if (!hasTimeout) return false; + if (!hasActorType) return false; + if (hasTypedActorInfo()) { + if (!getTypedActorInfo().isInitialized()) return false; + } + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasUuid()) { + output.writeString(1, getUuid()); + } + if (hasTarget()) { + output.writeString(2, getTarget()); + } + if (hasTimeout()) { + output.writeUInt64(3, getTimeout()); + } + if (hasActorType()) { + output.writeEnum(4, getActorType().getNumber()); + } + if (hasTypedActorInfo()) { + output.writeMessage(5, getTypedActorInfo()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasUuid()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(1, getUuid()); + } + if (hasTarget()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(2, getTarget()); + } + if (hasTimeout()) { + size += com.google.protobuf.CodedOutputStream + .computeUInt64Size(3, getTimeout()); + } + if (hasActorType()) { + size += com.google.protobuf.CodedOutputStream + .computeEnumSize(4, getActorType().getNumber()); + } + if (hasTypedActorInfo()) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(5, getTypedActorInfo()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol result; + + // Construct using se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol(); + return builder; + } + + protected se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol internalGetResult() { + return result; + } + + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol(); + return this; + } + + public Builder clone() { + return create().mergeFrom(result); + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol.getDescriptor(); + } + + public se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol getDefaultInstanceForType() { + return se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol.getDefaultInstance(); + } + + public boolean isInitialized() { + return result.isInitialized(); + } + public se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + public se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol returnMe = result; + result = null; + return returnMe; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol) { + return mergeFrom((se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol other) { + if (other == se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol.getDefaultInstance()) return this; + if (other.hasUuid()) { + setUuid(other.getUuid()); + } + if (other.hasTarget()) { + setTarget(other.getTarget()); + } + if (other.hasTimeout()) { + setTimeout(other.getTimeout()); + } + if (other.hasActorType()) { + setActorType(other.getActorType()); + } + if (other.hasTypedActorInfo()) { + mergeTypedActorInfo(other.getTypedActorInfo()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + setUuid(input.readString()); + break; + } + case 18: { + setTarget(input.readString()); + break; + } + case 24: { + setTimeout(input.readUInt64()); + break; + } + case 32: { + int rawValue = input.readEnum(); + se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorType value = se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorType.valueOf(rawValue); + if (value == null) { + unknownFields.mergeVarintField(4, rawValue); + } else { + setActorType(value); + } + break; + } + case 42: { + se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol.Builder subBuilder = se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol.newBuilder(); + if (hasTypedActorInfo()) { + subBuilder.mergeFrom(getTypedActorInfo()); + } + input.readMessage(subBuilder, extensionRegistry); + setTypedActorInfo(subBuilder.buildPartial()); + break; + } + } + } + } + + + // required string uuid = 1; + public boolean hasUuid() { + return result.hasUuid(); + } + public java.lang.String getUuid() { + return result.getUuid(); + } + public Builder setUuid(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasUuid = true; + result.uuid_ = value; + return this; + } + public Builder clearUuid() { + result.hasUuid = false; + result.uuid_ = getDefaultInstance().getUuid(); + return this; + } + + // required string target = 2; + public boolean hasTarget() { + return result.hasTarget(); + } + public java.lang.String getTarget() { + return result.getTarget(); + } + public Builder setTarget(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasTarget = true; + result.target_ = value; + return this; + } + public Builder clearTarget() { + result.hasTarget = false; + result.target_ = getDefaultInstance().getTarget(); + return this; + } + + // required uint64 timeout = 3; + public boolean hasTimeout() { + return result.hasTimeout(); + } + public long getTimeout() { + return result.getTimeout(); + } + public Builder setTimeout(long value) { + result.hasTimeout = true; + result.timeout_ = value; + return this; + } + public Builder clearTimeout() { + result.hasTimeout = false; + result.timeout_ = 0L; + return this; + } + + // required .ActorType actorType = 4; + public boolean hasActorType() { + return result.hasActorType(); + } + public se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorType getActorType() { + return result.getActorType(); + } + public Builder setActorType(se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorType value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasActorType = true; + result.actorType_ = value; + return this; + } + public Builder clearActorType() { + result.hasActorType = false; + result.actorType_ = se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorType.SCALA_ACTOR; + return this; + } + + // optional .TypedActorInfoProtocol typedActorInfo = 5; + public boolean hasTypedActorInfo() { + return result.hasTypedActorInfo(); + } + public se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol getTypedActorInfo() { + return result.getTypedActorInfo(); + } + public Builder setTypedActorInfo(se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasTypedActorInfo = true; + result.typedActorInfo_ = value; + return this; + } + public Builder setTypedActorInfo(se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol.Builder builderForValue) { + result.hasTypedActorInfo = true; + result.typedActorInfo_ = builderForValue.build(); + return this; + } + public Builder mergeTypedActorInfo(se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol value) { + if (result.hasTypedActorInfo() && + result.typedActorInfo_ != se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol.getDefaultInstance()) { + result.typedActorInfo_ = + se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol.newBuilder(result.typedActorInfo_).mergeFrom(value).buildPartial(); + } else { + result.typedActorInfo_ = value; + } + result.hasTypedActorInfo = true; + return this; + } + public Builder clearTypedActorInfo() { + result.hasTypedActorInfo = false; + result.typedActorInfo_ = se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol.getDefaultInstance(); + return this; + } + + // @@protoc_insertion_point(builder_scope:ActorInfoProtocol) + } + + static { + defaultInstance = new ActorInfoProtocol(true); + se.scalablesolutions.akka.remote.protocol.RemoteProtocol.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:ActorInfoProtocol) + } + + public static final class TypedActorInfoProtocol extends + com.google.protobuf.GeneratedMessage { + // Use TypedActorInfoProtocol.newBuilder() to construct. + private TypedActorInfoProtocol() { + initFields(); + } + private TypedActorInfoProtocol(boolean noInit) {} + + private static final TypedActorInfoProtocol defaultInstance; + public static TypedActorInfoProtocol getDefaultInstance() { + return defaultInstance; + } + + public TypedActorInfoProtocol getDefaultInstanceForType() { + return defaultInstance; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return se.scalablesolutions.akka.remote.protocol.RemoteProtocol.internal_static_TypedActorInfoProtocol_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return se.scalablesolutions.akka.remote.protocol.RemoteProtocol.internal_static_TypedActorInfoProtocol_fieldAccessorTable; + } + + // required string interface = 1; + public static final int INTERFACE_FIELD_NUMBER = 1; + private boolean hasInterface; + private java.lang.String interface_ = ""; + public boolean hasInterface() { return hasInterface; } + public java.lang.String getInterface() { return interface_; } + + // required string method = 2; + public static final int METHOD_FIELD_NUMBER = 2; + private boolean hasMethod; + private java.lang.String method_ = ""; + public boolean hasMethod() { return hasMethod; } + public java.lang.String getMethod() { return method_; } + + private void initFields() { + } + public final boolean isInitialized() { + if (!hasInterface) return false; + if (!hasMethod) return false; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (hasInterface()) { + output.writeString(1, getInterface()); + } + if (hasMethod()) { + output.writeString(2, getMethod()); + } + getUnknownFields().writeTo(output); + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasInterface()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(1, getInterface()); + } + if (hasMethod()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(2, getMethod()); + } + size += getUnknownFields().getSerializedSize(); + memoizedSerializedSize = size; + return size; + } + + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data).buildParsed(); + } + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return newBuilder().mergeFrom(data, extensionRegistry) + .buildParsed(); + } + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol parseFrom(java.io.InputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Builder builder = newBuilder(); + if (builder.mergeDelimitedFrom(input, extensionRegistry)) { + return builder.buildParsed(); + } else { + return null; + } + } + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return newBuilder().mergeFrom(input).buildParsed(); + } + public static se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return newBuilder().mergeFrom(input, extensionRegistry) + .buildParsed(); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder { + private se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol result; + + // Construct using se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol.newBuilder() + private Builder() {} + + private static Builder create() { + Builder builder = new Builder(); + builder.result = new se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol(); + return builder; + } + + protected se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol internalGetResult() { + return result; + } + + public Builder clear() { + if (result == null) { + throw new IllegalStateException( + "Cannot call clear() after build()."); + } + result = new se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol(); + return this; + } + + public Builder clone() { + return create().mergeFrom(result); + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol.getDescriptor(); + } + + public se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol getDefaultInstanceForType() { + return se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol.getDefaultInstance(); + } + + public boolean isInitialized() { + return result.isInitialized(); + } + public se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol build() { + if (result != null && !isInitialized()) { + throw newUninitializedMessageException(result); + } + return buildPartial(); + } + + private se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol buildParsed() + throws com.google.protobuf.InvalidProtocolBufferException { + if (!isInitialized()) { + throw newUninitializedMessageException( + result).asInvalidProtocolBufferException(); + } + return buildPartial(); + } + + public se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol buildPartial() { + if (result == null) { + throw new IllegalStateException( + "build() has already been called on this Builder."); + } + se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol returnMe = result; + result = null; + return returnMe; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol) { + return mergeFrom((se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol other) { + if (other == se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol.getDefaultInstance()) return this; + if (other.hasInterface()) { + setInterface(other.getInterface()); + } + if (other.hasMethod()) { + setMethod(other.getMethod()); + } + this.mergeUnknownFields(other.getUnknownFields()); + return this; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder( + this.getUnknownFields()); + while (true) { + int tag = input.readTag(); + switch (tag) { + case 0: + this.setUnknownFields(unknownFields.build()); + return this; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + this.setUnknownFields(unknownFields.build()); + return this; + } + break; + } + case 10: { + setInterface(input.readString()); + break; + } + case 18: { + setMethod(input.readString()); + break; + } + } + } + } + + + // required string interface = 1; + public boolean hasInterface() { + return result.hasInterface(); + } + public java.lang.String getInterface() { + return result.getInterface(); + } + public Builder setInterface(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasInterface = true; + result.interface_ = value; + return this; + } + public Builder clearInterface() { + result.hasInterface = false; + result.interface_ = getDefaultInstance().getInterface(); + return this; + } + + // required string method = 2; + public boolean hasMethod() { + return result.hasMethod(); + } + public java.lang.String getMethod() { + return result.getMethod(); + } + public Builder setMethod(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasMethod = true; + result.method_ = value; + return this; + } + public Builder clearMethod() { + result.hasMethod = false; + result.method_ = getDefaultInstance().getMethod(); + return this; + } + + // @@protoc_insertion_point(builder_scope:TypedActorInfoProtocol) + } + + static { + defaultInstance = new TypedActorInfoProtocol(true); + se.scalablesolutions.akka.remote.protocol.RemoteProtocol.internalForceInit(); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:TypedActorInfoProtocol) + } + public static final class RemoteRequestProtocol extends com.google.protobuf.GeneratedMessage { // Use RemoteRequestProtocol.newBuilder() to construct. @@ -1911,64 +2799,29 @@ public final class RemoteProtocol { public boolean hasMessage() { return hasMessage; } public se.scalablesolutions.akka.remote.protocol.RemoteProtocol.MessageProtocol getMessage() { return message_; } - // optional string method = 3; - public static final int METHOD_FIELD_NUMBER = 3; - private boolean hasMethod; - private java.lang.String method_ = ""; - public boolean hasMethod() { return hasMethod; } - public java.lang.String getMethod() { return method_; } + // required .ActorInfoProtocol actorInfo = 3; + public static final int ACTORINFO_FIELD_NUMBER = 3; + private boolean hasActorInfo; + private se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol actorInfo_; + public boolean hasActorInfo() { return hasActorInfo; } + public se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol getActorInfo() { return actorInfo_; } - // required string target = 4; - public static final int TARGET_FIELD_NUMBER = 4; - private boolean hasTarget; - private java.lang.String target_ = ""; - public boolean hasTarget() { return hasTarget; } - public java.lang.String getTarget() { return target_; } - - // required string uuid = 5; - public static final int UUID_FIELD_NUMBER = 5; - private boolean hasUuid; - private java.lang.String uuid_ = ""; - public boolean hasUuid() { return hasUuid; } - public java.lang.String getUuid() { return uuid_; } - - // required uint64 timeout = 6; - public static final int TIMEOUT_FIELD_NUMBER = 6; - private boolean hasTimeout; - private long timeout_ = 0L; - public boolean hasTimeout() { return hasTimeout; } - public long getTimeout() { return timeout_; } - - // optional string supervisorUuid = 7; - public static final int SUPERVISORUUID_FIELD_NUMBER = 7; - private boolean hasSupervisorUuid; - private java.lang.String supervisorUuid_ = ""; - public boolean hasSupervisorUuid() { return hasSupervisorUuid; } - public java.lang.String getSupervisorUuid() { return supervisorUuid_; } - - // required bool isActor = 8; - public static final int ISACTOR_FIELD_NUMBER = 8; - private boolean hasIsActor; - private boolean isActor_ = false; - public boolean hasIsActor() { return hasIsActor; } - public boolean getIsActor() { return isActor_; } - - // required bool isOneWay = 9; - public static final int ISONEWAY_FIELD_NUMBER = 9; + // required bool isOneWay = 4; + public static final int ISONEWAY_FIELD_NUMBER = 4; private boolean hasIsOneWay; private boolean isOneWay_ = false; public boolean hasIsOneWay() { return hasIsOneWay; } public boolean getIsOneWay() { return isOneWay_; } - // required bool isEscaped = 10; - public static final int ISESCAPED_FIELD_NUMBER = 10; - private boolean hasIsEscaped; - private boolean isEscaped_ = false; - public boolean hasIsEscaped() { return hasIsEscaped; } - public boolean getIsEscaped() { return isEscaped_; } + // optional string supervisorUuid = 5; + public static final int SUPERVISORUUID_FIELD_NUMBER = 5; + private boolean hasSupervisorUuid; + private java.lang.String supervisorUuid_ = ""; + public boolean hasSupervisorUuid() { return hasSupervisorUuid; } + public java.lang.String getSupervisorUuid() { return supervisorUuid_; } - // optional .RemoteActorRefProtocol sender = 11; - public static final int SENDER_FIELD_NUMBER = 11; + // optional .RemoteActorRefProtocol sender = 6; + public static final int SENDER_FIELD_NUMBER = 6; private boolean hasSender; private se.scalablesolutions.akka.remote.protocol.RemoteProtocol.RemoteActorRefProtocol sender_; public boolean hasSender() { return hasSender; } @@ -1976,18 +2829,16 @@ public final class RemoteProtocol { private void initFields() { message_ = se.scalablesolutions.akka.remote.protocol.RemoteProtocol.MessageProtocol.getDefaultInstance(); + actorInfo_ = se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol.getDefaultInstance(); sender_ = se.scalablesolutions.akka.remote.protocol.RemoteProtocol.RemoteActorRefProtocol.getDefaultInstance(); } public final boolean isInitialized() { if (!hasId) return false; if (!hasMessage) return false; - if (!hasTarget) return false; - if (!hasUuid) return false; - if (!hasTimeout) return false; - if (!hasIsActor) return false; + if (!hasActorInfo) return false; if (!hasIsOneWay) return false; - if (!hasIsEscaped) return false; if (!getMessage().isInitialized()) return false; + if (!getActorInfo().isInitialized()) return false; if (hasSender()) { if (!getSender().isInitialized()) return false; } @@ -2003,32 +2854,17 @@ public final class RemoteProtocol { if (hasMessage()) { output.writeMessage(2, getMessage()); } - if (hasMethod()) { - output.writeString(3, getMethod()); - } - if (hasTarget()) { - output.writeString(4, getTarget()); - } - if (hasUuid()) { - output.writeString(5, getUuid()); - } - if (hasTimeout()) { - output.writeUInt64(6, getTimeout()); - } - if (hasSupervisorUuid()) { - output.writeString(7, getSupervisorUuid()); - } - if (hasIsActor()) { - output.writeBool(8, getIsActor()); + if (hasActorInfo()) { + output.writeMessage(3, getActorInfo()); } if (hasIsOneWay()) { - output.writeBool(9, getIsOneWay()); + output.writeBool(4, getIsOneWay()); } - if (hasIsEscaped()) { - output.writeBool(10, getIsEscaped()); + if (hasSupervisorUuid()) { + output.writeString(5, getSupervisorUuid()); } if (hasSender()) { - output.writeMessage(11, getSender()); + output.writeMessage(6, getSender()); } getUnknownFields().writeTo(output); } @@ -2047,41 +2883,21 @@ public final class RemoteProtocol { size += com.google.protobuf.CodedOutputStream .computeMessageSize(2, getMessage()); } - if (hasMethod()) { + if (hasActorInfo()) { size += com.google.protobuf.CodedOutputStream - .computeStringSize(3, getMethod()); - } - if (hasTarget()) { - size += com.google.protobuf.CodedOutputStream - .computeStringSize(4, getTarget()); - } - if (hasUuid()) { - size += com.google.protobuf.CodedOutputStream - .computeStringSize(5, getUuid()); - } - if (hasTimeout()) { - size += com.google.protobuf.CodedOutputStream - .computeUInt64Size(6, getTimeout()); - } - if (hasSupervisorUuid()) { - size += com.google.protobuf.CodedOutputStream - .computeStringSize(7, getSupervisorUuid()); - } - if (hasIsActor()) { - size += com.google.protobuf.CodedOutputStream - .computeBoolSize(8, getIsActor()); + .computeMessageSize(3, getActorInfo()); } if (hasIsOneWay()) { size += com.google.protobuf.CodedOutputStream - .computeBoolSize(9, getIsOneWay()); + .computeBoolSize(4, getIsOneWay()); } - if (hasIsEscaped()) { + if (hasSupervisorUuid()) { size += com.google.protobuf.CodedOutputStream - .computeBoolSize(10, getIsEscaped()); + .computeStringSize(5, getSupervisorUuid()); } if (hasSender()) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(11, getSender()); + .computeMessageSize(6, getSender()); } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; @@ -2247,29 +3063,14 @@ public final class RemoteProtocol { if (other.hasMessage()) { mergeMessage(other.getMessage()); } - if (other.hasMethod()) { - setMethod(other.getMethod()); - } - if (other.hasTarget()) { - setTarget(other.getTarget()); - } - if (other.hasUuid()) { - setUuid(other.getUuid()); - } - if (other.hasTimeout()) { - setTimeout(other.getTimeout()); - } - if (other.hasSupervisorUuid()) { - setSupervisorUuid(other.getSupervisorUuid()); - } - if (other.hasIsActor()) { - setIsActor(other.getIsActor()); + if (other.hasActorInfo()) { + mergeActorInfo(other.getActorInfo()); } if (other.hasIsOneWay()) { setIsOneWay(other.getIsOneWay()); } - if (other.hasIsEscaped()) { - setIsEscaped(other.getIsEscaped()); + if (other.hasSupervisorUuid()) { + setSupervisorUuid(other.getSupervisorUuid()); } if (other.hasSender()) { mergeSender(other.getSender()); @@ -2313,38 +3114,23 @@ public final class RemoteProtocol { break; } case 26: { - setMethod(input.readString()); + se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol.Builder subBuilder = se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol.newBuilder(); + if (hasActorInfo()) { + subBuilder.mergeFrom(getActorInfo()); + } + input.readMessage(subBuilder, extensionRegistry); + setActorInfo(subBuilder.buildPartial()); break; } - case 34: { - setTarget(input.readString()); - break; - } - case 42: { - setUuid(input.readString()); - break; - } - case 48: { - setTimeout(input.readUInt64()); - break; - } - case 58: { - setSupervisorUuid(input.readString()); - break; - } - case 64: { - setIsActor(input.readBool()); - break; - } - case 72: { + case 32: { setIsOneWay(input.readBool()); break; } - case 80: { - setIsEscaped(input.readBool()); + case 42: { + setSupervisorUuid(input.readString()); break; } - case 90: { + case 50: { se.scalablesolutions.akka.remote.protocol.RemoteProtocol.RemoteActorRefProtocol.Builder subBuilder = se.scalablesolutions.akka.remote.protocol.RemoteProtocol.RemoteActorRefProtocol.newBuilder(); if (hasSender()) { subBuilder.mergeFrom(getSender()); @@ -2413,88 +3199,62 @@ public final class RemoteProtocol { return this; } - // optional string method = 3; - public boolean hasMethod() { - return result.hasMethod(); + // required .ActorInfoProtocol actorInfo = 3; + public boolean hasActorInfo() { + return result.hasActorInfo(); } - public java.lang.String getMethod() { - return result.getMethod(); + public se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol getActorInfo() { + return result.getActorInfo(); } - public Builder setMethod(java.lang.String value) { + public Builder setActorInfo(se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol value) { if (value == null) { - throw new NullPointerException(); - } - result.hasMethod = true; - result.method_ = value; + throw new NullPointerException(); + } + result.hasActorInfo = true; + result.actorInfo_ = value; return this; } - public Builder clearMethod() { - result.hasMethod = false; - result.method_ = getDefaultInstance().getMethod(); + public Builder setActorInfo(se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol.Builder builderForValue) { + result.hasActorInfo = true; + result.actorInfo_ = builderForValue.build(); + return this; + } + public Builder mergeActorInfo(se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol value) { + if (result.hasActorInfo() && + result.actorInfo_ != se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol.getDefaultInstance()) { + result.actorInfo_ = + se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol.newBuilder(result.actorInfo_).mergeFrom(value).buildPartial(); + } else { + result.actorInfo_ = value; + } + result.hasActorInfo = true; + return this; + } + public Builder clearActorInfo() { + result.hasActorInfo = false; + result.actorInfo_ = se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol.getDefaultInstance(); return this; } - // required string target = 4; - public boolean hasTarget() { - return result.hasTarget(); + // required bool isOneWay = 4; + public boolean hasIsOneWay() { + return result.hasIsOneWay(); } - public java.lang.String getTarget() { - return result.getTarget(); + public boolean getIsOneWay() { + return result.getIsOneWay(); } - public Builder setTarget(java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - result.hasTarget = true; - result.target_ = value; + public Builder setIsOneWay(boolean value) { + result.hasIsOneWay = true; + result.isOneWay_ = value; return this; } - public Builder clearTarget() { - result.hasTarget = false; - result.target_ = getDefaultInstance().getTarget(); + public Builder clearIsOneWay() { + result.hasIsOneWay = false; + result.isOneWay_ = false; return this; } - // required string uuid = 5; - public boolean hasUuid() { - return result.hasUuid(); - } - public java.lang.String getUuid() { - return result.getUuid(); - } - public Builder setUuid(java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - result.hasUuid = true; - result.uuid_ = value; - return this; - } - public Builder clearUuid() { - result.hasUuid = false; - result.uuid_ = getDefaultInstance().getUuid(); - return this; - } - - // required uint64 timeout = 6; - public boolean hasTimeout() { - return result.hasTimeout(); - } - public long getTimeout() { - return result.getTimeout(); - } - public Builder setTimeout(long value) { - result.hasTimeout = true; - result.timeout_ = value; - return this; - } - public Builder clearTimeout() { - result.hasTimeout = false; - result.timeout_ = 0L; - return this; - } - - // optional string supervisorUuid = 7; + // optional string supervisorUuid = 5; public boolean hasSupervisorUuid() { return result.hasSupervisorUuid(); } @@ -2515,61 +3275,7 @@ public final class RemoteProtocol { return this; } - // required bool isActor = 8; - public boolean hasIsActor() { - return result.hasIsActor(); - } - public boolean getIsActor() { - return result.getIsActor(); - } - public Builder setIsActor(boolean value) { - result.hasIsActor = true; - result.isActor_ = value; - return this; - } - public Builder clearIsActor() { - result.hasIsActor = false; - result.isActor_ = false; - return this; - } - - // required bool isOneWay = 9; - public boolean hasIsOneWay() { - return result.hasIsOneWay(); - } - public boolean getIsOneWay() { - return result.getIsOneWay(); - } - public Builder setIsOneWay(boolean value) { - result.hasIsOneWay = true; - result.isOneWay_ = value; - return this; - } - public Builder clearIsOneWay() { - result.hasIsOneWay = false; - result.isOneWay_ = false; - return this; - } - - // required bool isEscaped = 10; - public boolean hasIsEscaped() { - return result.hasIsEscaped(); - } - public boolean getIsEscaped() { - return result.getIsEscaped(); - } - public Builder setIsEscaped(boolean value) { - result.hasIsEscaped = true; - result.isEscaped_ = value; - return this; - } - public Builder clearIsEscaped() { - result.hasIsEscaped = false; - result.isEscaped_ = false; - return this; - } - - // optional .RemoteActorRefProtocol sender = 11; + // optional .RemoteActorRefProtocol sender = 6; public boolean hasSender() { return result.hasSender(); } @@ -3207,6 +3913,20 @@ public final class RemoteProtocol { public boolean hasPostRestart() { return hasPostRestart; } public java.lang.String getPostRestart() { return postRestart_; } + // optional string init = 4; + public static final int INIT_FIELD_NUMBER = 4; + private boolean hasInit; + private java.lang.String init_ = ""; + public boolean hasInit() { return hasInit; } + public java.lang.String getInit() { return init_; } + + // optional string shutdown = 5; + public static final int SHUTDOWN_FIELD_NUMBER = 5; + private boolean hasShutdown; + private java.lang.String shutdown_ = ""; + public boolean hasShutdown() { return hasShutdown; } + public java.lang.String getShutdown() { return shutdown_; } + private void initFields() { lifeCycle_ = se.scalablesolutions.akka.remote.protocol.RemoteProtocol.LifeCycleType.PERMANENT; } @@ -3227,6 +3947,12 @@ public final class RemoteProtocol { if (hasPostRestart()) { output.writeString(3, getPostRestart()); } + if (hasInit()) { + output.writeString(4, getInit()); + } + if (hasShutdown()) { + output.writeString(5, getShutdown()); + } getUnknownFields().writeTo(output); } @@ -3248,6 +3974,14 @@ public final class RemoteProtocol { size += com.google.protobuf.CodedOutputStream .computeStringSize(3, getPostRestart()); } + if (hasInit()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(4, getInit()); + } + if (hasShutdown()) { + size += com.google.protobuf.CodedOutputStream + .computeStringSize(5, getShutdown()); + } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; return size; @@ -3415,6 +4149,12 @@ public final class RemoteProtocol { if (other.hasPostRestart()) { setPostRestart(other.getPostRestart()); } + if (other.hasInit()) { + setInit(other.getInit()); + } + if (other.hasShutdown()) { + setShutdown(other.getShutdown()); + } this.mergeUnknownFields(other.getUnknownFields()); return this; } @@ -3458,6 +4198,14 @@ public final class RemoteProtocol { setPostRestart(input.readString()); break; } + case 34: { + setInit(input.readString()); + break; + } + case 42: { + setShutdown(input.readString()); + break; + } } } } @@ -3526,6 +4274,48 @@ public final class RemoteProtocol { return this; } + // optional string init = 4; + public boolean hasInit() { + return result.hasInit(); + } + public java.lang.String getInit() { + return result.getInit(); + } + public Builder setInit(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasInit = true; + result.init_ = value; + return this; + } + public Builder clearInit() { + result.hasInit = false; + result.init_ = getDefaultInstance().getInit(); + return this; + } + + // optional string shutdown = 5; + public boolean hasShutdown() { + return result.hasShutdown(); + } + public java.lang.String getShutdown() { + return result.getShutdown(); + } + public Builder setShutdown(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + result.hasShutdown = true; + result.shutdown_ = value; + return this; + } + public Builder clearShutdown() { + result.hasShutdown = false; + result.shutdown_ = getDefaultInstance().getShutdown(); + return this; + } + // @@protoc_insertion_point(builder_scope:LifeCycleProtocol) } @@ -4212,6 +5002,16 @@ public final class RemoteProtocol { private static com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_MessageProtocol_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_ActorInfoProtocol_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_ActorInfoProtocol_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_TypedActorInfoProtocol_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_TypedActorInfoProtocol_fieldAccessorTable; private static com.google.protobuf.Descriptors.Descriptor internal_static_RemoteRequestProtocol_descriptor; private static @@ -4262,27 +5062,33 @@ public final class RemoteProtocol { "tProtocol\"r\n\017MessageProtocol\0225\n\023serializ" + "ationScheme\030\001 \002(\0162\030.SerializationSchemeT" + "ype\022\017\n\007message\030\002 \002(\014\022\027\n\017messageManifest\030" + - "\003 \001(\014\"\374\001\n\025RemoteRequestProtocol\022\n\n\002id\030\001 " + - "\002(\004\022!\n\007message\030\002 \002(\0132\020.MessageProtocol\022\016" + - "\n\006method\030\003 \001(\t\022\016\n\006target\030\004 \002(\t\022\014\n\004uuid\030\005" + - " \002(\t\022\017\n\007timeout\030\006 \002(\004\022\026\n\016supervisorUuid\030", - "\007 \001(\t\022\017\n\007isActor\030\010 \002(\010\022\020\n\010isOneWay\030\t \002(\010" + - "\022\021\n\tisEscaped\030\n \002(\010\022\'\n\006sender\030\013 \001(\0132\027.Re" + - "moteActorRefProtocol\"\252\001\n\023RemoteReplyProt" + - "ocol\022\n\n\002id\030\001 \002(\004\022!\n\007message\030\002 \001(\0132\020.Mess" + - "ageProtocol\022%\n\texception\030\003 \001(\0132\022.Excepti" + - "onProtocol\022\026\n\016supervisorUuid\030\004 \001(\t\022\017\n\007is" + - "Actor\030\005 \002(\010\022\024\n\014isSuccessful\030\006 \002(\010\"_\n\021Lif" + - "eCycleProtocol\022!\n\tlifeCycle\030\001 \002(\0162\016.Life" + - "CycleType\022\022\n\npreRestart\030\002 \001(\t\022\023\n\013postRes" + - "tart\030\003 \001(\t\"1\n\017AddressProtocol\022\020\n\010hostnam", - "e\030\001 \002(\t\022\014\n\004port\030\002 \002(\r\"7\n\021ExceptionProtoc" + - "ol\022\021\n\tclassname\030\001 \002(\t\022\017\n\007message\030\002 \002(\t*]" + - "\n\027SerializationSchemeType\022\010\n\004JAVA\020\001\022\013\n\007S" + - "BINARY\020\002\022\016\n\nSCALA_JSON\020\003\022\r\n\tJAVA_JSON\020\004\022" + - "\014\n\010PROTOBUF\020\005*-\n\rLifeCycleType\022\r\n\tPERMAN" + - "ENT\020\001\022\r\n\tTEMPORARY\020\002B-\n)se.scalablesolut" + - "ions.akka.remote.protocolH\001" + "\003 \001(\014\"\222\001\n\021ActorInfoProtocol\022\014\n\004uuid\030\001 \002(" + + "\t\022\016\n\006target\030\002 \002(\t\022\017\n\007timeout\030\003 \002(\004\022\035\n\tac" + + "torType\030\004 \002(\0162\n.ActorType\022/\n\016typedActorI" + + "nfo\030\005 \001(\0132\027.TypedActorInfoProtocol\";\n\026Ty", + "pedActorInfoProtocol\022\021\n\tinterface\030\001 \002(\t\022" + + "\016\n\006method\030\002 \002(\t\"\300\001\n\025RemoteRequestProtoco" + + "l\022\n\n\002id\030\001 \002(\004\022!\n\007message\030\002 \002(\0132\020.Message" + + "Protocol\022%\n\tactorInfo\030\003 \002(\0132\022.ActorInfoP" + + "rotocol\022\020\n\010isOneWay\030\004 \002(\010\022\026\n\016supervisorU" + + "uid\030\005 \001(\t\022\'\n\006sender\030\006 \001(\0132\027.RemoteActorR" + + "efProtocol\"\252\001\n\023RemoteReplyProtocol\022\n\n\002id" + + "\030\001 \002(\004\022!\n\007message\030\002 \001(\0132\020.MessageProtoco" + + "l\022%\n\texception\030\003 \001(\0132\022.ExceptionProtocol" + + "\022\026\n\016supervisorUuid\030\004 \001(\t\022\017\n\007isActor\030\005 \002(", + "\010\022\024\n\014isSuccessful\030\006 \002(\010\"\177\n\021LifeCycleProt" + + "ocol\022!\n\tlifeCycle\030\001 \002(\0162\016.LifeCycleType\022" + + "\022\n\npreRestart\030\002 \001(\t\022\023\n\013postRestart\030\003 \001(\t" + + "\022\014\n\004init\030\004 \001(\t\022\020\n\010shutdown\030\005 \001(\t\"1\n\017Addr" + + "essProtocol\022\020\n\010hostname\030\001 \002(\t\022\014\n\004port\030\002 " + + "\002(\r\"7\n\021ExceptionProtocol\022\021\n\tclassname\030\001 " + + "\002(\t\022\017\n\007message\030\002 \002(\t*=\n\tActorType\022\017\n\013SCA" + + "LA_ACTOR\020\001\022\016\n\nJAVA_ACTOR\020\002\022\017\n\013TYPED_ACTO" + + "R\020\003*]\n\027SerializationSchemeType\022\010\n\004JAVA\020\001" + + "\022\013\n\007SBINARY\020\002\022\016\n\nSCALA_JSON\020\003\022\r\n\tJAVA_JS", + "ON\020\004\022\014\n\010PROTOBUF\020\005*-\n\rLifeCycleType\022\r\n\tP" + + "ERMANENT\020\001\022\r\n\tTEMPORARY\020\002B-\n)se.scalable" + + "solutions.akka.remote.protocolH\001" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -4313,16 +5119,32 @@ public final class RemoteProtocol { new java.lang.String[] { "SerializationScheme", "Message", "MessageManifest", }, se.scalablesolutions.akka.remote.protocol.RemoteProtocol.MessageProtocol.class, se.scalablesolutions.akka.remote.protocol.RemoteProtocol.MessageProtocol.Builder.class); - internal_static_RemoteRequestProtocol_descriptor = + internal_static_ActorInfoProtocol_descriptor = getDescriptor().getMessageTypes().get(3); + internal_static_ActorInfoProtocol_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_ActorInfoProtocol_descriptor, + new java.lang.String[] { "Uuid", "Target", "Timeout", "ActorType", "TypedActorInfo", }, + se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol.class, + se.scalablesolutions.akka.remote.protocol.RemoteProtocol.ActorInfoProtocol.Builder.class); + internal_static_TypedActorInfoProtocol_descriptor = + getDescriptor().getMessageTypes().get(4); + internal_static_TypedActorInfoProtocol_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_TypedActorInfoProtocol_descriptor, + new java.lang.String[] { "Interface", "Method", }, + se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol.class, + se.scalablesolutions.akka.remote.protocol.RemoteProtocol.TypedActorInfoProtocol.Builder.class); + internal_static_RemoteRequestProtocol_descriptor = + getDescriptor().getMessageTypes().get(5); internal_static_RemoteRequestProtocol_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_RemoteRequestProtocol_descriptor, - new java.lang.String[] { "Id", "Message", "Method", "Target", "Uuid", "Timeout", "SupervisorUuid", "IsActor", "IsOneWay", "IsEscaped", "Sender", }, + new java.lang.String[] { "Id", "Message", "ActorInfo", "IsOneWay", "SupervisorUuid", "Sender", }, se.scalablesolutions.akka.remote.protocol.RemoteProtocol.RemoteRequestProtocol.class, se.scalablesolutions.akka.remote.protocol.RemoteProtocol.RemoteRequestProtocol.Builder.class); internal_static_RemoteReplyProtocol_descriptor = - getDescriptor().getMessageTypes().get(4); + getDescriptor().getMessageTypes().get(6); internal_static_RemoteReplyProtocol_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_RemoteReplyProtocol_descriptor, @@ -4330,15 +5152,15 @@ public final class RemoteProtocol { se.scalablesolutions.akka.remote.protocol.RemoteProtocol.RemoteReplyProtocol.class, se.scalablesolutions.akka.remote.protocol.RemoteProtocol.RemoteReplyProtocol.Builder.class); internal_static_LifeCycleProtocol_descriptor = - getDescriptor().getMessageTypes().get(5); + getDescriptor().getMessageTypes().get(7); internal_static_LifeCycleProtocol_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_LifeCycleProtocol_descriptor, - new java.lang.String[] { "LifeCycle", "PreRestart", "PostRestart", }, + new java.lang.String[] { "LifeCycle", "PreRestart", "PostRestart", "Init", "Shutdown", }, se.scalablesolutions.akka.remote.protocol.RemoteProtocol.LifeCycleProtocol.class, se.scalablesolutions.akka.remote.protocol.RemoteProtocol.LifeCycleProtocol.Builder.class); internal_static_AddressProtocol_descriptor = - getDescriptor().getMessageTypes().get(6); + getDescriptor().getMessageTypes().get(8); internal_static_AddressProtocol_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_AddressProtocol_descriptor, @@ -4346,7 +5168,7 @@ public final class RemoteProtocol { se.scalablesolutions.akka.remote.protocol.RemoteProtocol.AddressProtocol.class, se.scalablesolutions.akka.remote.protocol.RemoteProtocol.AddressProtocol.Builder.class); internal_static_ExceptionProtocol_descriptor = - getDescriptor().getMessageTypes().get(7); + getDescriptor().getMessageTypes().get(9); internal_static_ExceptionProtocol_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_ExceptionProtocol_descriptor, diff --git a/akka-core/src/main/protocol/RemoteProtocol.proto b/akka-core/src/main/protocol/RemoteProtocol.proto index c4e5a8157e..0417251d55 100644 --- a/akka-core/src/main/protocol/RemoteProtocol.proto +++ b/akka-core/src/main/protocol/RemoteProtocol.proto @@ -52,21 +52,35 @@ message MessageProtocol { optional bytes messageManifest = 3; } +/** + * Defines the actor info. + */ +message ActorInfoProtocol { + required string uuid = 1; + required string target = 2; + required uint64 timeout = 3; + required ActorType actorType = 4; + optional TypedActorInfoProtocol typedActorInfo = 5; +} + +/** + * Defines the typed actor extra info. + */ +message TypedActorInfoProtocol { + required string interface = 1; + required string method = 2; +} + /** * Defines a remote message request. */ message RemoteRequestProtocol { required uint64 id = 1; required MessageProtocol message = 2; - optional string method = 3; - required string target = 4; - required string uuid = 5; - required uint64 timeout = 6; - optional string supervisorUuid = 7; - required bool isActor = 8; - required bool isOneWay = 9; - required bool isEscaped = 10; - optional RemoteActorRefProtocol sender = 11; + required ActorInfoProtocol actorInfo = 3; + required bool isOneWay = 4; + optional string supervisorUuid = 5; + optional RemoteActorRefProtocol sender = 6; } /** @@ -81,6 +95,15 @@ message RemoteReplyProtocol { required bool isSuccessful = 6; } +/** + * Defines the actor type. + */ +enum ActorType { + SCALA_ACTOR = 1; + JAVA_ACTOR = 2; + TYPED_ACTOR = 3; +} + /** * Defines the serialization scheme used to serialize the message and/or Actor instance. */ @@ -117,6 +140,8 @@ message LifeCycleProtocol { required LifeCycleType lifeCycle = 1; optional string preRestart = 2; optional string postRestart = 3; + optional string init = 4; + optional string shutdown = 5; } /** diff --git a/akka-core/src/main/resources/META-INF/aop.xml b/akka-core/src/main/resources/META-INF/aop.xml index 2f8d5159a8..bdc167ca54 100644 --- a/akka-core/src/main/resources/META-INF/aop.xml +++ b/akka-core/src/main/resources/META-INF/aop.xml @@ -1,7 +1,7 @@ - + diff --git a/akka-core/src/main/scala/actor/ActorRef.scala b/akka-core/src/main/scala/actor/ActorRef.scala index 9824e8b2b6..3d01ec7886 100644 --- a/akka-core/src/main/scala/actor/ActorRef.scala +++ b/akka-core/src/main/scala/actor/ActorRef.scala @@ -291,15 +291,15 @@ trait ActorRef extends TransactionManagement { def !!(message: Any, timeout: Long = this.timeout)(implicit sender: Option[ActorRef] = None): Option[Any] = { if (isRunning) { val future = postMessageToMailboxAndCreateFutureResultWithTimeout[Any](message, timeout, sender, None) - val isActiveObject = message.isInstanceOf[Invocation] - if (isActiveObject && message.asInstanceOf[Invocation].isVoid) { + val isTypedActor = message.isInstanceOf[Invocation] + if (isTypedActor && message.asInstanceOf[Invocation].isVoid) { future.asInstanceOf[CompletableFuture[Option[_]]].completeWithResult(None) } try { future.await } catch { case e: FutureTimeoutException => - if (isActiveObject) throw e + if (isTypedActor) throw e else None } if (future.exception.isDefined) throw future.exception.get._2 @@ -347,7 +347,7 @@ trait ActorRef extends TransactionManagement { "\n\tNo sender in scope, can't reply. " + "\n\tYou have probably: " + "\n\t\t1. Sent a message to an Actor from an instance that is NOT an Actor." + - "\n\t\t2. Invoked a method on an Active Object from an instance NOT an Active Object." + + "\n\t\t2. Invoked a method on an TypedActor from an instance NOT an TypedActor." + "\n\tElse you might want to use 'reply_?' which returns Boolean(true) if succes and Boolean(false) if no sender in scope") /** diff --git a/akka-core/src/main/scala/actor/SerializationProtocol.scala b/akka-core/src/main/scala/actor/SerializationProtocol.scala index 13e8230638..3897d3abda 100644 --- a/akka-core/src/main/scala/actor/SerializationProtocol.scala +++ b/akka-core/src/main/scala/actor/SerializationProtocol.scala @@ -122,7 +122,8 @@ object ActorSerialization { private def fromBinaryToLocalActorRef[T <: Actor](bytes: Array[Byte], format: Format[T]): ActorRef = fromProtobufToLocalActorRef(SerializedActorRefProtocol.newBuilder.mergeFrom(bytes).build, format, None) - private def fromProtobufToLocalActorRef[T <: Actor](protocol: SerializedActorRefProtocol, format: Format[T], loader: Option[ClassLoader]): ActorRef = { + private def fromProtobufToLocalActorRef[T <: Actor]( + protocol: SerializedActorRefProtocol, format: Format[T], loader: Option[ClassLoader]): ActorRef = { Actor.log.debug("Deserializing SerializedActorRefProtocol to LocalActorRef:\n" + protocol) val serializer = @@ -225,26 +226,30 @@ object RemoteActorSerialization { .build } - def createRemoteRequestProtocolBuilder(ar: ActorRef, - message: Any, isOneWay: Boolean, senderOption: Option[ActorRef]): RemoteRequestProtocol.Builder = { - import ar._ - val protocol = RemoteRequestProtocol.newBuilder - .setId(RemoteRequestProtocolIdFactory.nextId) - .setMessage(MessageSerializer.serialize(message)) + def createRemoteRequestProtocolBuilder(actorRef: ActorRef, message: Any, isOneWay: Boolean, senderOption: Option[ActorRef]): + RemoteRequestProtocol.Builder = { + import actorRef._ + + val actorInfo = ActorInfoProtocol.newBuilder + .setUuid(uuid) .setTarget(actorClassName) .setTimeout(timeout) - .setUuid(uuid) - .setIsActor(true) + .setActorType(ActorType.SCALA_ACTOR) + .build + + val request = RemoteRequestProtocol.newBuilder + .setId(RemoteRequestProtocolIdFactory.nextId) + .setMessage(MessageSerializer.serialize(message)) + .setActorInfo(actorInfo) .setIsOneWay(isOneWay) - .setIsEscaped(false) val id = registerSupervisorAsRemoteActor - if (id.isDefined) protocol.setSupervisorUuid(id.get) + if (id.isDefined) request.setSupervisorUuid(id.get) senderOption.foreach { sender => RemoteServer.getOrCreateServer(sender.homeAddress).register(sender.uuid, sender) - protocol.setSender(toRemoteActorRefProtocol(sender)) + request.setSender(toRemoteActorRefProtocol(sender)) } - protocol + request } } diff --git a/akka-core/src/main/scala/actor/ActiveObject.scala b/akka-core/src/main/scala/actor/TypedActor.scala similarity index 50% rename from akka-core/src/main/scala/actor/ActiveObject.scala rename to akka-core/src/main/scala/actor/TypedActor.scala index 83ac1fc924..bd5235242b 100644 --- a/akka-core/src/main/scala/actor/ActiveObject.scala +++ b/akka-core/src/main/scala/actor/TypedActor.scala @@ -6,12 +6,13 @@ package se.scalablesolutions.akka.actor import Actor._ import se.scalablesolutions.akka.config.FaultHandlingStrategy -import se.scalablesolutions.akka.remote.protocol.RemoteProtocol.RemoteRequestProtocol +import se.scalablesolutions.akka.remote.protocol.RemoteProtocol._ import se.scalablesolutions.akka.remote.{MessageSerializer, RemoteClient, RemoteRequestProtocolIdFactory} import se.scalablesolutions.akka.dispatch.{MessageDispatcher, Future, CompletableFuture} import se.scalablesolutions.akka.config.ScalaConfig._ import se.scalablesolutions.akka.serialization.Serializer import se.scalablesolutions.akka.util._ +import se.scalablesolutions.akka.actor.annotation._ import org.codehaus.aspectwerkz.joinpoint.{MethodRtti, JoinPoint} import org.codehaus.aspectwerkz.proxy.Proxy @@ -20,21 +21,111 @@ import org.codehaus.aspectwerkz.annotation.{Aspect, Around} import java.net.InetSocketAddress import java.lang.reflect.{InvocationTargetException, Method} -object Annotations { - import se.scalablesolutions.akka.actor.annotation._ - val transactionrequired = classOf[transactionrequired] - val prerestart = classOf[prerestart] - val postrestart = classOf[postrestart] - val shutdown = classOf[shutdown] - val inittransactionalstate = classOf[inittransactionalstate] +import scala.reflect.BeanProperty + +/** + * FIXME: document TypedActor + * + * @author Jonas Bonér + */ +abstract class TypedActor extends Logging { + + /** + * Holds RTTI (runtime type information) for the TypedActor, f.e. current 'sender' + * reference, the 'senderFuture' reference etc. + *

+ * This class does not contain static information but is updated by the runtime system + * at runtime. + *

+ * Here is an example of usage (in Java): + *

+   * class PingImpl exends TypedActor implements Ping {
+   *   public void hit(int count) {
+   *     Pong pong = (Pong) getContext().getSender();
+   *     pong.hit(count++)
+   *   }
+   * }
+   * 
+ */ + @BeanProperty protected var context: TypedActorContext = _ + + /** + * The uuid for the typed actor. + */ + @BeanProperty @volatile var uuid = UUID.newUuid.toString + + /** + * Identifier for actor, does not have to be a unique one. Default is the 'uuid'. + *

+ * This field is used for logging, AspectRegistry.actorsFor(id), identifier for remote + * actor in RemoteServer etc.But also as the identifier for persistence, which means + * that you can use a custom name to be able to retrieve the "correct" persisted state + * upon restart, remote restart etc. + *

+ * This property can be set to a custom ID. + */ + @BeanProperty @volatile protected var id: String = uuid + + /** + * Defines the default timeout for '!!' and '!!!' invocations, + * e.g. the timeout for the future returned by the call to '!!' and '!!!'. + *

+ * This property can be set to a custom timeout. + */ + @BeanProperty @volatile protected var timeout: Long = Actor.TIMEOUT + + /** + * User overridable callback. + *

+ * Is called when an Actor is started by invoking 'actor.start'. + */ + def init {} + + /** + * User overridable callback. + *

+ * Is called when 'actor.stop' is invoked. + */ + def shutdown {} + + /** + * User overridable callback. + *

+ * Is called on a crashed Actor right BEFORE it is restarted to allow clean up of resources before Actor is terminated. + */ + def preRestart(reason: Throwable) {} + + /** + * User overridable callback. + *

+ * Is called right AFTER restart on the newly created Actor to allow reinitialization after an Actor crash. + */ + def postRestart(reason: Throwable) {} + + /** + * User overridable callback. + *

+ * Is called during initialization. Can be used to initialize transactional state. Will be invoked within a transaction. + */ + def initTransactionalState {} } /** - * Configuration factory for Active Objects. + * FIXME: document TypedTransactor * - * FIXDOC: document ActiveObjectConfiguration + * @author Jonas Bonér */ -final class ActiveObjectConfiguration { +@transactionrequired +abstract class TypedTransactor extends TypedActor + +/** + * Configuration factory for TypedActors. + * + * FIXDOC: document TypedActorConfiguration + * + * @author Jonas Bonér + */ +final class TypedActorConfiguration { private[akka] var _timeout: Long = Actor.TIMEOUT private[akka] var _restartCallbacks: Option[RestartCallbacks] = None private[akka] var _shutdownCallback: Option[ShutdownCallback] = None @@ -43,57 +134,49 @@ final class ActiveObjectConfiguration { private[akka] var _messageDispatcher: Option[MessageDispatcher] = None def timeout = _timeout - def timeout(timeout: Duration) : ActiveObjectConfiguration = { + def timeout(timeout: Duration) : TypedActorConfiguration = { _timeout = timeout.toMillis this } - def restartCallbacks(pre: String, post: String) : ActiveObjectConfiguration = { + def restartCallbacks(pre: String, post: String) : TypedActorConfiguration = { _restartCallbacks = Some(new RestartCallbacks(pre, post)) this } - def shutdownCallback(down: String) : ActiveObjectConfiguration = { + def shutdownCallback(down: String) : TypedActorConfiguration = { _shutdownCallback = Some(new ShutdownCallback(down)) this } - def makeTransactionRequired() : ActiveObjectConfiguration = { + def makeTransactionRequired() : TypedActorConfiguration = { _transactionRequired = true; this } - def makeRemote(hostname: String, port: Int) : ActiveObjectConfiguration = { + def makeRemote(hostname: String, port: Int) : TypedActorConfiguration = { _host = Some(new InetSocketAddress(hostname, port)) this } - def dispatcher(messageDispatcher: MessageDispatcher) : ActiveObjectConfiguration = { + def dispatcher(messageDispatcher: MessageDispatcher) : TypedActorConfiguration = { _messageDispatcher = Some(messageDispatcher) this } } /** - * Holds RTTI (runtime type information) for the Active Object, f.e. current 'sender' + * Holds RTTI (runtime type information) for the TypedActor, f.e. current 'sender' * reference, the 'senderFuture' reference etc. *

- * In order to make use of this context you have to create a member field in your - * Active Object that has the type 'ActiveObjectContext', then an instance will - * be injected for you to use. - *

* This class does not contain static information but is updated by the runtime system * at runtime. *

- * Here is an example of usage: + * Here is an example of usage (from Java): *

- * class Ping {
- *   // This context will be injected, holds RTTI (runtime type information)
- *   // for the current message send
- *   private ActiveObjectContext context = null;
- *
+ * class PingImpl exends TypedActor implements Ping {
  *   public void hit(int count) {
- *     Pong pong = (Pong) context.getSender();
+ *     Pong pong = (Pong) getContext().getSender();
  *     pong.hit(count++)
  *   }
  * }
@@ -101,12 +184,12 @@ final class ActiveObjectConfiguration {
  *
  * @author Jonas Bonér
  */
-final class ActiveObjectContext {
+final class TypedActorContext {
   private[akka] var _sender: AnyRef = _
   private[akka] var _senderFuture: CompletableFuture[Any] = _
 
   /**
-   * Returns the current sender Active Object reference.
+   * Returns the current sender reference.
    * Scala style getter.
    */
   def sender: AnyRef = {
@@ -115,7 +198,7 @@ final class ActiveObjectContext {
   }
 
   /**
-   * Returns the current sender Active Object reference.
+   * Returns the current sender reference.
    * Java style getter.
    */
    def getSender: AnyRef = {
@@ -124,13 +207,13 @@ final class ActiveObjectContext {
    }
 
   /**
-   * Returns the current sender future Active Object reference.
+   * Returns the current sender future TypedActor reference.
    * Scala style getter.
    */
   def senderFuture: Option[CompletableFuture[Any]] = if (_senderFuture eq null) None else Some(_senderFuture)
 
   /**
-   * Returns the current sender future Active Object reference.
+   * Returns the current sender future TypedActor reference.
    * Java style getter.
    * This method returns 'null' if the sender future is not available.
    */
@@ -138,249 +221,63 @@ final class ActiveObjectContext {
 }
 
 /**
- * Internal helper class to help pass the contextual information between threads.
+ * Factory class for creating TypedActors out of plain POJOs and/or POJOs with interfaces.
  *
  * @author Jonas Bonér
  */
-private[akka] object ActiveObjectContext {
-  import scala.util.DynamicVariable
-  private[actor] val sender =       new DynamicVariable[AnyRef](null)
-  private[actor] val senderFuture = new DynamicVariable[CompletableFuture[Any]](null)
-}
-
-/**
- * Factory class for creating Active Objects out of plain POJOs and/or POJOs with interfaces.
- *
- * @author Jonas Bonér
- */
-object ActiveObject extends Logging {
+object TypedActor extends Logging {
   import Actor.actorOf
 
-  val AKKA_CAMEL_ROUTING_SCHEME = "akka"
+  val AKKA_CAMEL_ROUTING_SCHEME = "akka".intern
   private[actor] val AW_PROXY_PREFIX = "$$ProxiedByAW".intern
 
-  def newInstance[T](target: Class[T], timeout: Long): T =
-    newInstance(target, actorOf(new Dispatcher(false)), None, timeout)
+  def newInstance[T](intfClass: Class[T], targetClass: Class[_], timeout: Long): T = {
+    newInstance(intfClass, newTypedActor(targetClass), actorOf(new Dispatcher(false)), None, timeout)    
+  }
 
-  def newInstance[T](target: Class[T]): T =
-    newInstance(target, actorOf(new Dispatcher(false)), None, Actor.TIMEOUT)
+  def newInstance[T](intfClass: Class[T], targetClass: Class[_]): T = {
+    newInstance(intfClass, newTypedActor(targetClass), actorOf(new Dispatcher(false)), None, Actor.TIMEOUT)    
+  }
 
-  def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long): T =
-    newInstance(intf, target, actorOf(new Dispatcher(false)), None, timeout)
+  def newRemoteInstance[T](intfClass: Class[T], targetClass: Class[_], timeout: Long, hostname: String, port: Int): T = {
+    newInstance(intfClass, newTypedActor(targetClass), actorOf(new Dispatcher(false)), Some(new InetSocketAddress(hostname, port)), timeout)    
+  }
 
-  def newInstance[T](intf: Class[T], target: AnyRef): T =
-    newInstance(intf, target, actorOf(new Dispatcher(false)), None, Actor.TIMEOUT)
+  def newRemoteInstance[T](intfClass: Class[T], targetClass: Class[_], hostname: String, port: Int): T = {
+    newInstance(intfClass, newTypedActor(targetClass), actorOf(new Dispatcher(false)), Some(new InetSocketAddress(hostname, port)), Actor.TIMEOUT)    
+  }
 
-  def newRemoteInstance[T](target: Class[T], timeout: Long, hostname: String, port: Int): T =
-    newInstance(target, actorOf(new Dispatcher(false)), Some(new InetSocketAddress(hostname, port)), timeout)
-
-  def newRemoteInstance[T](target: Class[T], hostname: String, port: Int): T =
-    newInstance(target, actorOf(new Dispatcher(false)), Some(new InetSocketAddress(hostname, port)), Actor.TIMEOUT)
-
-  def newInstance[T](target: Class[T], config: ActiveObjectConfiguration): T = {
+  def newInstance[T](intfClass: Class[T], targetClass: Class[_], config: TypedActorConfiguration): T = {
     val actor = actorOf(new Dispatcher(config._transactionRequired, config._restartCallbacks, config._shutdownCallback))
-     if (config._messageDispatcher.isDefined) {
-       actor.dispatcher = config._messageDispatcher.get
-     }
-     newInstance(target, actor, config._host, config.timeout)
+    if (config._messageDispatcher.isDefined) actor.dispatcher = config._messageDispatcher.get
+    newInstance(intfClass, newTypedActor(targetClass), actor, config._host, config.timeout)
   }
 
-  def newInstance[T](intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration): T = {
-    val actor = actorOf(new Dispatcher(config._transactionRequired, config._restartCallbacks, config._shutdownCallback))
-     if (config._messageDispatcher.isDefined) {
-       actor.dispatcher = config._messageDispatcher.get
-     }
-     newInstance(intf, target, actor, config._host, config.timeout)
-  }
-
-  @deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
-  def newInstance[T](target: Class[T], timeout: Long, restartCallbacks: Option[RestartCallbacks]): T =
-    newInstance(target, actorOf(new Dispatcher(false, restartCallbacks)), None, timeout)
-
-  @deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
-  def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, restartCallbacks: Option[RestartCallbacks]): T =
-    newInstance(intf, target, actorOf(new Dispatcher(false, restartCallbacks)), None, timeout)
-
-  @deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
-  def newInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean): T =
-    newInstance(target, actorOf(new Dispatcher(transactionRequired, None)), None, timeout)
-
-  @deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
-  def newInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean, restartCallbacks: Option[RestartCallbacks]): T =
-    newInstance(target, actorOf(new Dispatcher(transactionRequired, restartCallbacks)), None, timeout)
-
-  @deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
-  def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean): T =
-    newInstance(intf, target, actorOf(new Dispatcher(transactionRequired, None)), None, timeout)
-
-  @deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
-  def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean, restartCallbacks: Option[RestartCallbacks]): T =
-    newInstance(intf, target, actorOf(new Dispatcher(transactionRequired, restartCallbacks)), None, timeout)
-
-  @deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
-  def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, hostname: String, port: Int): T =
-    newInstance(intf, target, actorOf(new Dispatcher(false, None)), Some(new InetSocketAddress(hostname, port)), timeout)
-
-  @deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
-  def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T =
-    newInstance(intf, target, actorOf(new Dispatcher(false, restartCallbacks)), Some(new InetSocketAddress(hostname, port)), timeout)
-
-  @deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
-  def newRemoteInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean, hostname: String, port: Int): T =
-    newInstance(target, actorOf(new Dispatcher(transactionRequired, None)), Some(new InetSocketAddress(hostname, port)), timeout)
-
-  @deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
-  def newRemoteInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean, hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T =
-    newInstance(target, actorOf(new Dispatcher(transactionRequired, restartCallbacks)), Some(new InetSocketAddress(hostname, port)), timeout)
-
-  @deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
-  def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean, hostname: String, port: Int): T =
-    newInstance(intf, target, actorOf(new Dispatcher(transactionRequired, None)), Some(new InetSocketAddress(hostname, port)), timeout)
-
-  @deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
-  def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean, hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T =
-    newInstance(intf, target, actorOf(new Dispatcher(transactionRequired, restartCallbacks)), Some(new InetSocketAddress(hostname, port)), timeout)
-
-  @deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
-  def newInstance[T](target: Class[T], timeout: Long, dispatcher: MessageDispatcher): T = {
-    val actor = actorOf(new Dispatcher(false, None))
-    actor.dispatcher = dispatcher
-    newInstance(target, actor, None, timeout)
-  }
-
-  @deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
-  def newInstance[T](target: Class[T], timeout: Long, dispatcher: MessageDispatcher, restartCallbacks: Option[RestartCallbacks]): T = {
-    val actor = actorOf(new Dispatcher(false, restartCallbacks))
-    actor.dispatcher = dispatcher
-    newInstance(target, actor, None, timeout)
-  }
-
-  @deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
-  def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, dispatcher: MessageDispatcher): T = {
-    val actor = actorOf(new Dispatcher(false, None))
-    actor.dispatcher = dispatcher
-    newInstance(intf, target, actor, None, timeout)
-  }
-
-  @deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
-  def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long,
-                     dispatcher: MessageDispatcher, restartCallbacks: Option[RestartCallbacks]): T = {
-    val actor = actorOf(new Dispatcher(false, restartCallbacks))
-    actor.dispatcher = dispatcher
-    newInstance(intf, target, actor, None, timeout)
-  }
-
-  @deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
-  def newInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean, dispatcher: MessageDispatcher): T = {
-    val actor = actorOf(new Dispatcher(transactionRequired, None))
-    actor.dispatcher = dispatcher
-    newInstance(target, actor, None, timeout)
-  }
-
-  @deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
-  def newInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean,
-                     dispatcher: MessageDispatcher, restartCallbacks: Option[RestartCallbacks]): T = {
-    val actor = actorOf(new Dispatcher(transactionRequired, restartCallbacks))
-    actor.dispatcher = dispatcher
-    newInstance(target, actor, None, timeout)
-  }
-
-  @deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
-  def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean, dispatcher: MessageDispatcher): T = {
-    val actor = actorOf(new Dispatcher(transactionRequired, None))
-    actor.dispatcher = dispatcher
-    newInstance(intf, target, actor, None, timeout)
-  }
-
-  @deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
-  def newInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean,
-                     dispatcher: MessageDispatcher, restartCallbacks: Option[RestartCallbacks]): T = {
-    val actor = actorOf(new Dispatcher(transactionRequired, restartCallbacks))
-    actor.dispatcher = dispatcher
-    newInstance(intf, target, actor, None, timeout)
-  }
-
-  @deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
-  def newRemoteInstance[T](target: Class[T], timeout: Long, dispatcher: MessageDispatcher, hostname: String, port: Int): T = {
-    val actor = actorOf(new Dispatcher(false, None))
-    actor.dispatcher = dispatcher
-    newInstance(target, actor, Some(new InetSocketAddress(hostname, port)), timeout)
-  }
-
-  @deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
-  def newRemoteInstance[T](target: Class[T], timeout: Long, dispatcher: MessageDispatcher,
-                           hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T = {
-    val actor = actorOf(new Dispatcher(false, restartCallbacks))
-    actor.dispatcher = dispatcher
-    newInstance(target, actor, Some(new InetSocketAddress(hostname, port)), timeout)
-  }
-
-  @deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
-  def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, dispatcher: MessageDispatcher, hostname: String, port: Int): T = {
-    val actor = actorOf(new Dispatcher(false, None))
-    actor.dispatcher = dispatcher
-    newInstance(intf, target, actor, Some(new InetSocketAddress(hostname, port)), timeout)
-  }
-
-  @deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
-  def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, dispatcher: MessageDispatcher,
-                           hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T = {
-    val actor = actorOf(new Dispatcher(false, restartCallbacks))
-    actor.dispatcher = dispatcher
-    newInstance(intf, target, actor, Some(new InetSocketAddress(hostname, port)), timeout)
-  }
-
-  @deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
-  def newRemoteInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean,
-                           dispatcher: MessageDispatcher, hostname: String, port: Int): T = {
-    val actor = actorOf(new Dispatcher(transactionRequired, None))
-    actor.dispatcher = dispatcher
-    newInstance(target, actor, Some(new InetSocketAddress(hostname, port)), timeout)
-  }
-
-  @deprecated("use newInstance(target: Class[T], config: ActiveObjectConfiguration) instead")
-  def newRemoteInstance[T](target: Class[T], timeout: Long, transactionRequired: Boolean, dispatcher: MessageDispatcher,
-                          hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T = {
-    val actor = actorOf(new Dispatcher(transactionRequired, restartCallbacks))
-    actor.dispatcher = dispatcher
-    newInstance(target, actor, Some(new InetSocketAddress(hostname, port)), timeout)
-  }
-
-  @deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
-  def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean,
-                           dispatcher: MessageDispatcher, hostname: String, port: Int): T = {
-    val actor = actorOf(new Dispatcher(transactionRequired, None))
-    actor.dispatcher = dispatcher
-    newInstance(intf, target, actor, Some(new InetSocketAddress(hostname, port)), timeout)
-  }
-
-  @deprecated("use newInstance(intf: Class[T], target: AnyRef, config: ActiveObjectConfiguration) instead")
-  def newRemoteInstance[T](intf: Class[T], target: AnyRef, timeout: Long, transactionRequired: Boolean,
-                           dispatcher: MessageDispatcher, hostname: String, port: Int, restartCallbacks: Option[RestartCallbacks]): T = {
-    val actor = actorOf(new Dispatcher(transactionRequired, restartCallbacks))
-    actor.dispatcher = dispatcher
-    newInstance(intf, target, actor, Some(new InetSocketAddress(hostname, port)), timeout)
-  }
-
-  private[akka] def newInstance[T](target: Class[T], actorRef: ActorRef, remoteAddress: Option[InetSocketAddress], timeout: Long): T = {
-    val proxy = Proxy.newInstance(target, true, false)
-    val context = injectActiveObjectContext(proxy)
-    actorRef.actor.asInstanceOf[Dispatcher].initialize(target, proxy, context)
+  private[akka] def newInstance[T](intfClass: Class[T], targetInstance: TypedActor, actorRef: ActorRef,
+                                   remoteAddress: Option[InetSocketAddress], timeout: Long): T = {
+    val context = injectTypedActorContext(targetInstance)
+    val proxy = Proxy.newInstance(Array(intfClass), Array(targetInstance), true, false)
+    actorRef.actor.asInstanceOf[Dispatcher].initialize(targetInstance.getClass, targetInstance, context)
     actorRef.timeout = timeout
     if (remoteAddress.isDefined) actorRef.makeRemote(remoteAddress.get)
-    AspectInitRegistry.register(proxy, AspectInit(target, actorRef, remoteAddress, timeout))
+    AspectInitRegistry.register(proxy, AspectInit(intfClass, targetInstance, actorRef, remoteAddress, timeout))
     actorRef.start
     proxy.asInstanceOf[T]
   }
 
-  private[akka] def newInstance[T](intf: Class[T], target: AnyRef, actorRef: ActorRef,
-                                   remoteAddress: Option[InetSocketAddress], timeout: Long): T = {
-    val context = injectActiveObjectContext(target)
-    val proxy = Proxy.newInstance(Array(intf), Array(target), true, false)
-    actorRef.actor.asInstanceOf[Dispatcher].initialize(target.getClass, target, context)
+  // NOTE: currently not used - but keep it around
+  private[akka] def newInstance[T <: TypedActor](
+      targetClass: Class[T], actorRef: ActorRef, remoteAddress: Option[InetSocketAddress], timeout: Long): T = {
+    val proxy = { 
+      val instance = Proxy.newInstance(targetClass, true, false)
+      if (instance.isInstanceOf[TypedActor]) instance.asInstanceOf[TypedActor]
+      else throw new IllegalActorStateException("Actor [" + targetClass.getName + "] is not a sub class of 'TypedActor'")
+    }
+    val context = injectTypedActorContext(proxy)
+    actorRef.actor.asInstanceOf[Dispatcher].initialize(targetClass, proxy, context)
     actorRef.timeout = timeout
     if (remoteAddress.isDefined) actorRef.makeRemote(remoteAddress.get)
-    AspectInitRegistry.register(proxy, AspectInit(intf, actorRef, remoteAddress, timeout))
+    AspectInitRegistry.register(proxy, AspectInit(targetClass, proxy, actorRef, remoteAddress, timeout))
     actorRef.start
     proxy.asInstanceOf[T]
   }
@@ -391,120 +288,150 @@ object ActiveObject extends Logging {
   }
 
   /**
-   * Get the underlying dispatcher actor for the given active object.
+   * Get the underlying dispatcher actor for the given typed actor.
    */
   def actorFor(obj: AnyRef): Option[ActorRef] =
     ActorRegistry.actorsFor(classOf[Dispatcher]).find(a => a.actor.asInstanceOf[Dispatcher].target == Some(obj))
 
   /**
-   * Links an other active object to this active object.
-   * @param supervisor the supervisor active object
-   * @param supervised the active object to link
+   * Links an other typed actor to this typed actor.
+   * @param supervisor the supervisor typed actor
+   * @param supervised the typed actor to link
    */
   def link(supervisor: AnyRef, supervised: AnyRef) = {
     val supervisorActor = actorFor(supervisor).getOrElse(
-      throw new IllegalActorStateException("Can't link when the supervisor is not an active object"))
+      throw new IllegalActorStateException("Can't link when the supervisor is not an typed actor"))
     val supervisedActor = actorFor(supervised).getOrElse(
-      throw new IllegalActorStateException("Can't link when the supervised is not an active object"))
+      throw new IllegalActorStateException("Can't link when the supervised is not an typed actor"))
     supervisorActor.link(supervisedActor)
   }
 
   /**
-   * Links an other active object to this active object and sets the fault handling for the supervisor.
-   * @param supervisor the supervisor active object
-   * @param supervised the active object to link
+   * Links an other typed actor to this typed actor and sets the fault handling for the supervisor.
+   * @param supervisor the supervisor typed actor
+   * @param supervised the typed actor to link
    * @param handler fault handling strategy
    * @param trapExceptions array of exceptions that should be handled by the supervisor
    */
-  def link(supervisor: AnyRef, supervised: AnyRef, handler: FaultHandlingStrategy, trapExceptions: Array[Class[_ <: Throwable]]) = {
+  def link(supervisor: AnyRef, supervised: AnyRef, 
+           handler: FaultHandlingStrategy, trapExceptions: Array[Class[_ <: Throwable]]) = {
     val supervisorActor = actorFor(supervisor).getOrElse(
-      throw new IllegalActorStateException("Can't link when the supervisor is not an active object"))
+      throw new IllegalActorStateException("Can't link when the supervisor is not an typed actor"))
     val supervisedActor = actorFor(supervised).getOrElse(
-      throw new IllegalActorStateException("Can't link when the supervised is not an active object"))
+      throw new IllegalActorStateException("Can't link when the supervised is not an typed actor"))
     supervisorActor.trapExit = trapExceptions.toList
     supervisorActor.faultHandler = Some(handler)
     supervisorActor.link(supervisedActor)
   }
 
   /**
-   * Unlink the supervised active object from the supervisor.
-   * @param supervisor the supervisor active object
-   * @param supervised the active object to unlink
+   * Unlink the supervised typed actor from the supervisor.
+   * @param supervisor the supervisor typed actor
+   * @param supervised the typed actor to unlink
    */
   def unlink(supervisor: AnyRef, supervised: AnyRef) = {
     val supervisorActor = actorFor(supervisor).getOrElse(
-      throw new IllegalActorStateException("Can't unlink when the supervisor is not an active object"))
+      throw new IllegalActorStateException("Can't unlink when the supervisor is not an typed actor"))
     val supervisedActor = actorFor(supervised).getOrElse(
-      throw new IllegalActorStateException("Can't unlink when the supervised is not an active object"))
+      throw new IllegalActorStateException("Can't unlink when the supervised is not an typed actor"))
     supervisorActor.unlink(supervisedActor)
   }
 
   /**
-   * Sets the trap exit for the given supervisor active object.
-   * @param supervisor the supervisor active object
+   * Sets the trap exit for the given supervisor typed actor.
+   * @param supervisor the supervisor typed actor
    * @param trapExceptions array of exceptions that should be handled by the supervisor
    */
   def trapExit(supervisor: AnyRef, trapExceptions: Array[Class[_ <: Throwable]]) = {
     val supervisorActor = actorFor(supervisor).getOrElse(
-      throw new IllegalActorStateException("Can't set trap exceptions when the supervisor is not an active object"))
+      throw new IllegalActorStateException("Can't set trap exceptions when the supervisor is not an typed actor"))
     supervisorActor.trapExit = trapExceptions.toList
     this
   }
 
   /**
-   * Sets the fault handling strategy for the given supervisor active object.
-   * @param supervisor the supervisor active object
+   * Sets the fault handling strategy for the given supervisor typed actor.
+   * @param supervisor the supervisor typed actor
    * @param handler fault handling strategy
    */
   def faultHandler(supervisor: AnyRef, handler: FaultHandlingStrategy) = {
     val supervisorActor = actorFor(supervisor).getOrElse(
-      throw new IllegalActorStateException("Can't set fault handler when the supervisor is not an active object"))
+      throw new IllegalActorStateException("Can't set fault handler when the supervisor is not an typed actor"))
     supervisorActor.faultHandler = Some(handler)
     this
   }
 
-  private def injectActiveObjectContext(activeObject: AnyRef): Option[ActiveObjectContext] = {
-    def injectActiveObjectContext0(activeObject: AnyRef, clazz: Class[_]): Option[ActiveObjectContext] = {
-      val contextField = clazz.getDeclaredFields.toList.find(_.getType == classOf[ActiveObjectContext])
+  private def injectTypedActorContext(activeObject: AnyRef): Option[TypedActorContext] = {
+    def injectTypedActorContext0(activeObject: AnyRef, clazz: Class[_]): Option[TypedActorContext] = {
+      val contextField = clazz.getDeclaredFields.toList.find(_.getType == classOf[TypedActorContext])
       if (contextField.isDefined) {
         contextField.get.setAccessible(true)
-        val context = new ActiveObjectContext
+        val context = new TypedActorContext
         contextField.get.set(activeObject, context)
         Some(context)
       } else {
         val parent = clazz.getSuperclass
-        if (parent != null) injectActiveObjectContext0(activeObject, parent)
+        if (parent != null) injectTypedActorContext0(activeObject, parent)
         else {
-          log.ifTrace("Can't set 'ActiveObjectContext' for ActiveObject [" + 
+          log.ifTrace("Can't set 'TypedActorContext' for TypedActor [" + 
                       activeObject.getClass.getName + 
                       "] since no field of this type could be found.")
           None
         }
       }
     }
-    injectActiveObjectContext0(activeObject, activeObject.getClass)
+    injectTypedActorContext0(activeObject, activeObject.getClass)
+  }
+
+  private[akka] def newTypedActor(targetClass: Class[_]): TypedActor = {
+    val instance = targetClass.newInstance
+    if (instance.isInstanceOf[TypedActor]) instance.asInstanceOf[TypedActor]
+    else throw new IllegalArgumentException("Actor [" + targetClass.getName + "] is not a sub class of 'TypedActor'")
   }
 
   private[akka] def supervise(restartStrategy: RestartStrategy, components: List[Supervise]): Supervisor =
     Supervisor(SupervisorConfig(restartStrategy, components))
 }
 
+/**
+ * Internal helper class to help pass the contextual information between threads.
+ *
+ * @author Jonas Bonér
+ */
+private[akka] object TypedActorContext {
+  import scala.util.DynamicVariable
+  private[actor] val sender =       new DynamicVariable[AnyRef](null)
+  private[actor] val senderFuture = new DynamicVariable[CompletableFuture[Any]](null)
+}
+
+/**
+ * @author Jonas Bonér
+ */
+object Annotations {
+  val transactionrequired =    classOf[transactionrequired]
+  val prerestart =             classOf[prerestart]
+  val postrestart =            classOf[postrestart]
+  val shutdown =               classOf[shutdown]
+  val inittransactionalstate = classOf[inittransactionalstate]
+}
+
+/**
+ * @author Jonas Bonér
+ */
 private[akka] object AspectInitRegistry extends ListenerManagement {
   private val initializations = new java.util.concurrent.ConcurrentHashMap[AnyRef, AspectInit]
 
-  def initFor(target: AnyRef) = {
-    initializations.get(target)
-  }
+  def initFor(proxy: AnyRef) = initializations.get(proxy)
 
-  def register(target: AnyRef, init: AspectInit) = {
-    val res = initializations.put(target, init)
-    foreachListener(_ ! AspectInitRegistered(target, init))
+  def register(proxy: AnyRef, init: AspectInit) = {
+    val res = initializations.put(proxy, init)
+    foreachListener(_ ! AspectInitRegistered(proxy, init))
     res
   }
 
-  def unregister(target: AnyRef) = {
-    val res = initializations.remove(target)
-    foreachListener(_ ! AspectInitUnregistered(target, res))
+  def unregister(proxy: AnyRef) = {
+    val res = initializations.remove(proxy)
+    foreachListener(_ ! AspectInitUnregistered(proxy, res))
     res
   }
 }
@@ -513,40 +440,50 @@ private[akka] sealed trait AspectInitRegistryEvent
 private[akka] case class AspectInitRegistered(proxy: AnyRef, init: AspectInit) extends AspectInitRegistryEvent
 private[akka] case class AspectInitUnregistered(proxy: AnyRef, init: AspectInit) extends AspectInitRegistryEvent
 
+/**
+ * @author Jonas Bonér
+ */
 private[akka] sealed case class AspectInit(
-  val target: Class[_],
+  val interfaceClass: Class[_],
+  val targetInstance: TypedActor,
   val actorRef: ActorRef,
   val remoteAddress: Option[InetSocketAddress],
   val timeout: Long) {
-  def this(target: Class[_], actorRef: ActorRef, timeout: Long) = this(target, actorRef, None, timeout)
+  def this(interfaceClass: Class[_], targetInstance: TypedActor, actorRef: ActorRef, timeout: Long) = 
+    this(interfaceClass, targetInstance, actorRef, None, timeout)
 }
 
 /**
- * AspectWerkz Aspect that is turning POJOs into Active Object.
- * Is deployed on a 'per-instance' basis.
+ * AspectWerkz Aspect that is turning POJO into TypedActor.
+ * 

+ * Is deployed on a 'perInstance' basis with the pointcut 'execution(* *.*(..))', + * e.g. all methods on the instance. * * @author Jonas Bonér */ @Aspect("perInstance") -private[akka] sealed class ActiveObjectAspect { +private[akka] sealed class TypedActorAspect { @volatile private var isInitialized = false @volatile private var isStopped = false - private var target: Class[_] = _ + private var interfaceClass: Class[_] = _ + private var targetInstance: TypedActor = _ private var actorRef: ActorRef = _ private var remoteAddress: Option[InetSocketAddress] = _ private var timeout: Long = _ - @volatile private var instance: AnyRef = _ + private var uuid: String = _ + @volatile private var instance: TypedActor = _ @Around("execution(* *.*(..))") def invoke(joinPoint: JoinPoint): AnyRef = { if (!isInitialized) { val init = AspectInitRegistry.initFor(joinPoint.getThis) - target = init.target + interfaceClass = init.interfaceClass + targetInstance = init.targetInstance + uuid = targetInstance.uuid actorRef = init.actorRef remoteAddress = init.remoteAddress timeout = init.timeout isInitialized = true - } dispatch(joinPoint) } @@ -559,15 +496,17 @@ private[akka] sealed class ActiveObjectAspect { private def localDispatch(joinPoint: JoinPoint): AnyRef = { val rtti = joinPoint.getRtti.asInstanceOf[MethodRtti] val isOneWay = isVoid(rtti) - val sender = ActiveObjectContext.sender.value - val senderFuture = ActiveObjectContext.senderFuture.value + val sender = TypedActorContext.sender.value + val senderFuture = TypedActorContext.senderFuture.value if (!actorRef.isRunning && !isStopped) { isStopped = true joinPoint.proceed + } else if (isOneWay) { actorRef ! Invocation(joinPoint, true, true, sender, senderFuture) null.asInstanceOf[AnyRef] + } else { val result = (actorRef !! (Invocation(joinPoint, false, isOneWay, sender, senderFuture), timeout)).as[AnyRef] if (result.isDefined) result.get @@ -579,20 +518,32 @@ private[akka] sealed class ActiveObjectAspect { val rtti = joinPoint.getRtti.asInstanceOf[MethodRtti] val isOneWay = isVoid(rtti) val (message: Array[AnyRef], isEscaped) = escapeArguments(rtti.getParameterValues) + + val typedActorInfo = TypedActorInfoProtocol.newBuilder + .setInterface(interfaceClass.getName) + .setMethod(rtti.getMethod.getName) + .build + + val actorInfo = ActorInfoProtocol.newBuilder + .setUuid(uuid) + .setTarget(targetInstance.getClass.getName) + .setTimeout(timeout) + .setActorType(ActorType.TYPED_ACTOR) + .build + val requestBuilder = RemoteRequestProtocol.newBuilder .setId(RemoteRequestProtocolIdFactory.nextId) .setMessage(MessageSerializer.serialize(message)) - .setMethod(rtti.getMethod.getName) - .setTarget(target.getName) - .setUuid(actorRef.uuid) - .setTimeout(timeout) - .setIsActor(false) + .setActorInfo(actorInfo) .setIsOneWay(isOneWay) - .setIsEscaped(false) + val id = actorRef.registerSupervisorAsRemoteActor if (id.isDefined) requestBuilder.setSupervisorUuid(id.get) + val remoteMessage = requestBuilder.build + val future = RemoteClient.clientFor(remoteAddress.get).send(remoteMessage, None) + if (isOneWay) null // for void methods else { if (future.isDefined) { @@ -616,9 +567,9 @@ private[akka] sealed class ActiveObjectAspect { var isEscaped = false val escapedArgs = for (arg <- args) yield { val clazz = arg.getClass - if (clazz.getName.contains(ActiveObject.AW_PROXY_PREFIX)) { + if (clazz.getName.contains(TypedActor.AW_PROXY_PREFIX)) { isEscaped = true - ActiveObject.AW_PROXY_PREFIX + clazz.getSuperclass.getName + TypedActor.AW_PROXY_PREFIX + clazz.getSuperclass.getName } else arg } (escapedArgs, isEscaped) @@ -685,20 +636,21 @@ private[akka] class Dispatcher(transactionalRequired: Boolean, private var preRestart: Option[Method] = None private var postRestart: Option[Method] = None private var initTxState: Option[Method] = None - private var context: Option[ActiveObjectContext] = None - private var targetClass:Class[_] = _ + private var context: Option[TypedActorContext] = None + private var targetClass: Class[_] = _ def this(transactionalRequired: Boolean) = this(transactionalRequired,None) - private[actor] def initialize(targetClass: Class[_], targetInstance: AnyRef, ctx: Option[ActiveObjectContext]) = { + private[actor] def initialize(targetClass: Class[_], proxy: AnyRef, ctx: Option[TypedActorContext]) = { if (transactionalRequired || targetClass.isAnnotationPresent(Annotations.transactionrequired)) self.makeTransactionRequired self.id = targetClass.getName this.targetClass = targetClass - target = Some(targetInstance) + target = Some(proxy) context = ctx - val methods = targetInstance.getClass.getDeclaredMethods.toList + val proxyClass = proxy.getClass + val methods = proxyClass.getDeclaredMethods.toList if (self.lifeCycle.isEmpty) self.lifeCycle = Some(LifeCycle(Permanent)) @@ -707,12 +659,12 @@ private[akka] class Dispatcher(transactionalRequired: Boolean, case None => {} case Some(RestartCallbacks(pre, post)) => preRestart = Some(try { - targetInstance.getClass.getDeclaredMethod(pre, ZERO_ITEM_CLASS_ARRAY: _*) + proxyClass.getDeclaredMethod(pre, ZERO_ITEM_CLASS_ARRAY: _*) } catch { case e => throw new IllegalActorStateException( "Could not find pre restart method [" + pre + "] \nin [" + targetClass.getName + "]. \nIt must have a zero argument definition.") }) postRestart = Some(try { - targetInstance.getClass.getDeclaredMethod(post, ZERO_ITEM_CLASS_ARRAY: _*) + proxyClass.getDeclaredMethod(post, ZERO_ITEM_CLASS_ARRAY: _*) } catch { case e => throw new IllegalActorStateException( "Could not find post restart method [" + post + "] \nin [" + targetClass.getName + "]. \nIt must have a zero argument definition.") }) @@ -722,7 +674,7 @@ private[akka] class Dispatcher(transactionalRequired: Boolean, case None => {} case Some(ShutdownCallback(down)) => zhutdown = Some(try { - targetInstance.getClass.getDeclaredMethod(down, ZERO_ITEM_CLASS_ARRAY: _*) + proxyClass.getDeclaredMethod(down, ZERO_ITEM_CLASS_ARRAY: _*) } catch { case e => throw new IllegalStateException( "Could not find shutdown method [" + down + "] \nin [" + targetClass.getName + "]. \nIt must have a zero argument definition.") }) @@ -760,13 +712,13 @@ private[akka] class Dispatcher(transactionalRequired: Boolean, def receive = { case invocation @ Invocation(joinPoint, isOneWay, _, sender, senderFuture) => - ActiveObject.log.ifTrace("Invoking active object with message:\n" + invocation) + TypedActor.log.ifTrace("Invoking typed actor with message:\n" + invocation) context.foreach { ctx => if (sender ne null) ctx._sender = sender if (senderFuture ne null) ctx._senderFuture = senderFuture } - ActiveObjectContext.sender.value = joinPoint.getThis // set next sender - self.senderFuture.foreach(ActiveObjectContext.senderFuture.value = _) + TypedActorContext.sender.value = joinPoint.getThis // set next sender + self.senderFuture.foreach(TypedActorContext.senderFuture.value = _) if (Actor.SERIALIZE_MESSAGES) serializeArguments(joinPoint) if (isOneWay) joinPoint.proceed else self.reply(joinPoint.proceed) @@ -843,7 +795,7 @@ private[akka] class Dispatcher(transactionalRequired: Boolean, !arg.isInstanceOf[java.lang.Character]) { hasMutableArgument = true } - if (arg.getClass.getName.contains(ActiveObject.AW_PROXY_PREFIX)) unserializable = true + if (arg.getClass.getName.contains(TypedActor.AW_PROXY_PREFIX)) unserializable = true } if (!unserializable && hasMutableArgument) { val copyOfArgs = Serializer.Java.deepClone(args) diff --git a/akka-core/src/main/scala/config/Configuration.scala b/akka-core/src/main/scala/config/Configuration.scala index faa5c912f1..e257c739a9 100644 --- a/akka-core/src/main/scala/config/Configuration.scala +++ b/akka-core/src/main/scala/config/Configuration.scala @@ -5,7 +5,7 @@ package se.scalablesolutions.akka.config /* -import se.scalablesolutions.akka.kernel.{ActiveObject, ActiveObjectProxy} +import se.scalablesolutions.akka.kernel.{TypedActor, TypedActorProxy} import com.google.inject.{AbstractModule} import java.util.{List => JList, ArrayList} import scala.reflect.BeanProperty @@ -55,6 +55,6 @@ class Component(@BeanProperty val intf: Class[_], @BeanProperty val target: Class[_], @BeanProperty val lifeCycle: LifeCycle, @BeanProperty val timeout: Int) extends Server { - def newWorker(proxy: ActiveObjectProxy) = se.scalablesolutions.akka.kernel.Supervise(proxy.server, lifeCycle.transform) + def newWorker(proxy: TypedActorProxy) = se.scalablesolutions.akka.kernel.Supervise(proxy.server, lifeCycle.transform) } */ diff --git a/akka-core/src/main/scala/config/Configurator.scala b/akka-core/src/main/scala/config/Configurator.scala index db92c5f35b..ba7e1f35f2 100644 --- a/akka-core/src/main/scala/config/Configurator.scala +++ b/akka-core/src/main/scala/config/Configurator.scala @@ -6,14 +6,14 @@ package se.scalablesolutions.akka.config import ScalaConfig.{RestartStrategy, Component} -private[akka] trait ActiveObjectConfiguratorBase { +private[akka] trait TypedActorConfiguratorBase { def getExternalDependency[T](clazz: Class[T]): T - def configure(restartStrategy: RestartStrategy, components: List[Component]): ActiveObjectConfiguratorBase + def configure(restartStrategy: RestartStrategy, components: List[Component]): TypedActorConfiguratorBase - def inject: ActiveObjectConfiguratorBase + def inject: TypedActorConfiguratorBase - def supervise: ActiveObjectConfiguratorBase + def supervise: TypedActorConfiguratorBase def reset diff --git a/akka-core/src/main/scala/config/ActiveObjectConfigurator.scala b/akka-core/src/main/scala/config/TypedActorConfigurator.scala similarity index 56% rename from akka-core/src/main/scala/config/ActiveObjectConfigurator.scala rename to akka-core/src/main/scala/config/TypedActorConfigurator.scala index 88e495bbd0..797d52cd70 100644 --- a/akka-core/src/main/scala/config/ActiveObjectConfigurator.scala +++ b/akka-core/src/main/scala/config/TypedActorConfigurator.scala @@ -12,54 +12,55 @@ import java.util.{ArrayList} import com.google.inject._ /** - * Configurator for the Active Objects. Used to do declarative configuration of supervision. - * It also does dependency injection with and into Active Objects using dependency injection + * Configurator for the TypedActors. Used to do declarative configuration of supervision. + * It also does dependency injection with and into TypedActors using dependency injection * frameworks such as Google Guice or Spring. *

- * If you don't want declarative configuration then you should use the ActiveObject + * If you don't want declarative configuration then you should use the TypedActor * factory methods. * * @author Jonas Bonér */ -class ActiveObjectConfigurator { +class TypedActorConfigurator { import scala.collection.JavaConversions._ // TODO: make pluggable once we have f.e a SpringConfigurator - private val INSTANCE = new ActiveObjectGuiceConfigurator + private val INSTANCE = new TypedActorGuiceConfigurator /** - * Returns the a list with all active objects that has been put under supervision for the class specified. + * Returns the a list with all typed actors that has been put under supervision for the class specified. * - * @param clazz the class for the active object - * @return a list with all the active objects for the class + * @param clazz the class for the typed actor + * @return a list with all the typed actors for the class */ - def getInstances[T](clazz: Class[T]): JList[T] = INSTANCE.getInstance(clazz).foldLeft(new ArrayList[T]){ (l, i) => l add i ; l } + def getInstances[T](clazz: Class[T]): JList[T] = + INSTANCE.getInstance(clazz).foldLeft(new ArrayList[T]){ (l, i) => l add i ; l } /** - * Returns the first item in a list of all active objects that has been put under supervision for the class specified. + * Returns the first item in a list of all typed actors that has been put under supervision for the class specified. * - * @param clazz the class for the active object - * @return the active object for the class + * @param clazz the class for the typed actor + * @return the typed actor for the class */ def getInstance[T](clazz: Class[T]): T = INSTANCE.getInstance(clazz).head - def configure(restartStrategy: RestartStrategy, components: Array[Component]): ActiveObjectConfigurator = { + def configure(restartStrategy: RestartStrategy, components: Array[Component]): TypedActorConfigurator = { INSTANCE.configure( restartStrategy.transform, components.toList.asInstanceOf[scala.List[Component]].map(_.transform)) this } - def inject: ActiveObjectConfigurator = { + def inject: TypedActorConfigurator = { INSTANCE.inject this } - def supervise: ActiveObjectConfigurator = { + def supervise: TypedActorConfigurator = { INSTANCE.supervise this } - def addExternalGuiceModule(module: Module): ActiveObjectConfigurator = { + def addExternalGuiceModule(module: Module): TypedActorConfigurator = { INSTANCE.addExternalGuiceModule(module) this } diff --git a/akka-core/src/main/scala/config/ActiveObjectGuiceConfigurator.scala b/akka-core/src/main/scala/config/TypedActorGuiceConfigurator.scala similarity index 73% rename from akka-core/src/main/scala/config/ActiveObjectGuiceConfigurator.scala rename to akka-core/src/main/scala/config/TypedActorGuiceConfigurator.scala index 54174b6030..f6c78a6a30 100644 --- a/akka-core/src/main/scala/config/ActiveObjectGuiceConfigurator.scala +++ b/akka-core/src/main/scala/config/TypedActorGuiceConfigurator.scala @@ -7,7 +7,7 @@ package se.scalablesolutions.akka.config import com.google.inject._ import se.scalablesolutions.akka.config.ScalaConfig._ -import se.scalablesolutions.akka.actor.{Supervisor, ActiveObject, Dispatcher, ActorRef, Actor, IllegalActorStateException} +import se.scalablesolutions.akka.actor.{Supervisor, TypedActor, Dispatcher, ActorRef, Actor, IllegalActorStateException} import se.scalablesolutions.akka.remote.RemoteServer import se.scalablesolutions.akka.util.Logging @@ -17,12 +17,12 @@ import java.net.InetSocketAddress import java.lang.reflect.Method /** - * This is an class for internal usage. Instead use the se.scalablesolutions.akka.config.ActiveObjectConfigurator - * class for creating ActiveObjects. + * This is an class for internal usage. Instead use the se.scalablesolutions.akka.config.TypedActorConfigurator + * class for creating TypedActors. * * @author Jonas Bonér */ -private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfiguratorBase with Logging { +private[akka] class TypedActorGuiceConfigurator extends TypedActorConfiguratorBase with Logging { private var injector: Injector = _ private var supervisor: Option[Supervisor] = None private var restartStrategy: RestartStrategy = _ @@ -37,11 +37,11 @@ private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurat /** * Returns the active abject that has been put under supervision for the class specified. * - * @param clazz the class for the active object - * @return the active objects for the class + * @param clazz the class for the typed actor + * @return the typed actors for the class */ def getInstance[T](clazz: Class[T]): List[T] = synchronized { - log.debug("Retrieving active object [%s]", clazz.getName) + log.debug("Retrieving typed actor [%s]", clazz.getName) if (injector eq null) throw new IllegalActorStateException( "inject() and/or supervise() must be called before invoking getInstance(clazz)") val (proxy, targetInstance, component) = @@ -67,7 +67,7 @@ private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurat } override def configure(restartStrategy: RestartStrategy, components: List[Component]): - ActiveObjectConfiguratorBase = synchronized { + TypedActorConfiguratorBase = synchronized { this.restartStrategy = restartStrategy this.components = components.toArray.toList.asInstanceOf[List[Component]] bindings = for (component <- this.components) yield { @@ -76,12 +76,14 @@ private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurat } val deps = new java.util.ArrayList[DependencyBinding](bindings.size) for (b <- bindings) deps.add(b) - modules.add(new ActiveObjectGuiceModule(deps)) + modules.add(new TypedActorGuiceModule(deps)) this } private def newSubclassingProxy(component: Component): DependencyBinding = { - val targetClass = component.target + val targetClass = + if (component.target.isInstanceOf[Class[_ <: TypedActor]]) component.target.asInstanceOf[Class[_ <: TypedActor]] + else throw new IllegalArgumentException("TypedActor [" + component.target.getName + "] must be a subclass of TypedActor") val actorRef = Actor.actorOf(new Dispatcher(component.transactionRequired, component.lifeCycle.restartCallbacks, component.lifeCycle.shutdownCallback)) @@ -90,8 +92,8 @@ private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurat if (component.remoteAddress.isDefined) Some(new InetSocketAddress(component.remoteAddress.get.hostname, component.remoteAddress.get.port)) else None - val proxy = ActiveObject.newInstance(targetClass, actorRef, remoteAddress, component.timeout).asInstanceOf[AnyRef] - remoteAddress.foreach(address => RemoteServer.registerActiveObject(address, targetClass.getName, proxy)) + val proxy = TypedActor.newInstance(targetClass, actorRef, remoteAddress, component.timeout).asInstanceOf[AnyRef] + remoteAddress.foreach(address => RemoteServer.registerTypedActor(address, targetClass.getName, proxy)) supervised ::= Supervise(actorRef, component.lifeCycle) activeObjectRegistry.put(targetClass, (proxy, proxy, component)) new DependencyBinding(targetClass, proxy) @@ -99,7 +101,12 @@ private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurat private def newDelegatingProxy(component: Component): DependencyBinding = { val targetClass = component.intf.get - val targetInstance = component.target.newInstance.asInstanceOf[AnyRef] // TODO: perhaps need to put in registry + val instance = component.target.newInstance.asInstanceOf[AnyRef] // TODO: perhaps need to put in registry + val targetInstance = + if (instance.isInstanceOf[TypedActor]) component.target.asInstanceOf[TypedActor] + else throw new IllegalArgumentException("TypedActor [" + component.target.getName + "] must be a subclass of TypedActor") + if (!component.target.isInstanceOf[TypedActor]) throw new IllegalArgumentException( + "TypedActor [" + component.target + "] must be a subclass of TypedActor") component.target.getConstructor(Array[Class[_]](): _*).setAccessible(true) val actorRef = Actor.actorOf(new Dispatcher(component.transactionRequired, component.lifeCycle.restartCallbacks, @@ -109,23 +116,23 @@ private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurat if (component.remoteAddress.isDefined) Some(new InetSocketAddress(component.remoteAddress.get.hostname, component.remoteAddress.get.port)) else None - val proxy = ActiveObject.newInstance( + val proxy = TypedActor.newInstance( targetClass, targetInstance, actorRef, remoteAddress, component.timeout).asInstanceOf[AnyRef] - remoteAddress.foreach(address => RemoteServer.registerActiveObject(address, targetClass.getName, proxy)) + remoteAddress.foreach(address => RemoteServer.registerTypedActor(address, targetClass.getName, proxy)) supervised ::= Supervise(actorRef, component.lifeCycle) activeObjectRegistry.put(targetClass, (proxy, targetInstance, component)) new DependencyBinding(targetClass, proxy) } - override def inject: ActiveObjectConfiguratorBase = synchronized { + override def inject: TypedActorConfiguratorBase = synchronized { if (injector ne null) throw new IllegalActorStateException("inject() has already been called on this configurator") injector = Guice.createInjector(modules) this } - override def supervise: ActiveObjectConfiguratorBase = synchronized { + override def supervise: TypedActorConfiguratorBase = synchronized { if (injector eq null) inject - supervisor = Some(ActiveObject.supervise(restartStrategy, supervised)) + supervisor = Some(TypedActor.supervise(restartStrategy, supervised)) this } @@ -141,7 +148,7 @@ private[akka] class ActiveObjectGuiceConfigurator extends ActiveObjectConfigurat * }}) *

*/ - def addExternalGuiceModule(module: Module): ActiveObjectConfiguratorBase = synchronized { + def addExternalGuiceModule(module: Module): TypedActorConfiguratorBase = synchronized { modules.add(module) this } diff --git a/akka-core/src/main/scala/remote/RemoteClient.scala b/akka-core/src/main/scala/remote/RemoteClient.scala index 2936b73b67..a08348e461 100644 --- a/akka-core/src/main/scala/remote/RemoteClient.scala +++ b/akka-core/src/main/scala/remote/RemoteClient.scala @@ -137,7 +137,7 @@ object RemoteClient extends Logging { actorsFor(RemoteServer.Address(hostname, port)) += uuid } - // TODO: add RemoteClient.unregister for ActiveObject, but first need a @shutdown callback + // TODO: add RemoteClient.unregister for TypedActor, but first need a @shutdown callback private[akka] def unregister(hostname: String, port: Int, uuid: String) = synchronized { val set = actorsFor(RemoteServer.Address(hostname, port)) set -= uuid @@ -217,7 +217,7 @@ class RemoteClient private[akka] (val hostname: String, val port: Int, loader: O } else { futures.synchronized { val futureResult = if (senderFuture.isDefined) senderFuture.get - else new DefaultCompletableFuture[T](request.getTimeout) + else new DefaultCompletableFuture[T](request.getActorInfo.getTimeout) futures.put(request.getId, futureResult) connection.getChannel.write(request) Some(futureResult) @@ -230,11 +230,13 @@ class RemoteClient private[akka] (val hostname: String, val port: Int, loader: O } private[akka] def registerSupervisorForActor(actorRef: ActorRef) = - if (!actorRef.supervisor.isDefined) throw new IllegalActorStateException("Can't register supervisor for " + actorRef + " since it is not under supervision") + if (!actorRef.supervisor.isDefined) throw new IllegalActorStateException( + "Can't register supervisor for " + actorRef + " since it is not under supervision") else supervisors.putIfAbsent(actorRef.supervisor.get.uuid, actorRef) private[akka] def deregisterSupervisorForActor(actorRef: ActorRef) = - if (!actorRef.supervisor.isDefined) throw new IllegalActorStateException("Can't unregister supervisor for " + actorRef + " since it is not under supervision") + if (!actorRef.supervisor.isDefined) throw new IllegalActorStateException( + "Can't unregister supervisor for " + actorRef + " since it is not under supervision") else supervisors.remove(actorRef.supervisor.get.uuid) } diff --git a/akka-core/src/main/scala/remote/RemoteServer.scala b/akka-core/src/main/scala/remote/RemoteServer.scala index c3f5cc4f0a..e93fc4db48 100644 --- a/akka-core/src/main/scala/remote/RemoteServer.scala +++ b/akka-core/src/main/scala/remote/RemoteServer.scala @@ -55,7 +55,7 @@ object RemoteNode extends RemoteServer /** * For internal use only. - * Holds configuration variables, remote actors, remote active objects and remote servers. + * Holds configuration variables, remote actors, remote typed actors and remote servers. * * @author Jonas Bonér */ @@ -104,7 +104,7 @@ object RemoteServer { actorsFor(RemoteServer.Address(address.getHostName, address.getPort)).actors.put(uuid, actor) } - private[akka] def registerActiveObject(address: InetSocketAddress, name: String, activeObject: AnyRef) = guard.withWriteGuard { + private[akka] def registerTypedActor(address: InetSocketAddress, name: String, activeObject: AnyRef) = guard.withWriteGuard { actorsFor(RemoteServer.Address(address.getHostName, address.getPort)).activeObjects.put(name, activeObject) } @@ -228,7 +228,7 @@ class RemoteServer extends Logging { } } - // TODO: register active object in RemoteServer as well + // TODO: register typed actor in RemoteServer as well /** * Register Remote Actor by the Actor's 'id' field. It starts the Actor if it is not started already. @@ -360,139 +360,88 @@ class RemoteServerHandler( private def handleRemoteRequestProtocol(request: RemoteRequestProtocol, channel: Channel) = { log.debug("Received RemoteRequestProtocol[\n%s]", request.toString) - if (request.getIsActor) dispatchToActor(request, channel) - else dispatchToActiveObject(request, channel) + val actorType = request.getActorInfo.getActorType + if (actorType == ActorType.SCALA_ACTOR) dispatchToActor(request, channel) + else if (actorType == ActorType.JAVA_ACTOR) throw new IllegalActorStateException("ActorType JAVA_ACTOR is currently not supported") + else if (actorType == ActorType.TYPED_ACTOR) dispatchToTypedActor(request, channel) + else throw new IllegalActorStateException("Unknown ActorType [" + actorType + "]") } private def dispatchToActor(request: RemoteRequestProtocol, channel: Channel) = { - log.debug("Dispatching to remote actor [%s:%s]", request.getTarget, request.getUuid) - val actorRef = createActor(request.getTarget, request.getUuid, request.getTimeout) + val actorInfo = request.getActorInfo + log.debug("Dispatching to remote actor [%s:%s]", actorInfo.getTarget, actorInfo.getUuid) + + val actorRef = createActor(actorInfo) actorRef.start + val message = MessageSerializer.deserialize(request.getMessage) val sender = if (request.hasSender) Some(RemoteActorSerialization.fromProtobufToRemoteActorRef(request.getSender, applicationLoader)) else None + if (request.getIsOneWay) actorRef.!(message)(sender) else { try { val resultOrNone = (actorRef.!!(message)(sender)).as[AnyRef] val result = if (resultOrNone.isDefined) resultOrNone.get else null + log.debug("Returning result from actor invocation [%s]", result) val replyBuilder = RemoteReplyProtocol.newBuilder .setId(request.getId) .setMessage(MessageSerializer.serialize(result)) .setIsSuccessful(true) .setIsActor(true) + if (request.hasSupervisorUuid) replyBuilder.setSupervisorUuid(request.getSupervisorUuid) - val replyMessage = replyBuilder.build - channel.write(replyMessage) + channel.write(replyBuilder.build) + } catch { - case e: Throwable => - log.error(e, "Could not invoke remote actor [%s]", request.getTarget) - val replyBuilder = RemoteReplyProtocol.newBuilder - .setId(request.getId) - .setException(ExceptionProtocol.newBuilder.setClassname(e.getClass.getName).setMessage(e.getMessage).build) - .setIsSuccessful(false) - .setIsActor(true) - if (request.hasSupervisorUuid) replyBuilder.setSupervisorUuid(request.getSupervisorUuid) - val replyMessage = replyBuilder.build - channel.write(replyMessage) + case e: Throwable => channel.write(createErrorReplyMessage(e, request, true)) } } } - private def dispatchToActiveObject(request: RemoteRequestProtocol, channel: Channel) = { - log.debug("Dispatching to remote active object [%s :: %s]", request.getMethod, request.getTarget) - val activeObject = createActiveObject(request.getTarget, request.getTimeout) + private def dispatchToTypedActor(request: RemoteRequestProtocol, channel: Channel) = { + val actorInfo = request.getActorInfo + val typedActorInfo = actorInfo.getTypedActorInfo + log.debug("Dispatching to remote typed actor [%s :: %s]", typedActorInfo.getMethod, typedActorInfo.getInterface) + val activeObject = createTypedActor(actorInfo) val args = MessageSerializer.deserialize(request.getMessage).asInstanceOf[Array[AnyRef]].toList val argClasses = args.map(_.getClass) - val (unescapedArgs, unescapedArgClasses) = unescapeArgs(args, argClasses, request.getTimeout) try { - val messageReceiver = activeObject.getClass.getDeclaredMethod( - request.getMethod, unescapedArgClasses: _*) - if (request.getIsOneWay) messageReceiver.invoke(activeObject, unescapedArgs: _*) + val messageReceiver = activeObject.getClass.getDeclaredMethod(typedActorInfo.getMethod, argClasses: _*) + if (request.getIsOneWay) messageReceiver.invoke(activeObject, args: _*) else { - val result = messageReceiver.invoke(activeObject, unescapedArgs: _*) - log.debug("Returning result from remote active object invocation [%s]", result) + val result = messageReceiver.invoke(activeObject, args: _*) + log.debug("Returning result from remote typed actor invocation [%s]", result) val replyBuilder = RemoteReplyProtocol.newBuilder .setId(request.getId) .setMessage(MessageSerializer.serialize(result)) .setIsSuccessful(true) .setIsActor(false) if (request.hasSupervisorUuid) replyBuilder.setSupervisorUuid(request.getSupervisorUuid) - val replyMessage = replyBuilder.build - channel.write(replyMessage) + channel.write(replyBuilder.build) } } catch { - case e: InvocationTargetException => - log.error(e.getCause, "Could not invoke remote active object [%s :: %s]", request.getMethod, request.getTarget) - val replyBuilder = RemoteReplyProtocol.newBuilder - .setId(request.getId) - .setException(ExceptionProtocol.newBuilder.setClassname(e.getCause.getClass.getName).setMessage(e.getCause.getMessage).build) - .setIsSuccessful(false) - .setIsActor(false) - if (request.hasSupervisorUuid) replyBuilder.setSupervisorUuid(request.getSupervisorUuid) - val replyMessage = replyBuilder.build - channel.write(replyMessage) - case e: Throwable => - log.error(e, "Could not invoke remote active object [%s :: %s]", request.getMethod, request.getTarget) - val replyBuilder = RemoteReplyProtocol.newBuilder - .setId(request.getId) - .setException(ExceptionProtocol.newBuilder.setClassname(e.getClass.getName).setMessage(e.getMessage).build) - .setIsSuccessful(false) - .setIsActor(false) - if (request.hasSupervisorUuid) replyBuilder.setSupervisorUuid(request.getSupervisorUuid) - val replyMessage = replyBuilder.build - channel.write(replyMessage) + case e: InvocationTargetException => channel.write(createErrorReplyMessage(e.getCause, request, false)) + case e: Throwable => channel.write(createErrorReplyMessage(e, request, false)) } } - private def unescapeArgs(args: scala.List[AnyRef], argClasses: scala.List[Class[_]], timeout: Long) = { - val unescapedArgs = new Array[AnyRef](args.size) - val unescapedArgClasses = new Array[Class[_]](args.size) - - val escapedArgs = for (i <- 0 until args.size) { - val arg = args(i) - if (arg.isInstanceOf[String] && arg.asInstanceOf[String].startsWith(AW_PROXY_PREFIX)) { - val argString = arg.asInstanceOf[String] - val proxyName = argString.replace(AW_PROXY_PREFIX, "") - val activeObject = createActiveObject(proxyName, timeout) - unescapedArgs(i) = activeObject - unescapedArgClasses(i) = Class.forName(proxyName) - } else { - unescapedArgs(i) = args(i) - unescapedArgClasses(i) = argClasses(i) - } - } - (unescapedArgs, unescapedArgClasses) - } - - private def createActiveObject(name: String, timeout: Long): AnyRef = { - val activeObjectOrNull = activeObjects.get(name) - if (activeObjectOrNull eq null) { - try { - log.info("Creating a new remote active object [%s]", name) - val clazz = if (applicationLoader.isDefined) applicationLoader.get.loadClass(name) - else Class.forName(name) - val newInstance = ActiveObject.newInstance(clazz, timeout).asInstanceOf[AnyRef] - activeObjects.put(name, newInstance) - newInstance - } catch { - case e => - log.error(e, "Could not create remote active object instance") - throw e - } - } else activeObjectOrNull - } - /** * Creates a new instance of the actor with name, uuid and timeout specified as arguments. + * * If actor already created then just return it from the registry. + * * Does not start the actor. */ - private def createActor(name: String, uuid: String, timeout: Long): ActorRef = { + private def createActor(actorInfo: ActorInfoProtocol): ActorRef = { + val name = actorInfo.getTarget + val uuid = actorInfo.getUuid + val timeout = actorInfo.getTimeout + val actorRefOrNull = actors.get(uuid) if (actorRefOrNull eq null) { try { @@ -512,4 +461,43 @@ class RemoteServerHandler( } } else actorRefOrNull } + + private def createTypedActor(actorInfo: ActorInfoProtocol): AnyRef = { + val uuid = actorInfo.getUuid + val activeObjectOrNull = activeObjects.get(uuid) + + if (activeObjectOrNull eq null) { + val typedActorInfo = actorInfo.getTypedActorInfo + val interfaceClassname = typedActorInfo.getInterface + val targetClassname = actorInfo.getTarget + + try { + log.info("Creating a new remote typed actor:\n\t[%s :: %s]", interfaceClassname, targetClassname) + + val (interfaceClass, targetClass) = + if (applicationLoader.isDefined) (applicationLoader.get.loadClass(interfaceClassname), + applicationLoader.get.loadClass(targetClassname)) + else (Class.forName(interfaceClassname), Class.forName(targetClassname)) + + val newInstance = TypedActor.newInstance( + interfaceClass, targetClass.asInstanceOf[Class[_ <: TypedActor]], actorInfo.getTimeout).asInstanceOf[AnyRef] + activeObjects.put(uuid, newInstance) + newInstance + } catch { + case e => log.error(e, "Could not create remote typed actor instance"); throw e + } + } else activeObjectOrNull + } + + private def createErrorReplyMessage(e: Throwable, request: RemoteRequestProtocol, isActor: Boolean): RemoteReplyProtocol = { + val actorInfo = request.getActorInfo + log.error(e, "Could not invoke remote typed actor [%s :: %s]", actorInfo.getTypedActorInfo.getMethod, actorInfo.getTarget) + val replyBuilder = RemoteReplyProtocol.newBuilder + .setId(request.getId) + .setException(ExceptionProtocol.newBuilder.setClassname(e.getClass.getName).setMessage(e.getMessage).build) + .setIsSuccessful(false) + .setIsActor(isActor) + if (request.hasSupervisorUuid) replyBuilder.setSupervisorUuid(request.getSupervisorUuid) + replyBuilder.build + } } diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/NestedTransactionalActiveObject.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/NestedTransactionalTypedActor.java similarity index 89% rename from akka-core/src/test/java/se/scalablesolutions/akka/actor/NestedTransactionalActiveObject.java rename to akka-core/src/test/java/se/scalablesolutions/akka/actor/NestedTransactionalTypedActor.java index af6bb8245c..fa13417f8b 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/NestedTransactionalActiveObject.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/NestedTransactionalTypedActor.java @@ -5,7 +5,7 @@ import se.scalablesolutions.akka.actor.annotation.inittransactionalstate; import se.scalablesolutions.akka.stm.*; @transactionrequired -public class NestedTransactionalActiveObject { +public class NestedTransactionalTypedActor { private TransactionalMap mapState; private TransactionalVector vectorState; private Ref refState; @@ -58,7 +58,7 @@ public class NestedTransactionalActiveObject { } - public String failure(String key, String msg, ActiveObjectFailer failer) { + public String failure(String key, String msg, TypedActorFailer failer) { mapState.put(key, msg); vectorState.add(msg); refState.swap(msg); @@ -67,7 +67,7 @@ public class NestedTransactionalActiveObject { } - public void thisMethodHangs(String key, String msg, ActiveObjectFailer failer) { + public void thisMethodHangs(String key, String msg, TypedActorFailer failer) { setMapState(key, msg); } diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojo.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojo.java index 31f22c217f..b068af4f12 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojo.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojo.java @@ -2,12 +2,12 @@ package se.scalablesolutions.akka.actor; import se.scalablesolutions.akka.actor.annotation.prerestart; import se.scalablesolutions.akka.actor.annotation.postrestart; -import se.scalablesolutions.akka.actor.ActiveObjectContext; +import se.scalablesolutions.akka.actor.TypedActorContext; import se.scalablesolutions.akka.dispatch.CompletableFuture; public class SimpleJavaPojo { - ActiveObjectContext context; + TypedActorContext context; public boolean pre = false; public boolean post = false; diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/TransactionalActiveObject.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/TransactionalTypedActor.java similarity index 88% rename from akka-core/src/test/java/se/scalablesolutions/akka/actor/TransactionalActiveObject.java rename to akka-core/src/test/java/se/scalablesolutions/akka/actor/TransactionalTypedActor.java index 515f4fafee..222a8c82fa 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/TransactionalActiveObject.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/TransactionalTypedActor.java @@ -7,7 +7,7 @@ import se.scalablesolutions.akka.actor.annotation.inittransactionalstate; import se.scalablesolutions.akka.stm.*; @transactionrequired -public class TransactionalActiveObject { +public class TransactionalTypedActor { private TransactionalMap mapState; private TransactionalVector vectorState; private Ref refState; @@ -53,14 +53,14 @@ public class TransactionalActiveObject { refState.swap(msg); } - public void success(String key, String msg, NestedTransactionalActiveObject nested) { + public void success(String key, String msg, NestedTransactionalTypedActor nested) { mapState.put(key, msg); vectorState.add(msg); refState.swap(msg); nested.success(key, msg); } - public String failure(String key, String msg, ActiveObjectFailer failer) { + public String failure(String key, String msg, TypedActorFailer failer) { mapState.put(key, msg); vectorState.add(msg); refState.swap(msg); @@ -68,7 +68,7 @@ public class TransactionalActiveObject { return msg; } - public String failure(String key, String msg, NestedTransactionalActiveObject nested, ActiveObjectFailer failer) { + public String failure(String key, String msg, NestedTransactionalTypedActor nested, TypedActorFailer failer) { mapState.put(key, msg); vectorState.add(msg); refState.swap(msg); @@ -76,7 +76,7 @@ public class TransactionalActiveObject { return msg; } - public void thisMethodHangs(String key, String msg, ActiveObjectFailer failer) { + public void thisMethodHangs(String key, String msg, TypedActorFailer failer) { setMapState(key, msg); } diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/ActiveObjectFailer.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/TypedAcotrFailer.java similarity index 62% rename from akka-core/src/test/java/se/scalablesolutions/akka/actor/ActiveObjectFailer.java rename to akka-core/src/test/java/se/scalablesolutions/akka/actor/TypedAcotrFailer.java index 6e30a1a971..311e959527 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/ActiveObjectFailer.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/TypedAcotrFailer.java @@ -1,6 +1,6 @@ package se.scalablesolutions.akka.actor; -public class ActiveObjectFailer implements java.io.Serializable { +public class TypedActorFailer implements java.io.Serializable { public int fail() { throw new RuntimeException("expected"); } diff --git a/akka-core/src/test/resources/META-INF/aop.xml b/akka-core/src/test/resources/META-INF/aop.xml index 2f8d5159a8..bdc167ca54 100644 --- a/akka-core/src/test/resources/META-INF/aop.xml +++ b/akka-core/src/test/resources/META-INF/aop.xml @@ -1,7 +1,7 @@ - + diff --git a/akka-core/src/test/scala/NestedTransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/NestedTransactionalActiveObjectSpec.scala index afb9f9523e..c1dde6a582 100644 --- a/akka-core/src/test/scala/NestedTransactionalActiveObjectSpec.scala +++ b/akka-core/src/test/scala/NestedTransactionalActiveObjectSpec.scala @@ -1,4 +1,4 @@ -/** + /** * Copyright (C) 2009-2010 Scalable Solutions AB */ @@ -14,7 +14,7 @@ import org.junit.runner.RunWith import se.scalablesolutions.akka.actor._ @RunWith(classOf[JUnitRunner]) -class NestedTransactionalActiveObjectSpec extends +class NestedTransactionalTypedActorSpec extends Spec with ShouldMatchers with BeforeAndAfterAll { @@ -25,13 +25,13 @@ class NestedTransactionalActiveObjectSpec extends // ActorRegistry.shutdownAll } - describe("Declaratively nested supervised transactional in-memory Active Object") { + describe("Declaratively nested supervised transactional in-memory TypedActor") { it("map should not rollback state for stateful server in case of success") { - val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) stateful.init stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init") // set init state - val nested = ActiveObject.newInstance(classOf[NestedTransactionalActiveObject]) + val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor]) nested.init nested.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init") // set init state stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state", nested) // transactionrequired @@ -40,13 +40,13 @@ class NestedTransactionalActiveObjectSpec extends } it("map should rollback state for stateful server in case of failure") { - val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) stateful.init stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state - val nested = ActiveObject.newInstance(classOf[NestedTransactionalActiveObject]) + val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor]) nested.init nested.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state - val failer = ActiveObject.newInstance(classOf[ActiveObjectFailer]) + val failer = TypedActor.newInstance(classOf[TypedActorFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) fail("should have thrown an exception") @@ -56,10 +56,10 @@ class NestedTransactionalActiveObjectSpec extends } it("vector should not rollback state for stateful server in case of success") { - val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) stateful.init stateful.setVectorState("init") // set init state - val nested = ActiveObject.newInstance(classOf[NestedTransactionalActiveObject]) + val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor]) nested.init nested.setVectorState("init") // set init state stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state", nested) // transactionrequired @@ -68,13 +68,13 @@ class NestedTransactionalActiveObjectSpec extends } it("vector should rollback state for stateful server in case of failure") { - val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) stateful.init stateful.setVectorState("init") // set init state - val nested = ActiveObject.newInstance(classOf[NestedTransactionalActiveObject]) + val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor]) nested.init nested.setVectorState("init") // set init state - val failer = ActiveObject.newInstance(classOf[ActiveObjectFailer]) + val failer = TypedActor.newInstance(classOf[TypedActorFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) fail("should have thrown an exception") @@ -84,9 +84,9 @@ class NestedTransactionalActiveObjectSpec extends } it("ref should not rollback state for stateful server in case of success") { - val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) stateful.init - val nested = ActiveObject.newInstance(classOf[NestedTransactionalActiveObject]) + val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor]) nested.init stateful.setRefState("init") // set init state nested.setRefState("init") // set init state @@ -96,13 +96,13 @@ class NestedTransactionalActiveObjectSpec extends } it("ref should rollback state for stateful server in case of failure") { - val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) stateful.init - val nested = ActiveObject.newInstance(classOf[NestedTransactionalActiveObject]) + val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor]) nested.init stateful.setRefState("init") // set init state nested.setRefState("init") // set init state - val failer = ActiveObject.newInstance(classOf[ActiveObjectFailer]) + val failer = TypedActor.newInstance(classOf[TypedActorFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) fail("should have thrown an exception") diff --git a/akka-core/src/test/scala/RemoteTransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/RemoteTransactionalActiveObjectSpec.scala index 897318ce7d..71d44fd4bd 100644 --- a/akka-core/src/test/scala/RemoteTransactionalActiveObjectSpec.scala +++ b/akka-core/src/test/scala/RemoteTransactionalActiveObjectSpec.scala @@ -13,25 +13,25 @@ import org.junit.runner.RunWith import org.junit.{Test, Before, After} import se.scalablesolutions.akka.config.Config -import se.scalablesolutions.akka.config.ActiveObjectConfigurator +import se.scalablesolutions.akka.config.TypedActorConfigurator import se.scalablesolutions.akka.remote.{RemoteNode, RemoteServer, RemoteClient} -object RemoteTransactionalActiveObjectSpec { +object RemoteTransactionalTypedActorSpec { val HOSTNAME = "localhost" val PORT = 9988 var server: RemoteServer = null } @RunWith(classOf[JUnitRunner]) -class RemoteTransactionalActiveObjectSpec extends +class RemoteTransactionalTypedActorSpec extends Spec with ShouldMatchers with BeforeAndAfterAll { - import RemoteTransactionalActiveObjectSpec._ + import RemoteTransactionalTypedActorSpec._ Config.config - private val conf = new ActiveObjectConfigurator + private val conf = new TypedActorConfigurator private var messageLog = "" override def beforeAll = { @@ -51,19 +51,19 @@ class RemoteTransactionalActiveObjectSpec extends } } - describe("Remote transactional in-memory Active Object ") { + describe("Remote transactional in-memory TypedActor ") { /* it("map should not rollback state for stateful server in case of success") { - val stateful = ActiveObject.newRemoteInstance(classOf[TransactionalActiveObject], 1000, HOSTNAME, PORT) + val stateful = TypedActor.newRemoteInstance(classOf[TransactionalTypedActor], 1000, HOSTNAME, PORT) stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init") // set init state stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") // transactionrequired stateful.getMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess") should equal("new state") } it("map should rollback state for stateful server in case of failure") { - val stateful = ActiveObject.newRemoteInstance(classOf[TransactionalActiveObject], 1000, HOSTNAME, PORT) + val stateful = TypedActor.newRemoteInstance(classOf[TransactionalTypedActor], 1000, HOSTNAME, PORT) stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state - val failer =ActiveObject.newRemoteInstance(classOf[ActiveObjectFailer], 1000, HOSTNAME, PORT) //conf.getInstance(classOf[ActiveObjectFailer]) + val failer =TypedActor.newRemoteInstance(classOf[TypedActorFailer], 1000, HOSTNAME, PORT) //conf.getInstance(classOf[TypedActorFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) // call failing transactionrequired method fail("should have thrown an exception") @@ -72,16 +72,16 @@ class RemoteTransactionalActiveObjectSpec extends } it("vector should not rollback state for stateful server in case of success") { - val stateful = ActiveObject.newRemoteInstance(classOf[TransactionalActiveObject], 1000, HOSTNAME, PORT) + val stateful = TypedActor.newRemoteInstance(classOf[TransactionalTypedActor], 1000, HOSTNAME, PORT) stateful.setVectorState("init") // set init state stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") // transactionrequired stateful.getVectorState should equal("new state") } it("vector should rollback state for stateful server in case of failure") { - val stateful = ActiveObject.newRemoteInstance(classOf[TransactionalActiveObject], 1000, HOSTNAME, PORT) + val stateful = TypedActor.newRemoteInstance(classOf[TransactionalTypedActor], 1000, HOSTNAME, PORT) stateful.setVectorState("init") // set init state - val failer =ActiveObject.newRemoteInstance(classOf[ActiveObjectFailer], 1000, HOSTNAME, PORT) //conf.getInstance(classOf[ActiveObjectFailer]) + val failer =TypedActor.newRemoteInstance(classOf[TypedActorFailer], 1000, HOSTNAME, PORT) //conf.getInstance(classOf[TypedActorFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) // call failing transactionrequired method fail("should have thrown an exception") @@ -90,16 +90,16 @@ class RemoteTransactionalActiveObjectSpec extends } it("ref should not rollback state for stateful server in case of success") { - val stateful = ActiveObject.newRemoteInstance(classOf[TransactionalActiveObject], 1000, HOSTNAME, PORT) + val stateful = TypedActor.newRemoteInstance(classOf[TransactionalTypedActor], 1000, HOSTNAME, PORT) stateful.setRefState("init") // set init state stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") // transactionrequired stateful.getRefState should equal("new state") } it("ref should rollback state for stateful server in case of failure") { - val stateful = ActiveObject.newRemoteInstance(classOf[TransactionalActiveObject], 1000, HOSTNAME, PORT) + val stateful = TypedActor.newRemoteInstance(classOf[TransactionalTypedActor], 1000, HOSTNAME, PORT) stateful.setRefState("init") // set init state - val failer =ActiveObject.newRemoteInstance(classOf[ActiveObjectFailer], 1000, HOSTNAME, PORT) //conf.getInstance(classOf[ActiveObjectFailer]) + val failer =TypedActor.newRemoteInstance(classOf[TypedActorFailer], 1000, HOSTNAME, PORT) //conf.getInstance(classOf[TypedActorFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) // call failing transactionrequired method fail("should have thrown an exception") diff --git a/akka-core/src/test/scala/RestartNestedTransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/RestartNestedTransactionalActiveObjectSpec.scala index 67076aff7c..7e23b00957 100644 --- a/akka-core/src/test/scala/RestartNestedTransactionalActiveObjectSpec.scala +++ b/akka-core/src/test/scala/RestartNestedTransactionalActiveObjectSpec.scala @@ -13,17 +13,17 @@ import org.junit.runner.RunWith import se.scalablesolutions.akka.config.Config import se.scalablesolutions.akka.config._ -import se.scalablesolutions.akka.config.ActiveObjectConfigurator +import se.scalablesolutions.akka.config.TypedActorConfigurator import se.scalablesolutions.akka.config.JavaConfig._ import se.scalablesolutions.akka.actor._ @RunWith(classOf[JUnitRunner]) -class RestartNestedTransactionalActiveObjectSpec extends +class RestartNestedTransactionalTypedActorSpec extends Spec with ShouldMatchers with BeforeAndAfterAll { - private val conf = new ActiveObjectConfigurator + private val conf = new TypedActorConfigurator private var messageLog = "" override def beforeAll { @@ -31,13 +31,13 @@ class RestartNestedTransactionalActiveObjectSpec extends conf.configure( new RestartStrategy(new AllForOne, 3, 5000, List(classOf[Exception]).toArray), List( - new Component(classOf[TransactionalActiveObject], + new Component(classOf[TransactionalTypedActor], new LifeCycle(new Permanent), 10000), - new Component(classOf[NestedTransactionalActiveObject], + new Component(classOf[NestedTransactionalTypedActor], new LifeCycle(new Permanent), 10000), - new Component(classOf[ActiveObjectFailer], + new Component(classOf[TypedActorFailer], new LifeCycle(new Permanent), 10000) ).toArray).supervise @@ -51,15 +51,15 @@ class RestartNestedTransactionalActiveObjectSpec extends describe("Restart nested supervised transactional Active Object") { /* it("map should rollback state for stateful server in case of failure") { - val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + val stateful = conf.getInstance(classOf[TransactionalTypedActor]) stateful.init stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state - val nested = conf.getInstance(classOf[NestedTransactionalActiveObject]) + val nested = conf.getInstance(classOf[NestedTransactionalTypedActor]) nested.init nested.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state - val failer = conf.getInstance(classOf[ActiveObjectFailer]) + val failer = conf.getInstance(classOf[TypedActorFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) @@ -71,15 +71,15 @@ class RestartNestedTransactionalActiveObjectSpec extends } it("vector should rollback state for stateful server in case of failure") { - val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + val stateful = conf.getInstance(classOf[TransactionalTypedActor]) stateful.init stateful.setVectorState("init") // set init state - val nested = conf.getInstance(classOf[NestedTransactionalActiveObject]) + val nested = conf.getInstance(classOf[NestedTransactionalTypedActor]) nested.init nested.setVectorState("init") // set init state - val failer = conf.getInstance(classOf[ActiveObjectFailer]) + val failer = conf.getInstance(classOf[TypedActorFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) @@ -91,15 +91,15 @@ class RestartNestedTransactionalActiveObjectSpec extends } it("ref should rollback state for stateful server in case of failure") { - val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + val stateful = conf.getInstance(classOf[TransactionalTypedActor]) stateful.init - val nested = conf.getInstance(classOf[NestedTransactionalActiveObject]) + val nested = conf.getInstance(classOf[NestedTransactionalTypedActor]) nested.init stateful.setRefState("init") // set init state nested.setRefState("init") // set init state - val failer = conf.getInstance(classOf[ActiveObjectFailer]) + val failer = conf.getInstance(classOf[TypedActorFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) diff --git a/akka-core/src/test/scala/RestartTransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/RestartTransactionalActiveObjectSpec.scala index a1a2f8b507..a4f9c61f59 100644 --- a/akka-core/src/test/scala/RestartTransactionalActiveObjectSpec.scala +++ b/akka-core/src/test/scala/RestartTransactionalActiveObjectSpec.scala @@ -13,17 +13,17 @@ import org.junit.runner.RunWith import se.scalablesolutions.akka.config.Config import se.scalablesolutions.akka.config._ -import se.scalablesolutions.akka.config.ActiveObjectConfigurator +import se.scalablesolutions.akka.config.TypedActorConfigurator import se.scalablesolutions.akka.config.JavaConfig._ import se.scalablesolutions.akka.actor._ @RunWith(classOf[JUnitRunner]) -class RestartTransactionalActiveObjectSpec extends +class RestartTransactionalTypedActorSpec extends Spec with ShouldMatchers with BeforeAndAfterAll { - private val conf = new ActiveObjectConfigurator + private val conf = new TypedActorConfigurator private var messageLog = "" def before { @@ -32,11 +32,11 @@ class RestartTransactionalActiveObjectSpec extends new RestartStrategy(new AllForOne, 3, 5000, List(classOf[Exception]).toArray), List( new Component( - classOf[TransactionalActiveObject], + classOf[TransactionalTypedActor], new LifeCycle(new Temporary), 10000), new Component( - classOf[ActiveObjectFailer], + classOf[TypedActorFailer], new LifeCycle(new Temporary), 10000) ).toArray).supervise @@ -51,10 +51,10 @@ class RestartTransactionalActiveObjectSpec extends /* it("map should rollback state for stateful server in case of failure") { before - val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + val stateful = conf.getInstance(classOf[TransactionalTypedActor]) stateful.init stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") - val failer = conf.getInstance(classOf[ActiveObjectFailer]) + val failer = conf.getInstance(classOf[TypedActorFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) fail("should have thrown an exception") @@ -65,10 +65,10 @@ class RestartTransactionalActiveObjectSpec extends it("vector should rollback state for stateful server in case of failure") { before - val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + val stateful = conf.getInstance(classOf[TransactionalTypedActor]) stateful.init stateful.setVectorState("init") // set init state - val failer = conf.getInstance(classOf[ActiveObjectFailer]) + val failer = conf.getInstance(classOf[TypedActorFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) fail("should have thrown an exception") @@ -78,10 +78,10 @@ class RestartTransactionalActiveObjectSpec extends } it("ref should rollback state for stateful server in case of failure") { - val stateful = conf.getInstance(classOf[TransactionalActiveObject]) + val stateful = conf.getInstance(classOf[TransactionalTypedActor]) stateful.init stateful.setRefState("init") // set init state - val failer = conf.getInstance(classOf[ActiveObjectFailer]) + val failer = conf.getInstance(classOf[TypedActorFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) fail("should have thrown an exception") diff --git a/akka-core/src/test/scala/TransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/TransactionalActiveObjectSpec.scala index 1225df9a92..280c6df652 100644 --- a/akka-core/src/test/scala/TransactionalActiveObjectSpec.scala +++ b/akka-core/src/test/scala/TransactionalActiveObjectSpec.scala @@ -14,7 +14,7 @@ import org.junit.runner.RunWith import se.scalablesolutions.akka.actor._ @RunWith(classOf[JUnitRunner]) -class TransactionalActiveObjectSpec extends +class TransactionalTypedActorSpec extends Spec with ShouldMatchers with BeforeAndAfterAll { @@ -27,7 +27,7 @@ class TransactionalActiveObjectSpec extends describe("Declaratively supervised transactional in-memory Active Object ") { it("map should not rollback state for stateful server in case of success") { - val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) stateful.init stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init") stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") @@ -35,10 +35,10 @@ class TransactionalActiveObjectSpec extends } it("map should rollback state for stateful server in case of failure") { - val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) stateful.init stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") - val failer = ActiveObject.newInstance(classOf[ActiveObjectFailer]) + val failer = TypedActor.newInstance(classOf[TypedActorFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) fail("should have thrown an exception") @@ -47,7 +47,7 @@ class TransactionalActiveObjectSpec extends } it("vector should not rollback state for stateful server in case of success") { - val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) stateful.init stateful.setVectorState("init") // set init state stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") @@ -55,10 +55,10 @@ class TransactionalActiveObjectSpec extends } it("vector should rollback state for stateful server in case of failure") { - val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) stateful.init stateful.setVectorState("init") // set init state - val failer = ActiveObject.newInstance(classOf[ActiveObjectFailer]) + val failer = TypedActor.newInstance(classOf[TypedActorFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) fail("should have thrown an exception") @@ -67,7 +67,7 @@ class TransactionalActiveObjectSpec extends } it("ref should not rollback state for stateful server in case of success") { - val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) stateful.init stateful.setRefState("init") // set init state stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") @@ -75,10 +75,10 @@ class TransactionalActiveObjectSpec extends } it("ref should rollback state for stateful server in case of failure") { - val stateful = ActiveObject.newInstance(classOf[TransactionalActiveObject]) + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) stateful.init stateful.setRefState("init") // set init state - val failer = ActiveObject.newInstance(classOf[ActiveObjectFailer]) + val failer = TypedActor.newInstance(classOf[TypedActorFailer]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) fail("should have thrown an exception") diff --git a/akka-core/src/test/scala/ActiveObjectContextSpec.scala b/akka-core/src/test/scala/TypedActorContextSpec.scala similarity index 64% rename from akka-core/src/test/scala/ActiveObjectContextSpec.scala rename to akka-core/src/test/scala/TypedActorContextSpec.scala index 5a54f0a505..b83da59206 100644 --- a/akka-core/src/test/scala/ActiveObjectContextSpec.scala +++ b/akka-core/src/test/scala/TypedActorContextSpec.scala @@ -14,15 +14,15 @@ import org.junit.runner.RunWith import se.scalablesolutions.akka.dispatch.DefaultCompletableFuture; @RunWith(classOf[JUnitRunner]) -class ActiveObjectContextSpec extends +class TypedActorContextSpec extends Spec with ShouldMatchers with BeforeAndAfterAll { - describe("ActiveObjectContext") { - it("context.sender should return the sender Active Object reference") { - val pojo = ActiveObject.newInstance(classOf[SimpleJavaPojo]) - val pojoCaller = ActiveObject.newInstance(classOf[SimpleJavaPojoCaller]) + describe("TypedActorContext") { + it("context.sender should return the sender TypedActor reference") { + val pojo = TypedActor.newInstance(classOf[SimpleJavaPojo]) + val pojoCaller = TypedActor.newInstance(classOf[SimpleJavaPojoCaller]) pojoCaller.setPojo(pojo) try { pojoCaller.getSenderFromSimpleJavaPojo should equal (pojoCaller) @@ -31,9 +31,9 @@ class ActiveObjectContextSpec extends } } - it("context.senderFuture should return the senderFuture Active Object reference") { - val pojo = ActiveObject.newInstance(classOf[SimpleJavaPojo]) - val pojoCaller = ActiveObject.newInstance(classOf[SimpleJavaPojoCaller]) + it("context.senderFuture should return the senderFuture TypedActor reference") { + val pojo = TypedActor.newInstance(classOf[SimpleJavaPojo]) + val pojoCaller = TypedActor.newInstance(classOf[SimpleJavaPojoCaller]) pojoCaller.setPojo(pojo) try { pojoCaller.getSenderFutureFromSimpleJavaPojo.getClass.getName should equal (classOf[DefaultCompletableFuture[_]].getName) diff --git a/akka-core/src/test/scala/ActiveObjectGuiceConfiguratorSpec.scala b/akka-core/src/test/scala/TypedActorGuiceConfiguratorSpec.scala similarity index 90% rename from akka-core/src/test/scala/ActiveObjectGuiceConfiguratorSpec.scala rename to akka-core/src/test/scala/TypedActorGuiceConfiguratorSpec.scala index 3cb871d0d8..b43609a4f5 100644 --- a/akka-core/src/test/scala/ActiveObjectGuiceConfiguratorSpec.scala +++ b/akka-core/src/test/scala/TypedActorGuiceConfiguratorSpec.scala @@ -15,18 +15,18 @@ import org.scalatest.junit.JUnitRunner import org.junit.runner.RunWith import se.scalablesolutions.akka.config.Config -import se.scalablesolutions.akka.config.ActiveObjectConfigurator +import se.scalablesolutions.akka.config.TypedActorConfigurator import se.scalablesolutions.akka.config.JavaConfig._ import se.scalablesolutions.akka.dispatch._ import se.scalablesolutions.akka.dispatch.FutureTimeoutException @RunWith(classOf[JUnitRunner]) -class ActiveObjectGuiceConfiguratorSpec extends +class TypedActorGuiceConfiguratorSpec extends Spec with ShouldMatchers with BeforeAndAfterAll { - private val conf = new ActiveObjectConfigurator + private val conf = new TypedActorConfigurator private var messageLog = "" override def beforeAll { @@ -55,9 +55,9 @@ class ActiveObjectGuiceConfiguratorSpec extends override def afterAll = conf.stop - describe("ActiveObjectGuiceConfigurator") { + describe("TypedActorGuiceConfigurator") { /* - it("should inject active object using guice") { + it("should inject typed actor using guice") { messageLog = "" val foo = conf.getInstance(classOf[Foo]) val bar = conf.getInstance(classOf[Bar]) @@ -81,7 +81,7 @@ class ActiveObjectGuiceConfiguratorSpec extends } } - it("should be able to invoke active object") { + it("should be able to invoke typed actor") { messageLog = "" val foo = conf.getInstance(classOf[Foo]) messageLog += foo.foo("foo ") @@ -91,7 +91,7 @@ class ActiveObjectGuiceConfiguratorSpec extends messageLog should equal("foo return_foo before_bar ") } - it("should be able to invoke active object's invocation") { + it("should be able to invoke typed actor's invocation") { messageLog = "" val foo = conf.getInstance(classOf[Foo]) val bar = conf.getInstance(classOf[Bar]) diff --git a/akka-core/src/test/scala/ActiveObjectLifecycleSpec.scala b/akka-core/src/test/scala/TypedActorLifecycleSpec.scala similarity index 68% rename from akka-core/src/test/scala/ActiveObjectLifecycleSpec.scala rename to akka-core/src/test/scala/TypedActorLifecycleSpec.scala index 2b8e4d502f..b250e3da37 100644 --- a/akka-core/src/test/scala/ActiveObjectLifecycleSpec.scala +++ b/akka-core/src/test/scala/TypedActorLifecycleSpec.scala @@ -5,20 +5,20 @@ import org.scalatest.{BeforeAndAfterAll, Spec} import org.scalatest.junit.JUnitRunner import org.scalatest.matchers.ShouldMatchers -import se.scalablesolutions.akka.actor.ActiveObject._ +import se.scalablesolutions.akka.actor.TypedActor._ -import se.scalablesolutions.akka.config.{OneForOneStrategy, ActiveObjectConfigurator} +import se.scalablesolutions.akka.config.{OneForOneStrategy, TypedActorConfigurator} import se.scalablesolutions.akka.config.JavaConfig._ /** * @author Martin Krasser */ @RunWith(classOf[JUnitRunner]) -class ActiveObjectLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAfterAll { - var conf1: ActiveObjectConfigurator = _ - var conf2: ActiveObjectConfigurator = _ - var conf3: ActiveObjectConfigurator = _ - var conf4: ActiveObjectConfigurator = _ +class TypedActorLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAfterAll { + var conf1: TypedActorConfigurator = _ + var conf2: TypedActorConfigurator = _ + var conf3: TypedActorConfigurator = _ + var conf4: TypedActorConfigurator = _ override protected def beforeAll() = { val strategy = new RestartStrategy(new AllForOne(), 3, 1000, Array(classOf[Exception])) @@ -26,10 +26,10 @@ class ActiveObjectLifecycleSpec extends Spec with ShouldMatchers with BeforeAndA val comp2 = new Component(classOf[SamplePojoAnnotated], new LifeCycle(new Temporary()), 1000) val comp3 = new Component(classOf[SamplePojo], new LifeCycle(new Permanent(), new RestartCallbacks("pre", "post")), 1000) val comp4 = new Component(classOf[SamplePojo], new LifeCycle(new Temporary(), new ShutdownCallback("down")), 1000) - conf1 = new ActiveObjectConfigurator().configure(strategy, Array(comp1)).supervise - conf2 = new ActiveObjectConfigurator().configure(strategy, Array(comp2)).supervise - conf3 = new ActiveObjectConfigurator().configure(strategy, Array(comp3)).supervise - conf4 = new ActiveObjectConfigurator().configure(strategy, Array(comp4)).supervise + conf1 = new TypedActorConfigurator().configure(strategy, Array(comp1)).supervise + conf2 = new TypedActorConfigurator().configure(strategy, Array(comp2)).supervise + conf3 = new TypedActorConfigurator().configure(strategy, Array(comp3)).supervise + conf4 = new TypedActorConfigurator().configure(strategy, Array(comp4)).supervise } override protected def afterAll() = { @@ -39,8 +39,8 @@ class ActiveObjectLifecycleSpec extends Spec with ShouldMatchers with BeforeAndA conf4.stop } - describe("ActiveObject lifecycle management") { - it("should restart supervised, annotated active object on failure") { + describe("TypedActor lifecycle management") { + it("should restart supervised, annotated typed actor on failure") { val obj = conf1.getInstance[SamplePojoAnnotated](classOf[SamplePojoAnnotated]) val cdl = obj.newCountdownLatch(2) assert(AspectInitRegistry.initFor(obj) ne null) @@ -58,7 +58,7 @@ class ActiveObjectLifecycleSpec extends Spec with ShouldMatchers with BeforeAndA } } - it("should shutdown supervised, annotated active object on failure") { + it("should shutdown supervised, annotated typed actor on failure") { val obj = conf2.getInstance[SamplePojoAnnotated](classOf[SamplePojoAnnotated]) val cdl = obj.newCountdownLatch(1) assert(AspectInitRegistry.initFor(obj) ne null) @@ -76,7 +76,7 @@ class ActiveObjectLifecycleSpec extends Spec with ShouldMatchers with BeforeAndA } } - it("should restart supervised, non-annotated active object on failure") { + it("should restart supervised, non-annotated typed actor on failure") { val obj = conf3.getInstance[SamplePojo](classOf[SamplePojo]) val cdl = obj.newCountdownLatch(2) assert(AspectInitRegistry.initFor(obj) ne null) @@ -94,7 +94,7 @@ class ActiveObjectLifecycleSpec extends Spec with ShouldMatchers with BeforeAndA } } - it("should shutdown supervised, non-annotated active object on failure") { + it("should shutdown supervised, non-annotated typed actor on failure") { val obj = conf4.getInstance[SamplePojo](classOf[SamplePojo]) val cdl = obj.newCountdownLatch(1) assert(AspectInitRegistry.initFor(obj) ne null) @@ -112,25 +112,25 @@ class ActiveObjectLifecycleSpec extends Spec with ShouldMatchers with BeforeAndA } } - it("should shutdown non-supervised, annotated active object on ActiveObject.stop") { - val obj = ActiveObject.newInstance(classOf[SamplePojoAnnotated]) + it("should shutdown non-supervised, annotated typed actor on TypedActor.stop") { + val obj = TypedActor.newInstance(classOf[SamplePojoAnnotated]) assert(AspectInitRegistry.initFor(obj) ne null) assert("hello akka" === obj.greet("akka")) - ActiveObject.stop(obj) + TypedActor.stop(obj) assert(AspectInitRegistry.initFor(obj) eq null) assert(!obj._pre) assert(!obj._post) assert(obj._down) try { obj.greet("akka") - fail("access to stopped active object") + fail("access to stopped typed actor") } catch { case e: Exception => { /* test passed */ } } } - it("should shutdown non-supervised, annotated active object on ActorRegistry.shutdownAll") { - val obj = ActiveObject.newInstance(classOf[SamplePojoAnnotated]) + it("should shutdown non-supervised, annotated typed actor on ActorRegistry.shutdownAll") { + val obj = TypedActor.newInstance(classOf[SamplePojoAnnotated]) assert(AspectInitRegistry.initFor(obj) ne null) assert("hello akka" === obj.greet("akka")) ActorRegistry.shutdownAll @@ -140,23 +140,23 @@ class ActiveObjectLifecycleSpec extends Spec with ShouldMatchers with BeforeAndA assert(obj._down) try { obj.greet("akka") - fail("access to stopped active object") + fail("access to stopped typed actor") } catch { case e: Exception => { /* test passed */ } } } - it("should shutdown non-supervised, non-initialized active object on ActiveObject.stop") { - val obj = ActiveObject.newInstance(classOf[SamplePojoAnnotated]) - ActiveObject.stop(obj) + it("should shutdown non-supervised, non-initialized typed actor on TypedActor.stop") { + val obj = TypedActor.newInstance(classOf[SamplePojoAnnotated]) + TypedActor.stop(obj) assert(!obj._pre) assert(!obj._post) assert(obj._down) } it("both preRestart and postRestart methods should be invoked when an actor is restarted") { - val pojo = ActiveObject.newInstance(classOf[SimpleJavaPojo]) - val supervisor = ActiveObject.newInstance(classOf[SimpleJavaPojo]) + val pojo = TypedActor.newInstance(classOf[SimpleJavaPojo]) + val supervisor = TypedActor.newInstance(classOf[SimpleJavaPojo]) link(supervisor,pojo, new OneForOneStrategy(3, 2000),Array(classOf[Throwable])) pojo.throwException Thread.sleep(500) diff --git a/akka-core/src/test/scala/ActorObjectUtilFunctionsSpec.scala b/akka-core/src/test/scala/TypedActorUtilFunctionsSpec.scala similarity index 100% rename from akka-core/src/test/scala/ActorObjectUtilFunctionsSpec.scala rename to akka-core/src/test/scala/TypedActorUtilFunctionsSpec.scala diff --git a/akka-samples/akka-sample-camel/src/main/java/sample/camel/BeanImpl.java b/akka-samples/akka-sample-camel/src/main/java/sample/camel/BeanImpl.java index 10437e7624..5fa9e8c599 100644 --- a/akka-samples/akka-sample-camel/src/main/java/sample/camel/BeanImpl.java +++ b/akka-samples/akka-sample-camel/src/main/java/sample/camel/BeanImpl.java @@ -1,9 +1,10 @@ package sample.camel; +import se.scalablesolutions.akka.actor.TypedActor; /** * @author Martin Krasser */ -public class BeanImpl implements BeanIntf { +public class BeanImpl extends TypedActor implements BeanIntf { public String foo(String s) { return "hello " + s; diff --git a/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo1.java b/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo1.java index ed29ac30e6..d099816161 100644 --- a/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo1.java +++ b/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo1.java @@ -8,17 +8,10 @@ import se.scalablesolutions.akka.actor.annotation.consume; /** * @author Martin Krasser */ -public class ConsumerPojo1 { - +public interface ConsumerPojo1 { @consume("file:data/input/pojo") - public void foo(String body) { - System.out.println("Received message:"); - System.out.println(body); - } - + public void foo(String body); + @consume("jetty:http://0.0.0.0:8877/camel/pojo") - public String bar(@Body String body, @Header("name") String header) { - return String.format("body=%s header=%s", body, header); - } - + public String bar(@Body String body, @Header("name") String header); } diff --git a/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo1Impl.java b/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo1Impl.java new file mode 100644 index 0000000000..8f3ca9625d --- /dev/null +++ b/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo1Impl.java @@ -0,0 +1,24 @@ +package sample.camel; + +import org.apache.camel.Body; +import org.apache.camel.Header; + +import se.scalablesolutions.akka.actor.annotation.consume; +import se.scalablesolutions.akka.actor.TypedActor; + +/** + * @author Martin Krasser + */ +public class ConsumerPojo1Impl extends TypedActor implements ConsumerPojo1 { + + @consume("file:data/input/pojo") + public void foo(String body) { + System.out.println("Received message:"); + System.out.println(body); + } + + @consume("jetty:http://0.0.0.0:8877/camel/pojo") + public String bar(@Body String body, @Header("name") String header) { + return String.format("body=%s header=%s", body, header); + } +} diff --git a/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo2.java b/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo2.java index 429e6043ad..c0ef7a6798 100644 --- a/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo2.java +++ b/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo2.java @@ -7,11 +7,8 @@ import se.scalablesolutions.akka.actor.annotation.consume; /** * @author Martin Krasser */ -public class ConsumerPojo2 { +public interface ConsumerPojo2 { @consume("direct:default") - public String foo(String body) { - return String.format("default: %s", body); - } - + public String foo(String body); } \ No newline at end of file diff --git a/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo2Impl.java b/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo2Impl.java new file mode 100644 index 0000000000..eeca816d1b --- /dev/null +++ b/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo2Impl.java @@ -0,0 +1,18 @@ +package sample.camel; + +import org.apache.camel.Body; +import org.apache.camel.Header; + +import se.scalablesolutions.akka.actor.TypedActor; +import se.scalablesolutions.akka.actor.annotation.consume; + +/** + * @author Martin Krasser + */ +public class ConsumerPojo2Impl extends TypedActor implements ConsumerPojo2 { + + @consume("direct:default") + public String foo(String body) { + return String.format("default: %s", body); + } +} \ No newline at end of file diff --git a/akka-samples/akka-sample-camel/src/main/java/sample/camel/RemoteConsumerPojo1.java b/akka-samples/akka-sample-camel/src/main/java/sample/camel/RemoteConsumerPojo1.java index ab7e878b0d..929a82b65d 100644 --- a/akka-samples/akka-sample-camel/src/main/java/sample/camel/RemoteConsumerPojo1.java +++ b/akka-samples/akka-sample-camel/src/main/java/sample/camel/RemoteConsumerPojo1.java @@ -8,11 +8,8 @@ import se.scalablesolutions.akka.actor.annotation.consume; /** * @author Martin Krasser */ -public class RemoteConsumerPojo1 { +public interface RemoteConsumerPojo1 { @consume("jetty:http://localhost:6644/camel/remote-active-object-1") - public String foo(@Body String body, @Header("name") String header) { - return String.format("remote1: body=%s header=%s", body, header); - } - + public String foo(@Body String body, @Header("name") String header); } diff --git a/akka-samples/akka-sample-camel/src/main/java/sample/camel/RemoteConsumerPojo1Impl.java b/akka-samples/akka-sample-camel/src/main/java/sample/camel/RemoteConsumerPojo1Impl.java new file mode 100644 index 0000000000..858afcdbeb --- /dev/null +++ b/akka-samples/akka-sample-camel/src/main/java/sample/camel/RemoteConsumerPojo1Impl.java @@ -0,0 +1,18 @@ +package sample.camel; + +import org.apache.camel.Body; +import org.apache.camel.Header; + +import se.scalablesolutions.akka.actor.annotation.consume; +import se.scalablesolutions.akka.actor.TypedActor; + +/** + * @author Martin Krasser + */ +public class RemoteConsumerPojo1Impl extends TypedActor implements RemoteConsumerPojo1 { + + @consume("jetty:http://localhost:6644/camel/remote-active-object-1") + public String foo(@Body String body, @Header("name") String header) { + return String.format("remote1: body=%s header=%s", body, header); + } +} diff --git a/akka-samples/akka-sample-camel/src/main/scala/Boot.scala b/akka-samples/akka-sample-camel/src/main/scala/Boot.scala index bcb884d186..3b733fa988 100644 --- a/akka-samples/akka-sample-camel/src/main/scala/Boot.scala +++ b/akka-samples/akka-sample-camel/src/main/scala/Boot.scala @@ -7,7 +7,7 @@ import org.apache.camel.spring.spi.ApplicationContextRegistry import org.springframework.context.support.ClassPathXmlApplicationContext import se.scalablesolutions.akka.actor.Actor._ -import se.scalablesolutions.akka.actor.{ActiveObject, Supervisor} +import se.scalablesolutions.akka.actor.{TypedActor, Supervisor} import se.scalablesolutions.akka.camel.CamelContextManager import se.scalablesolutions.akka.config.ScalaConfig._ @@ -89,7 +89,7 @@ class Boot { // Active object example // ----------------------------------------------------------------------- - ActiveObject.newInstance(classOf[ConsumerPojo1]) + TypedActor.newInstance(classOf[ConsumerPojo1], classOf[ConsumerPojo1Impl]) } /** diff --git a/akka-samples/akka-sample-camel/src/main/scala/ClientApplication.scala b/akka-samples/akka-sample-camel/src/main/scala/ClientApplication.scala index 467d715360..5be24f1c8f 100644 --- a/akka-samples/akka-sample-camel/src/main/scala/ClientApplication.scala +++ b/akka-samples/akka-sample-camel/src/main/scala/ClientApplication.scala @@ -1,7 +1,7 @@ package sample.camel import se.scalablesolutions.akka.actor.Actor._ -import se.scalablesolutions.akka.actor.{ActiveObject, Actor, ActorRef} +import se.scalablesolutions.akka.actor.{TypedActor, Actor, ActorRef} import se.scalablesolutions.akka.camel.Message import se.scalablesolutions.akka.remote.RemoteClient @@ -18,15 +18,15 @@ object ClientApplication { val actor1 = actorOf[RemoteActor1] val actor2 = RemoteClient.actorFor("remote2", "localhost", 7777) - val actobj1 = ActiveObject.newRemoteInstance(classOf[RemoteConsumerPojo1], "localhost", 7777) - //val actobj2 = TODO: create reference to server-managed active object (RemoteConsumerPojo2) + val actobj1 = TypedActor.newRemoteInstance(classOf[RemoteConsumerPojo1], classOf[RemoteConsumerPojo1Impl], "localhost", 7777) + //val actobj2 = TODO: create reference to server-managed typed actor (RemoteConsumerPojo2) actor1.start println(actor1 !! Message("actor1")) // activates and publishes actor remotely println(actor2 !! Message("actor2")) // actor already activated and published remotely - println(actobj1.foo("x", "y")) // activates and publishes active object methods remotely + println(actobj1.foo("x", "y")) // activates and publishes typed actor methods remotely // ... } diff --git a/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala b/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala index 941da479b3..6584651f68 100644 --- a/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala +++ b/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala @@ -5,7 +5,7 @@ import org.apache.camel.builder.RouteBuilder import org.apache.camel.spring.spi.ApplicationContextRegistry import org.springframework.context.support.ClassPathXmlApplicationContext -import se.scalablesolutions.akka.actor.{Actor, ActorRegistry, ActiveObject} +import se.scalablesolutions.akka.actor.{Actor, ActorRegistry, TypedActor} import se.scalablesolutions.akka.camel._ import se.scalablesolutions.akka.util.Logging @@ -16,10 +16,9 @@ object StandaloneApplication { def main(args: Array[String]) { import CamelContextManager.context - // 'externally' register active objects + // 'externally' register typed actors val registry = new SimpleRegistry - registry.put("pojo1", ActiveObject.newInstance(classOf[BeanIntf], new BeanImpl)) - registry.put("pojo2", ActiveObject.newInstance(classOf[BeanImpl])) + registry.put("pojo1", TypedActor.newInstance(classOf[BeanIntf], classOf[BeanImpl])) // customize CamelContext CamelContextManager.init(new DefaultCamelContext(registry)) @@ -28,12 +27,12 @@ object StandaloneApplication { // start CamelService val camelService = CamelService.newInstance.load - // access 'externally' registered active objects + // access 'externally' registered typed actors assert("hello msg1" == context.createProducerTemplate.requestBody("direct:test1", "msg1")) assert("hello msg2" == context.createProducerTemplate.requestBody("direct:test2", "msg2")) - // 'internally' register active object (requires CamelService) - ActiveObject.newInstance(classOf[ConsumerPojo2]) + // 'internally' register typed actor (requires CamelService) + TypedActor.newInstance(classOf[ConsumerPojo2], classOf[ConsumerPojo2Impl]) // internal registration is done in background. Wait a bit ... Thread.sleep(1000) @@ -52,7 +51,7 @@ object StandaloneApplication { class StandaloneApplicationRoute extends RouteBuilder { def configure = { - // routes to active objects (in SimpleRegistry) + // routes to typed actors (in SimpleRegistry) from("direct:test1").to("active-object:pojo1?method=foo") from("direct:test2").to("active-object:pojo2?method=foo") } @@ -65,7 +64,7 @@ object StandaloneSpringApplication { // load Spring application context val appctx = new ClassPathXmlApplicationContext("/context-standalone.xml") - // access 'externally' registered active objects with active-object component + // access 'externally' registered typed actors with active-object component assert("hello msg3" == template.requestBody("direct:test3", "msg3")) // destroy Spring application context @@ -78,7 +77,7 @@ object StandaloneSpringApplication { class StandaloneSpringApplicationRoute extends RouteBuilder { def configure = { - // routes to active object (in ApplicationContextRegistry) + // routes to typed actor (in ApplicationContextRegistry) from("direct:test3").to("active-object:pojo3?method=foo") } } diff --git a/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/Boot.java b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/Boot.java index 60eb4f11af..cd382ae6ec 100644 --- a/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/Boot.java +++ b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/Boot.java @@ -4,11 +4,11 @@ package sample.rest.java; -import se.scalablesolutions.akka.config.ActiveObjectConfigurator; +import se.scalablesolutions.akka.config.TypedActorConfigurator; import static se.scalablesolutions.akka.config.JavaConfig.*; public class Boot { - public final static ActiveObjectConfigurator configurator = new ActiveObjectConfigurator(); + public final static TypedActorConfigurator configurator = new TypedActorConfigurator(); static { configurator.configure( new RestartStrategy(new OneForOne(), 3, 5000, new Class[]{Exception.class}), diff --git a/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/PersistentSimpleService.java b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/PersistentSimpleService.java index 1108fcdb63..67368ceedd 100644 --- a/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/PersistentSimpleService.java +++ b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/PersistentSimpleService.java @@ -4,42 +4,6 @@ package sample.rest.java; -import se.scalablesolutions.akka.actor.annotation.transactionrequired; -import se.scalablesolutions.akka.actor.annotation.prerestart; -import se.scalablesolutions.akka.actor.annotation.postrestart; -import se.scalablesolutions.akka.persistence.common.PersistentMap; -import se.scalablesolutions.akka.persistence.cassandra.CassandraStorage; - -import java.nio.ByteBuffer; - -@transactionrequired -public class PersistentSimpleService { - private String KEY = "COUNTER"; - - private boolean hasStartedTicking = false; - private PersistentMap storage; - - public String count() { - if (storage == null) storage = CassandraStorage.newMap(); - if (!hasStartedTicking) { - storage.put(KEY.getBytes(), ByteBuffer.allocate(4).putInt(0).array()); - hasStartedTicking = true; - return "Tick: 0\n"; - } else { - byte[] bytes = (byte[])storage.get(KEY.getBytes()).get(); - int counter = ByteBuffer.wrap(bytes).getInt(); - storage.put(KEY.getBytes(), ByteBuffer.allocate(4).putInt(counter + 1).array()); - return "Tick: " + counter + "\n"; - } - } - - @prerestart - public void preRestart() { - System.out.println("Prepare for restart by supervisor"); - } - - @postrestart - public void postRestart() { - System.out.println("Reinitialize after restart by supervisor"); - } +public interface PersistentSimpleService { + public String count(); } \ No newline at end of file diff --git a/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/PersistentSimpleServiceImpl.java b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/PersistentSimpleServiceImpl.java new file mode 100644 index 0000000000..2b83f4acbb --- /dev/null +++ b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/PersistentSimpleServiceImpl.java @@ -0,0 +1,42 @@ +/** + * Copyright (C) 2009-2010 Scalable Solutions AB + */ + +package sample.rest.java; + +import se.scalablesolutions.akka.actor.TypedTransactor; +import se.scalablesolutions.akka.persistence.common.PersistentMap; +import se.scalablesolutions.akka.persistence.cassandra.CassandraStorage; + +import java.nio.ByteBuffer; + +public class PersistentSimpleServiceImpl extends TypedTransactor implements PersistentSimpleService { + private String KEY = "COUNTER"; + + private boolean hasStartedTicking = false; + private PersistentMap storage; + + public String count() { + if (storage == null) storage = CassandraStorage.newMap(); + if (!hasStartedTicking) { + storage.put(KEY.getBytes(), ByteBuffer.allocate(4).putInt(0).array()); + hasStartedTicking = true; + return "Tick: 0\n"; + } else { + byte[] bytes = (byte[])storage.get(KEY.getBytes()).get(); + int counter = ByteBuffer.wrap(bytes).getInt(); + storage.put(KEY.getBytes(), ByteBuffer.allocate(4).putInt(counter + 1).array()); + return "Tick: " + counter + "\n"; + } + } + + @Override + public void preRestart(Throwable cause) { + System.out.println("Prepare for restart by supervisor"); + } + + @Override + public void postRestart(Throwable cause) { + System.out.println("Reinitialize after restart by supervisor"); + } +} \ No newline at end of file diff --git a/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/Receiver.java b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/Receiver.java index 06631659a2..4c60e44ae6 100644 --- a/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/Receiver.java +++ b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/Receiver.java @@ -4,17 +4,6 @@ package sample.rest.java; -import javax.ws.rs.Path; -import javax.ws.rs.GET; -import javax.ws.rs.Produces; - -import se.scalablesolutions.akka.actor.ActiveObject; -import se.scalablesolutions.akka.actor.ActiveObjectContext; - -public class Receiver { - private ActiveObjectContext context = null; - public SimpleService receive() { - System.out.println("------ RECEIVE"); - return (SimpleService) context.getSender(); - } +public interface Receiver { + SimpleService receive(); } diff --git a/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/ReceiverImpl.java b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/ReceiverImpl.java new file mode 100644 index 0000000000..c46042a848 --- /dev/null +++ b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/ReceiverImpl.java @@ -0,0 +1,14 @@ +/** + * Copyright (C) 2009-2010 Scalable Solutions AB + */ + +package sample.rest.java; + +import se.scalablesolutions.akka.actor.TypedActorContext; +import se.scalablesolutions.akka.actor.TypedActor; + +public class ReceiverImpl extends TypedActor implements Receiver { + public SimpleService receive() { + return (SimpleService) getContext().getSender(); + } +} diff --git a/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/SimpleService.java b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/SimpleService.java index 097ba810b5..8055b3383a 100644 --- a/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/SimpleService.java +++ b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/SimpleService.java @@ -4,43 +4,6 @@ package sample.rest.java; -import se.scalablesolutions.akka.actor.ActiveObject; -import se.scalablesolutions.akka.actor.ActiveObjectContext; -import se.scalablesolutions.akka.actor.annotation.transactionrequired; -import se.scalablesolutions.akka.actor.annotation.prerestart; -import se.scalablesolutions.akka.actor.annotation.postrestart; -import se.scalablesolutions.akka.stm.TransactionalMap; - -@transactionrequired -public class SimpleService { - private String KEY = "COUNTER"; - - private boolean hasStartedTicking = false; - private TransactionalMap storage; - private Receiver receiver = ActiveObject.newInstance(Receiver.class); - - public String count() { - if (storage == null) storage = new TransactionalMap(); - if (!hasStartedTicking) { - storage.put(KEY, 0); - hasStartedTicking = true; - return "Tick: 0\n"; - } else { - // Grabs the sender address and returns it - //SimpleService sender = receiver.receive(); - int counter = (Integer)storage.get(KEY).get() + 1; - storage.put(KEY, counter); - return "Tick: " + counter + "\n"; - } - } - - @prerestart - public void preRestart() { - System.out.println("Prepare for restart by supervisor"); - } - - @postrestart - public void postRestart() { - System.out.println("Reinitialize after restart by supervisor"); - } +public interface SimpleService { + public String count(); } \ No newline at end of file diff --git a/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/SimpleServiceImpl.java b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/SimpleServiceImpl.java new file mode 100644 index 0000000000..96400a0404 --- /dev/null +++ b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/SimpleServiceImpl.java @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2009-2010 Scalable Solutions AB + */ + +package sample.rest.java; + +import se.scalablesolutions.akka.actor.TypedActor; +import se.scalablesolutions.akka.actor.TypedTransactor; +import se.scalablesolutions.akka.actor.TypedActorContext; +import se.scalablesolutions.akka.stm.TransactionalMap; + +public class SimpleServiceImpl extends TypedTransactor implements SimpleService { + private String KEY = "COUNTER"; + + private boolean hasStartedTicking = false; + private TransactionalMap storage; + private Receiver receiver = TypedActor.newInstance(Receiver.class, ReceiverImpl.class); + + public String count() { + if (storage == null) storage = new TransactionalMap(); + if (!hasStartedTicking) { + storage.put(KEY, 0); + hasStartedTicking = true; + return "Tick: 0\n"; + } else { + // Grabs the sender address and returns it + //SimpleService sender = receiver.receive(); + int counter = (Integer)storage.get(KEY).get() + 1; + storage.put(KEY, counter); + return "Tick: " + counter + "\n"; + } + } + + @Override + public void preRestart(Throwable cause) { + System.out.println("Prepare for restart by supervisor"); + } + + @Override + public void postRestart(Throwable cause) { + System.out.println("Reinitialize after restart by supervisor"); + } +} \ No newline at end of file diff --git a/akka-spring/akka-spring-test-java/src/main/resources/se/scalablesolutions/akka/spring/foo/test-config.xml b/akka-spring/akka-spring-test-java/src/main/resources/se/scalablesolutions/akka/spring/foo/test-config.xml index 665d03a05e..13c45e6d3b 100644 --- a/akka-spring/akka-spring-test-java/src/main/resources/se/scalablesolutions/akka/spring/foo/test-config.xml +++ b/akka-spring/akka-spring-test-java/src/main/resources/se/scalablesolutions/akka/spring/foo/test-config.xml @@ -10,7 +10,7 @@ http://www.akkasource.org/schema/akka http://scalablesolutions.se/akka/akka-0.10.xsd"> diff --git a/akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/ActiveObjectConfigurationTest.java b/akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/ActiveObjectConfigurationTest.java index 7cc691f3e3..4117347380 100644 --- a/akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/ActiveObjectConfigurationTest.java +++ b/akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/ActiveObjectConfigurationTest.java @@ -21,10 +21,10 @@ import se.scalablesolutions.akka.remote.RemoteNode; import se.scalablesolutions.akka.spring.foo.MyPojo; /** - * Tests for spring configuration of active objects and supervisor configuration. + * Tests for spring configuration of typed actors and supervisor configuration. * @author michaelkober */ -public class ActiveObjectConfigurationTest { +public class TypedActorConfigurationTest { private ApplicationContext context = null; @@ -50,7 +50,7 @@ public class ActiveObjectConfigurationTest { } @Test - public void testSimpleActiveObject() { + public void testSimpleTypedActor() { MyPojo myPojo = (MyPojo) context.getBean("simple-active-object"); String msg = myPojo.getFoo(); msg += myPojo.getBar(); @@ -58,20 +58,20 @@ public class ActiveObjectConfigurationTest { } @Test(expected = FutureTimeoutException.class) - public void testSimpleActiveObject_Timeout() { + public void testSimpleTypedActor_Timeout() { MyPojo myPojo = (MyPojo) context.getBean("simple-active-object"); myPojo.longRunning(); } @Test - public void testSimpleActiveObject_NoTimeout() { + public void testSimpleTypedActor_NoTimeout() { MyPojo myPojo = (MyPojo) context.getBean("simple-active-object-long-timeout"); String msg = myPojo.longRunning(); assertEquals("this took long", msg); } @Test - public void testTransactionalActiveObject() { + public void testTransactionalTypedActor() { MyPojo myPojo = (MyPojo) context.getBean("transactional-active-object"); String msg = myPojo.getFoo(); msg += myPojo.getBar(); @@ -79,7 +79,7 @@ public class ActiveObjectConfigurationTest { } @Test - public void testRemoteActiveObject() { + public void testRemoteTypedActor() { new Thread(new Runnable() { public void run() { RemoteNode.start(); diff --git a/akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/SupervisorConfigurationTest.java b/akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/SupervisorConfigurationTest.java index 659433cb9f..c90fd56b72 100644 --- a/akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/SupervisorConfigurationTest.java +++ b/akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/SupervisorConfigurationTest.java @@ -13,8 +13,8 @@ import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; -import se.scalablesolutions.akka.actor.ActiveObject; -import se.scalablesolutions.akka.config.ActiveObjectConfigurator; +import se.scalablesolutions.akka.actor.TypedActor; +import se.scalablesolutions.akka.config.TypedActorConfigurator; import se.scalablesolutions.akka.config.JavaConfig.AllForOne; import se.scalablesolutions.akka.config.JavaConfig.Component; import se.scalablesolutions.akka.config.JavaConfig.LifeCycle; @@ -45,10 +45,10 @@ public class SupervisorConfigurationTest { @Test public void testSupervision() { - // get ActiveObjectConfigurator bean from spring context - ActiveObjectConfigurator myConfigurator = (ActiveObjectConfigurator) context + // get TypedActorConfigurator bean from spring context + TypedActorConfigurator myConfigurator = (TypedActorConfigurator) context .getBean("supervision1"); - // get ActiveObjects + // get TypedActors Foo foo = myConfigurator.getInstance(Foo.class); assertNotNull(foo); IBar bar = myConfigurator.getInstance(IBar.class); @@ -59,7 +59,7 @@ public class SupervisorConfigurationTest { @Test public void testTransactionalState() { - ActiveObjectConfigurator conf = (ActiveObjectConfigurator) context + TypedActorConfigurator conf = (TypedActorConfigurator) context .getBean("supervision2"); StatefulPojo stateful = conf.getInstance(StatefulPojo.class); stateful.setMapState("testTransactionalState", "some map state"); @@ -73,23 +73,23 @@ public class SupervisorConfigurationTest { @Test public void testInitTransactionalState() { - StatefulPojo stateful = ActiveObject.newInstance(StatefulPojo.class, + StatefulPojo stateful = TypedActor.newInstance(StatefulPojo.class, 1000, true); assertTrue("should be inititalized", stateful.isInitialized()); } @Test public void testSupervisionWithDispatcher() { - ActiveObjectConfigurator myConfigurator = (ActiveObjectConfigurator) context + TypedActorConfigurator myConfigurator = (TypedActorConfigurator) context .getBean("supervision-with-dispatcher"); - // get ActiveObjects + // get TypedActors Foo foo = myConfigurator.getInstance(Foo.class); assertNotNull(foo); // TODO how to check dispatcher? } @Test - public void testRemoteActiveObject() { + public void testRemoteTypedActor() { new Thread(new Runnable() { public void run() { RemoteNode.start(); @@ -99,13 +99,13 @@ public class SupervisorConfigurationTest { Thread.currentThread().sleep(1000); } catch (Exception e) { } - Foo instance = ActiveObject.newRemoteInstance(Foo.class, 2000, "localhost", 9999); + Foo instance = TypedActor.newRemoteInstance(Foo.class, 2000, "localhost", 9999); System.out.println(instance.foo()); } @Test - public void testSupervisedRemoteActiveObject() { + public void testSupervisedRemoteTypedActor() { new Thread(new Runnable() { public void run() { RemoteNode.start(); @@ -116,7 +116,7 @@ public class SupervisorConfigurationTest { } catch (Exception e) { } - ActiveObjectConfigurator conf = new ActiveObjectConfigurator(); + TypedActorConfigurator conf = new TypedActorConfigurator(); conf.configure( new RestartStrategy(new AllForOne(), 3, 10000, new Class[] { Exception.class }), new Component[] { diff --git a/akka-spring/src/main/resources/se/scalablesolutions/akka/spring/akka-0.10.xsd b/akka-spring/src/main/resources/se/scalablesolutions/akka/spring/akka-0.10.xsd index 6eb0ec48fa..5fd9b94c38 100644 --- a/akka-spring/src/main/resources/se/scalablesolutions/akka/spring/akka-0.10.xsd +++ b/akka-spring/src/main/resources/se/scalablesolutions/akka/spring/akka-0.10.xsd @@ -134,7 +134,7 @@ - + @@ -196,7 +196,7 @@ - + @@ -252,7 +252,7 @@ - + diff --git a/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala b/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala deleted file mode 100644 index 7e33d0176a..0000000000 --- a/akka-spring/src/main/scala/ActiveObjectFactoryBean.scala +++ /dev/null @@ -1,198 +0,0 @@ -/** - * Copyright (C) 2009-2010 Scalable Solutions AB - */ - -package se.scalablesolutions.akka.spring - -import java.beans.PropertyDescriptor -import java.lang.reflect.Method -import javax.annotation.PreDestroy -import javax.annotation.PostConstruct -import reflect.BeanProperty - -import org.springframework.beans.BeanWrapperImpl -import org.springframework.beans.BeanWrapper -import org.springframework.beans.BeanUtils -import org.springframework.beans.factory.BeanFactory -import org.springframework.beans.factory.config.AbstractFactoryBean -import org.springframework.context.{ApplicationContext,ApplicationContextAware} -import org.springframework.util.ReflectionUtils -import org.springframework.util.StringUtils - -import se.scalablesolutions.akka.actor.{ActiveObjectConfiguration, ActiveObject} -import se.scalablesolutions.akka.config.ScalaConfig.{ShutdownCallback, RestartCallbacks} -import se.scalablesolutions.akka.dispatch.MessageDispatcher -import se.scalablesolutions.akka.util.{Logging, Duration} - -/** - * Factory bean for active objects. - * - * @author michaelkober - * @author Johan Rask - * @author Martin Krasser - */ -class ActiveObjectFactoryBean extends AbstractFactoryBean[AnyRef] with Logging with ApplicationContextAware { - import StringReflect._ - import AkkaSpringConfigurationTags._ - - @BeanProperty var target: String = "" - @BeanProperty var timeout: Long = _ - @BeanProperty var interface: String = "" - @BeanProperty var transactional: Boolean = false - @BeanProperty var pre: String = "" - @BeanProperty var post: String = "" - @BeanProperty var shutdown: String = "" - @BeanProperty var host: String = "" - @BeanProperty var port: Int = _ - @BeanProperty var lifecycle: String = "" - @BeanProperty var dispatcher: DispatcherProperties = _ - @BeanProperty var scope:String = VAL_SCOPE_SINGLETON - @BeanProperty var property:PropertyEntries = _ - @BeanProperty var applicationContext:ApplicationContext = _ - - // Holds info about if deps has been set or not. Depends on - // if interface is specified or not. We must set deps on - // target instance if interface is specified - var hasSetDependecies = false - - - override def isSingleton:Boolean = { - if(scope.equals(VAL_SCOPE_SINGLETON)) { - true - } else { - false - } - } - - /* - * @see org.springframework.beans.factory.FactoryBean#getObjectType() - */ - def getObjectType: Class[AnyRef] = try { - target.toClass - } catch { - // required by contract to return null - case e: ClassNotFoundException => null - } - - /* - * @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance() - */ - def createInstance: AnyRef = { - var argumentList = "" - if (isRemote) argumentList += "r" - if (hasInterface) argumentList += "i" - if (hasDispatcher) argumentList += "d" - - postConstruct( - setProperties( - create(argumentList))) - - } - - /** - * Stop the active object if it is a singleton. - */ - override def destroyInstance(instance:AnyRef) { - ActiveObject.stop(instance) - } - - /** - * Invokes any method annotated with @PostConstruct - * When interfaces are specified, this method is invoked both on the - * target instance and on the active object, so a developer is free do decide - * where the annotation should be. If no interface is specified it is only invoked - * on the active object - */ - private def postConstruct(ref:AnyRef) : AnyRef = { - // Invoke postConstruct method if any - for(method <- ref.getClass.getMethods) { - if(method.isAnnotationPresent(classOf[PostConstruct])) { - method.invoke(ref) - } - } - ref - } - - - private def setProperties(ref:AnyRef) : AnyRef = { - if(hasSetDependecies) { - return ref - } - - log.debug("Processing properties and dependencies for target class %s",target) - val beanWrapper = new BeanWrapperImpl(ref); - if(ref.isInstanceOf[ApplicationContextAware]) { - log.debug("Setting application context") - beanWrapper.setPropertyValue("applicationContext",applicationContext) - } - for(entry <- property.entryList) { - val propertyDescriptor = BeanUtils.getPropertyDescriptor(ref.getClass,entry.name) - val method = propertyDescriptor.getWriteMethod(); - - if(StringUtils.hasText(entry.ref)) { - log.debug("Setting property %s with bean ref %s using method %s", - entry.name,entry.ref,method.getName) - method.invoke(ref,getBeanFactory().getBean(entry.ref)) - } else if(StringUtils.hasText(entry.value)) { - log.debug("Setting property %s with value %s using method %s", - entry.name,entry.value,method.getName) - beanWrapper.setPropertyValue(entry.name,entry.value) - } else { - throw new AkkaBeansException("Either property@ref or property@value must be set on property element") - } - } - ref - } - - private[akka] def create(argList : String) : AnyRef = { - if (argList == "r") { - ActiveObject.newInstance(target.toClass, createConfig.makeRemote(host, port)) - } else if (argList == "ri" ) { - ActiveObject.newInstance(interface.toClass, aNewInstance(target.toClass), createConfig.makeRemote(host, port)) - } else if (argList == "rd") { - ActiveObject.newInstance(target.toClass, createConfig.makeRemote(host, port).dispatcher(dispatcherInstance)) - } else if (argList == "rid") { - ActiveObject.newInstance(interface.toClass, aNewInstance(target.toClass), createConfig.makeRemote(host, port).dispatcher(dispatcherInstance)) - } else if (argList == "i") { - ActiveObject.newInstance(interface.toClass, aNewInstance(target.toClass), createConfig) - } else if (argList == "id") { - ActiveObject.newInstance(interface.toClass, aNewInstance(target.toClass), createConfig.dispatcher(dispatcherInstance)) - } else if (argList == "d") { - ActiveObject.newInstance(target.toClass, createConfig.dispatcher(dispatcherInstance)) - } else { - ActiveObject.newInstance(target.toClass, createConfig) - } - } - - - - private[akka] def createConfig: ActiveObjectConfiguration = { - val config = new ActiveObjectConfiguration().timeout(Duration(timeout, "millis")) - if (hasRestartCallbacks) config.restartCallbacks(pre, post) - if (hasShutdownCallback) config.shutdownCallback(shutdown) - if (transactional) config.makeTransactionRequired - config - } - def aNewInstance[T <: AnyRef](clazz: Class[T]) : T = { - var ref = clazz.newInstance().asInstanceOf[T] - postConstruct( - setProperties(ref)) - hasSetDependecies = true - ref - } - - private[akka] def isRemote = (host != null) && (!host.isEmpty) - - private[akka] def hasInterface = (interface != null) && (!interface.isEmpty) - - private[akka] def hasRestartCallbacks = ((pre != null) && !pre.isEmpty) || ((post != null) && !post.isEmpty) - - private[akka] def hasShutdownCallback = ((shutdown != null) && !shutdown.isEmpty) - - private[akka] def hasDispatcher = (dispatcher != null) && (dispatcher.dispatcherType != null) && (!dispatcher.dispatcherType.isEmpty) - - private[akka] def dispatcherInstance : MessageDispatcher = { - import DispatcherFactoryBean._ - createNewInstance(dispatcher) - } -} diff --git a/akka-spring/src/main/scala/AkkaNamespaceHandler.scala b/akka-spring/src/main/scala/AkkaNamespaceHandler.scala index 466dbeca30..34dede40aa 100644 --- a/akka-spring/src/main/scala/AkkaNamespaceHandler.scala +++ b/akka-spring/src/main/scala/AkkaNamespaceHandler.scala @@ -12,7 +12,7 @@ import AkkaSpringConfigurationTags._ */ class AkkaNamespaceHandler extends NamespaceHandlerSupport { def init = { - registerBeanDefinitionParser(ACTIVE_OBJECT_TAG, new ActiveObjectBeanDefinitionParser()); + registerBeanDefinitionParser(ACTIVE_OBJECT_TAG, new TypedActorBeanDefinitionParser()); registerBeanDefinitionParser(SUPERVISION_TAG, new SupervisionBeanDefinitionParser()); registerBeanDefinitionParser(DISPATCHER_TAG, new DispatcherBeanDefinitionParser()); registerBeanDefinitionParser(CAMEL_SERVICE_TAG, new CamelServiceBeanDefinitionParser); diff --git a/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala b/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala index 80a9f2e8d0..1e13865ad3 100644 --- a/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala +++ b/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala @@ -38,7 +38,7 @@ object AkkaSpringConfigurationTags { // --- ATTRIBUTES // - // active object attributes + // typed actor attributes val TIMEOUT = "timeout" val TARGET = "target" val INTERFACE = "interface" diff --git a/akka-spring/src/main/scala/DispatcherBeanDefinitionParser.scala b/akka-spring/src/main/scala/DispatcherBeanDefinitionParser.scala index 826125fcfc..9d4a16ff9b 100644 --- a/akka-spring/src/main/scala/DispatcherBeanDefinitionParser.scala +++ b/akka-spring/src/main/scala/DispatcherBeanDefinitionParser.scala @@ -12,7 +12,7 @@ import org.springframework.beans.factory.xml.{ParserContext, AbstractSingleBeanD * Parser for custom namespace configuration. * @author michaelkober */ -class DispatcherBeanDefinitionParser extends AbstractSingleBeanDefinitionParser with ActiveObjectParser with DispatcherParser { +class DispatcherBeanDefinitionParser extends AbstractSingleBeanDefinitionParser with TypedActorParser with DispatcherParser { /* * @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder) */ diff --git a/akka-spring/src/main/scala/SupervisionBeanDefinitionParser.scala b/akka-spring/src/main/scala/SupervisionBeanDefinitionParser.scala index dde14f3cb2..4a76f5b008 100644 --- a/akka-spring/src/main/scala/SupervisionBeanDefinitionParser.scala +++ b/akka-spring/src/main/scala/SupervisionBeanDefinitionParser.scala @@ -18,7 +18,7 @@ import org.springframework.util.xml.DomUtils * Parser for custom namespace for Akka declarative supervisor configuration. * @author michaelkober */ -class SupervisionBeanDefinitionParser extends AbstractSingleBeanDefinitionParser with ActiveObjectParser { +class SupervisionBeanDefinitionParser extends AbstractSingleBeanDefinitionParser with TypedActorParser { /* (non-Javadoc) * @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder) */ @@ -33,7 +33,7 @@ class SupervisionBeanDefinitionParser extends AbstractSingleBeanDefinitionParser val strategyElement = mandatoryElement(element, STRATEGY_TAG); val activeObjectsElement = mandatoryElement(element, ACTIVE_OBJECTS_TAG); parseRestartStrategy(strategyElement, builder) - parseActiveObjectList(activeObjectsElement, builder) + parseTypedActorList(activeObjectsElement, builder) } private[akka] def parseRestartStrategy(element: Element, builder: BeanDefinitionBuilder) { @@ -46,9 +46,9 @@ class SupervisionBeanDefinitionParser extends AbstractSingleBeanDefinitionParser builder.addPropertyValue("restartStrategy", restartStrategy) } - private[akka] def parseActiveObjectList(element: Element, builder: BeanDefinitionBuilder) { + private[akka] def parseTypedActorList(element: Element, builder: BeanDefinitionBuilder) { val activeObjects = DomUtils.getChildElementsByTagName(element, ACTIVE_OBJECT_TAG).toArray.toList.asInstanceOf[List[Element]] - val activeObjectProperties = activeObjects.map(parseActiveObject(_)) + val activeObjectProperties = activeObjects.map(parseTypedActor(_)) builder.addPropertyValue("supervised", activeObjectProperties) } diff --git a/akka-spring/src/main/scala/SupervisionFactoryBean.scala b/akka-spring/src/main/scala/SupervisionFactoryBean.scala index d8c44c3502..80a1f8a5fa 100644 --- a/akka-spring/src/main/scala/SupervisionFactoryBean.scala +++ b/akka-spring/src/main/scala/SupervisionFactoryBean.scala @@ -4,7 +4,7 @@ package se.scalablesolutions.akka.spring import org.springframework.beans.factory.config.AbstractFactoryBean -import se.scalablesolutions.akka.config.ActiveObjectConfigurator +import se.scalablesolutions.akka.config.TypedActorConfigurator import se.scalablesolutions.akka.config.JavaConfig._ import AkkaSpringConfigurationTags._ import reflect.BeanProperty @@ -14,20 +14,20 @@ import reflect.BeanProperty * Factory bean for supervisor configuration. * @author michaelkober */ -class SupervisionFactoryBean extends AbstractFactoryBean[ActiveObjectConfigurator] { +class SupervisionFactoryBean extends AbstractFactoryBean[TypedActorConfigurator] { @BeanProperty var restartStrategy: RestartStrategy = _ - @BeanProperty var supervised: List[ActiveObjectProperties] = _ + @BeanProperty var supervised: List[TypedActorProperties] = _ /* * @see org.springframework.beans.factory.FactoryBean#getObjectType() */ - def getObjectType: Class[ActiveObjectConfigurator] = classOf[ActiveObjectConfigurator] + def getObjectType: Class[TypedActorConfigurator] = classOf[TypedActorConfigurator] /* * @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance() */ - def createInstance: ActiveObjectConfigurator = { - val configurator = new ActiveObjectConfigurator() + def createInstance: TypedActorConfigurator = { + val configurator = new TypedActorConfigurator() configurator.configure( restartStrategy, @@ -36,9 +36,9 @@ class SupervisionFactoryBean extends AbstractFactoryBean[ActiveObjectConfigurato } /** - * Create configuration for ActiveObject + * Create configuration for TypedActor */ - private[akka] def createComponent(props: ActiveObjectProperties): Component = { + private[akka] def createComponent(props: TypedActorProperties): Component = { import StringReflect._ val lifeCycle = if (!props.lifecycle.isEmpty && props.lifecycle.equalsIgnoreCase(VAL_LIFECYCYLE_TEMPORARY)) new LifeCycle(new Temporary()) else new LifeCycle(new Permanent()) val isRemote = (props.host != null) && (!props.host.isEmpty) diff --git a/akka-spring/src/main/scala/ActiveObjectBeanDefinitionParser.scala b/akka-spring/src/main/scala/TypedActorBeanDefinitionParser.scala similarity index 84% rename from akka-spring/src/main/scala/ActiveObjectBeanDefinitionParser.scala rename to akka-spring/src/main/scala/TypedActorBeanDefinitionParser.scala index 0189147994..7869a6a33f 100644 --- a/akka-spring/src/main/scala/ActiveObjectBeanDefinitionParser.scala +++ b/akka-spring/src/main/scala/TypedActorBeanDefinitionParser.scala @@ -13,17 +13,17 @@ import org.w3c.dom.Element * Parser for custom namespace configuration. * @author michaelkober */ -class ActiveObjectBeanDefinitionParser extends AbstractSingleBeanDefinitionParser with ActiveObjectParser { +class TypedActorBeanDefinitionParser extends AbstractSingleBeanDefinitionParser with TypedActorParser { /* * @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder) */ override def doParse(element: Element, parserContext: ParserContext, builder: BeanDefinitionBuilder) { - val activeObjectConf = parseActiveObject(element) + val activeObjectConf = parseTypedActor(element) activeObjectConf.setAsProperties(builder) } /* * @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#getBeanClass(org.w3c.dom.Element) */ - override def getBeanClass(element: Element): Class[_] = classOf[ActiveObjectFactoryBean] + override def getBeanClass(element: Element): Class[_] = classOf[TypedActorFactoryBean] } diff --git a/akka-spring/src/main/scala/TypedActorFactoryBean.scala b/akka-spring/src/main/scala/TypedActorFactoryBean.scala new file mode 100644 index 0000000000..0e2848f8d6 --- /dev/null +++ b/akka-spring/src/main/scala/TypedActorFactoryBean.scala @@ -0,0 +1,167 @@ +/** + * Copyright (C) 2009-2010 Scalable Solutions AB + */ + +package se.scalablesolutions.akka.spring + +import java.beans.PropertyDescriptor +import java.lang.reflect.Method +import javax.annotation.PreDestroy +import javax.annotation.PostConstruct +import reflect.BeanProperty + +import org.springframework.beans.BeanWrapperImpl +import org.springframework.beans.BeanWrapper +import org.springframework.beans.BeanUtils +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.config.AbstractFactoryBean +import org.springframework.context.{ApplicationContext,ApplicationContextAware} +import org.springframework.util.ReflectionUtils +import org.springframework.util.StringUtils + +import se.scalablesolutions.akka.actor.{TypedActorConfiguration, TypedActor} +import se.scalablesolutions.akka.config.ScalaConfig.{ShutdownCallback, RestartCallbacks} +import se.scalablesolutions.akka.dispatch.MessageDispatcher +import se.scalablesolutions.akka.util.{Logging, Duration} + +/** + * Factory bean for typed actors. + * + * @author michaelkober + * @author Johan Rask + * @author Martin Krasser + * @author Jonas Bonér + */ +class TypedActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging with ApplicationContextAware { + import StringReflect._ + import AkkaSpringConfigurationTags._ + + @BeanProperty var target: String = "" + @BeanProperty var timeout: Long = _ + @BeanProperty var interface: String = "" + @BeanProperty var transactional: Boolean = false + @BeanProperty var pre: String = "" + @BeanProperty var post: String = "" + @BeanProperty var shutdown: String = "" + @BeanProperty var host: String = "" + @BeanProperty var port: Int = _ + @BeanProperty var lifecycle: String = "" + @BeanProperty var dispatcher: DispatcherProperties = _ + @BeanProperty var scope: String = VAL_SCOPE_SINGLETON + @BeanProperty var property: PropertyEntries = _ + @BeanProperty var applicationContext: ApplicationContext = _ + + // Holds info about if deps has been set or not. Depends on + // if interface is specified or not. We must set deps on + // target instance if interface is specified + var hasSetDependecies = false + + override def isSingleton = scope.equals(VAL_SCOPE_SINGLETON) + + /* + * @see org.springframework.beans.factory.FactoryBean#getObjectType() + */ + def getObjectType: Class[AnyRef] = try { + target.toClass + } catch { + // required by contract to return null + case e: ClassNotFoundException => null + } + + /* + * @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance() + */ + def createInstance: AnyRef = { + var argumentList = "" + if (isRemote) argumentList += "r" + if (hasInterface) argumentList += "i" + if (hasDispatcher) argumentList += "d" + postConstruct(setProperties(create(argumentList))) + } + + /** + * Stop the typed actor if it is a singleton. + */ + override def destroyInstance(instance: AnyRef) = TypedActor.stop(instance.asInstanceOf[TypedActor]) + + /** + * Invokes any method annotated with @PostConstruct + * When interfaces are specified, this method is invoked both on the + * target instance and on the typed actor, so a developer is free do decide + * where the annotation should be. If no interface is specified it is only invoked + * on the typed actor + */ + private def postConstruct(ref: AnyRef): AnyRef = { + // Invoke postConstruct method if any + for { + method <- ref.getClass.getMethods + if method.isAnnotationPresent(classOf[PostConstruct]) + } method.invoke(ref) + ref + } + + + private def setProperties(ref: AnyRef): AnyRef = { + if (hasSetDependecies) return ref + log.debug("Processing properties and dependencies for target class\n\t[%s]", target) + val beanWrapper = new BeanWrapperImpl(ref); + if (ref.isInstanceOf[ApplicationContextAware]) { + log.debug("Setting application context") + beanWrapper.setPropertyValue("applicationContext", applicationContext) + } + for (entry <- property.entryList) { + val propertyDescriptor = BeanUtils.getPropertyDescriptor(ref.getClass, entry.name) + val method = propertyDescriptor.getWriteMethod + if (StringUtils.hasText(entry.ref)) { + log.debug("Setting property %s with bean ref %s using method %s", entry.name, entry.ref, method.getName) + method.invoke(ref,getBeanFactory().getBean(entry.ref)) + } else if(StringUtils.hasText(entry.value)) { + log.debug("Setting property %s with value %s using method %s", entry.name, entry.value, method.getName) + beanWrapper.setPropertyValue(entry.name,entry.value) + } else throw new AkkaBeansException("Either property@ref or property@value must be set on property element") + } + ref + } + + private[akka] def create(argList: String) : AnyRef = argList match { + case "ri" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), createConfig.makeRemote(host, port)) + case "i" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), createConfig) + case "id" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), createConfig.dispatcher(dispatcherInstance)) + case "rid" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), + createConfig.makeRemote(host, port).dispatcher(dispatcherInstance)) + // case "rd" => TypedActor.newInstance(target.toClass, createConfig.makeRemote(host, port).dispatcher(dispatcherInstance)) + // case "r" => TypedActor.newInstance(target.toClass, createConfig.makeRemote(host, port)) + // case "d" => TypedActor.newInstance(target.toClass, createConfig.dispatcher(dispatcherInstance)) + case _ => throw new AkkaBeansException("Illegal configuration argument list for TypedActor Spring bean [" + argList + "]") + } + + private[akka] def createConfig: TypedActorConfiguration = { + val config = new TypedActorConfiguration().timeout(Duration(timeout, "millis")) + if (hasRestartCallbacks) config.restartCallbacks(pre, post) + if (hasShutdownCallback) config.shutdownCallback(shutdown) + if (transactional) config.makeTransactionRequired + config + } + + def newInstanceFor[T <: AnyRef](clazz: Class[T]) : T = { + var ref = clazz.newInstance().asInstanceOf[T] + postConstruct(setProperties(ref)) + hasSetDependecies = true + ref + } + + private[akka] def isRemote = (host != null) && (!host.isEmpty) + + private[akka] def hasInterface = (interface != null) && (!interface.isEmpty) + + private[akka] def hasRestartCallbacks = ((pre != null) && !pre.isEmpty) || ((post != null) && !post.isEmpty) + + private[akka] def hasShutdownCallback = ((shutdown != null) && !shutdown.isEmpty) + + private[akka] def hasDispatcher = (dispatcher != null) && (dispatcher.dispatcherType != null) && (!dispatcher.dispatcherType.isEmpty) + + private[akka] def dispatcherInstance: MessageDispatcher = { + import DispatcherFactoryBean._ + createNewInstance(dispatcher) + } +} diff --git a/akka-spring/src/main/scala/ActiveObjectParser.scala b/akka-spring/src/main/scala/TypedActorParser.scala similarity index 90% rename from akka-spring/src/main/scala/ActiveObjectParser.scala rename to akka-spring/src/main/scala/TypedActorParser.scala index 8838360a44..43e713f00e 100644 --- a/akka-spring/src/main/scala/ActiveObjectParser.scala +++ b/akka-spring/src/main/scala/TypedActorParser.scala @@ -15,16 +15,16 @@ import se.scalablesolutions.akka.actor.IllegalActorStateException * @author Johan Rask * @author Martin Krasser */ -trait ActiveObjectParser extends BeanParser with DispatcherParser { +trait TypedActorParser extends BeanParser with DispatcherParser { import AkkaSpringConfigurationTags._ /** - * Parses the given element and returns a ActiveObjectProperties. + * Parses the given element and returns a TypedActorProperties. * @param element dom element to parse - * @return configuration for the active object + * @return configuration for the typed actor */ - def parseActiveObject(element: Element): ActiveObjectProperties = { - val objectProperties = new ActiveObjectProperties() + def parseTypedActor(element: Element): TypedActorProperties = { + val objectProperties = new TypedActorProperties() val remoteElement = DomUtils.getChildElementByTagName(element, REMOTE_TAG); val restartCallbacksElement = DomUtils.getChildElementByTagName(element, RESTART_CALLBACKS_TAG); val shutdownCallbackElement = DomUtils.getChildElementByTagName(element, SHUTDOWN_CALLBACK_TAG); diff --git a/akka-spring/src/main/scala/ActiveObjectProperties.scala b/akka-spring/src/main/scala/TypedActorProperties.scala similarity index 94% rename from akka-spring/src/main/scala/ActiveObjectProperties.scala rename to akka-spring/src/main/scala/TypedActorProperties.scala index 0f4b09d559..53f2fca05a 100644 --- a/akka-spring/src/main/scala/ActiveObjectProperties.scala +++ b/akka-spring/src/main/scala/TypedActorProperties.scala @@ -8,11 +8,11 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder import AkkaSpringConfigurationTags._ /** - * Data container for active object configuration data. + * Data container for typed actor configuration data. * @author michaelkober * @author Martin Krasser */ -class ActiveObjectProperties { +class TypedActorProperties { var target: String = "" var timeout: Long = _ var interface: String = "" diff --git a/akka-spring/src/test/scala/ActiveObjectBeanDefinitionParserTest.scala b/akka-spring/src/test/scala/ActiveObjectBeanDefinitionParserTest.scala index dc48ecc4b1..1984e32c47 100644 --- a/akka-spring/src/test/scala/ActiveObjectBeanDefinitionParserTest.scala +++ b/akka-spring/src/test/scala/ActiveObjectBeanDefinitionParserTest.scala @@ -12,16 +12,16 @@ import ScalaDom._ import org.w3c.dom.Element /** - * Test for ActiveObjectParser + * Test for TypedActorParser * @author michaelkober */ @RunWith(classOf[JUnitRunner]) -class ActiveObjectBeanDefinitionParserTest extends Spec with ShouldMatchers { - private class Parser extends ActiveObjectParser +class TypedActorBeanDefinitionParserTest extends Spec with ShouldMatchers { + private class Parser extends TypedActorParser - describe("An ActiveObjectParser") { + describe("An TypedActorParser") { val parser = new Parser() - it("should parse the active object configuration") { + it("should parse the typed actor configuration") { val xml = - val props = parser.parseActiveObject(dom(xml).getDocumentElement); + val props = parser.parseTypedActor(dom(xml).getDocumentElement); assert(props != null) assert(props.timeout === 1000) assert(props.target === "foo.bar.MyPojo") @@ -44,25 +44,25 @@ class ActiveObjectBeanDefinitionParserTest extends Spec with ShouldMatchers { timeout="1000" transactional="true"/> - evaluating { parser.parseActiveObject(dom(xml).getDocumentElement) } should produce [IllegalArgumentException] + evaluating { parser.parseTypedActor(dom(xml).getDocumentElement) } should produce [IllegalArgumentException] } - it("should parse ActiveObjects configuration with dispatcher") { + it("should parse TypedActors configuration with dispatcher") { val xml = - val props = parser.parseActiveObject(dom(xml).getDocumentElement); + val props = parser.parseTypedActor(dom(xml).getDocumentElement); assert(props != null) assert(props.dispatcher.dispatcherType === "thread-based") } - it("should parse remote ActiveObjects configuration") { + it("should parse remote TypedActors configuration") { val xml = - val props = parser.parseActiveObject(dom(xml).getDocumentElement); + val props = parser.parseTypedActor(dom(xml).getDocumentElement); assert(props != null) assert(props.host === "com.some.host") assert(props.port === 9999) diff --git a/akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala b/akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala index 68dac8e97c..c65344cd9e 100644 --- a/akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala +++ b/akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala @@ -11,14 +11,14 @@ import org.springframework.core.io.ResourceEditor import org.springframework.context.support.ClassPathXmlApplicationContext; /** - * Test for ActiveObjectFactoryBean + * Test for TypedActorFactoryBean * @author michaelkober */ @RunWith(classOf[JUnitRunner]) -class ActiveObjectFactoryBeanTest extends Spec with ShouldMatchers { +class TypedActorFactoryBeanTest extends Spec with ShouldMatchers { - describe("A ActiveObjectFactoryBean") { - val bean = new ActiveObjectFactoryBean + describe("A TypedActorFactoryBean") { + val bean = new TypedActorFactoryBean it("should have java getters and setters for all properties") { bean.setTarget("java.lang.String") assert(bean.getTarget == "java.lang.String") @@ -26,7 +26,7 @@ class ActiveObjectFactoryBeanTest extends Spec with ShouldMatchers { assert(bean.getTimeout == 1000) } - it("should create a remote active object when a host is set") { + it("should create a remote typed actor when a host is set") { bean.setHost("some.host.com"); assert(bean.isRemote) } @@ -36,7 +36,7 @@ class ActiveObjectFactoryBeanTest extends Spec with ShouldMatchers { assert(bean.hasInterface) } - it("should create an active object with dispatcher if dispatcher is set") { + it("should create an typed actor with dispatcher if dispatcher is set") { val props = new DispatcherProperties() props.dispatcherType = "executor-based-event-driven" bean.setDispatcher(props); @@ -49,7 +49,7 @@ class ActiveObjectFactoryBeanTest extends Spec with ShouldMatchers { } it("should create a proxy of type ResourceEditor") { - val bean = new ActiveObjectFactoryBean() + val bean = new TypedActorFactoryBean() // we must have a java class here bean.setTarget("org.springframework.core.io.ResourceEditor") val entries = new PropertyEntries() @@ -78,7 +78,7 @@ class ActiveObjectFactoryBeanTest extends Spec with ShouldMatchers { assert(pojoInf.gotApplicationContext) } - it("should stop the created active object when scope is singleton and the context is closed") { + it("should stop the created typed actor when scope is singleton and the context is closed") { var ctx = new ClassPathXmlApplicationContext("appContext.xml"); val target = ctx.getBean("bean-singleton").asInstanceOf[SampleBean] assert(!target.down) @@ -86,7 +86,7 @@ class ActiveObjectFactoryBeanTest extends Spec with ShouldMatchers { assert(target.down) } - it("should not stop the created active object when scope is prototype and the context is closed") { + it("should not stop the created typed actor when scope is prototype and the context is closed") { var ctx = new ClassPathXmlApplicationContext("appContext.xml"); val target = ctx.getBean("bean-prototype").asInstanceOf[SampleBean] assert(!target.down) diff --git a/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala b/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala index d260afa44f..b78f5d552f 100644 --- a/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala +++ b/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala @@ -6,7 +6,7 @@ import org.scalatest.{BeforeAndAfterAll, BeforeAndAfterEach, FeatureSpec} import org.springframework.context.support.ClassPathXmlApplicationContext import se.scalablesolutions.akka.camel.CamelContextManager -import se.scalablesolutions.akka.actor.{ActiveObject, ActorRegistry} +import se.scalablesolutions.akka.actor.{TypedActor, ActorRegistry} class CamelServiceSpringFeatureTest extends FeatureSpec with BeforeAndAfterEach with BeforeAndAfterAll { override protected def beforeAll = { @@ -20,22 +20,22 @@ class CamelServiceSpringFeatureTest extends FeatureSpec with BeforeAndAfterEach feature("start CamelService from Spring application context") { import CamelContextManager._ - scenario("with a custom CamelContext and access a registered active object") { + scenario("with a custom CamelContext and access a registered typed actor") { val appctx = new ClassPathXmlApplicationContext("/appContextCamelServiceCustom.xml") assert(context.isInstanceOf[SpringCamelContext]) assert("hello sample" === template.requestBody("direct:test", "sample")) appctx.close } - scenario("with a default CamelContext and access a registered active object") { + scenario("with a default CamelContext and access a registered typed actor") { val appctx = new ClassPathXmlApplicationContext("/appContextCamelServiceDefault.xml") // create a custom registry val registry = new SimpleRegistry - registry.put("custom", ActiveObject.newInstance(classOf[SampleBean])) + registry.put("custom", TypedActor.newInstance(classOf[SampleBean])) // set custom registry in DefaultCamelContext assert(context.isInstanceOf[DefaultCamelContext]) context.asInstanceOf[DefaultCamelContext].setRegistry(registry) - // access registered active object + // access registered typed actor assert("hello sample" === template.requestBody("active-object:custom?method=foo", "sample")) appctx.close } diff --git a/akka-spring/src/test/scala/DispatcherBeanDefinitionParserTest.scala b/akka-spring/src/test/scala/DispatcherBeanDefinitionParserTest.scala index bd5490a1b0..64e9ea2425 100644 --- a/akka-spring/src/test/scala/DispatcherBeanDefinitionParserTest.scala +++ b/akka-spring/src/test/scala/DispatcherBeanDefinitionParserTest.scala @@ -89,7 +89,7 @@ class DispatcherBeanDefinitionParserTest extends Spec with ShouldMatchers { } - it("should throw IllegalArgumentException when configuring a thread based dispatcher without ActiveObject") { + it("should throw IllegalArgumentException when configuring a thread based dispatcher without TypedActor") { val xml = evaluating { parser.parseDispatcher(dom(xml).getDocumentElement) } should produce [IllegalArgumentException] } diff --git a/akka-spring/src/test/scala/SupervisionBeanDefinitionParserTest.scala b/akka-spring/src/test/scala/SupervisionBeanDefinitionParserTest.scala index ffc1f7a95d..317421c207 100644 --- a/akka-spring/src/test/scala/SupervisionBeanDefinitionParserTest.scala +++ b/akka-spring/src/test/scala/SupervisionBeanDefinitionParserTest.scala @@ -26,8 +26,8 @@ class SupervisionBeanDefinitionParserTest extends Spec with ShouldMatchers { val parser = new Parser() val builder = BeanDefinitionBuilder.genericBeanDefinition("foo.bar.Foo") - it("should be able to parse active object configuration") { - val props = parser.parseActiveObject(createActiveObjectElement); + it("should be able to parse typed actor configuration") { + val props = parser.parseTypedActor(createTypedActorElement); assert(props != null) assert(props.timeout == 1000) assert(props.target == "foo.bar.MyPojo") @@ -45,9 +45,9 @@ class SupervisionBeanDefinitionParserTest extends Spec with ShouldMatchers { expect(1000) { strategy.withinTimeRange } } - it("should parse the supervised active objects") { + it("should parse the supervised typed actors") { parser.parseSupervisor(createSupervisorElement, builder); - val supervised = builder.getBeanDefinition.getPropertyValues.getPropertyValue("supervised").getValue.asInstanceOf[List[ActiveObjectProperties]] + val supervised = builder.getBeanDefinition.getPropertyValues.getPropertyValue("supervised").getValue.asInstanceOf[List[TypedActorProperties]] assert(supervised != null) expect(4) { supervised.length } val iterator = supervised.iterator @@ -75,7 +75,7 @@ class SupervisionBeanDefinitionParserTest extends Spec with ShouldMatchers { } } - private def createActiveObjectElement : Element = { + private def createTypedActorElement : Element = { val xml = Date: Tue, 27 Jul 2010 10:38:17 +0200 Subject: [PATCH 062/188] Converted all TypedActor tests to interface-impl, code and tests compile --- .../akka/camel/PojoBase.java | 3 +- .../akka/camel/PojoBaseIntf.java | 21 ++++ .../akka/camel/PojoImpl.java | 3 +- .../camel/{Pojo.java => PojoNonConsumer.java} | 4 +- .../akka/camel/PojoNonConsumerIntf.java | 9 ++ .../akka/camel/PojoRemote.java | 3 +- .../akka/camel/PojoRemoteIntf.java | 12 +++ .../akka/camel/PojoSingle.java | 3 +- .../akka/camel/PojoSingleIntf.java | 12 +++ .../scalablesolutions/akka/camel/PojoSub.java | 3 +- .../akka/camel/PojoSubIntf.java | 18 ++++ .../test/scala/CamelServiceFeatureTest.scala | 4 +- .../scala/ConsumerMethodRegisteredTest.scala | 10 +- .../src/test/scala/PublishRequestorTest.scala | 8 +- .../src/test/scala/RemoteConsumerTest.scala | 2 +- ...a => TypedActorComponentFeatureTest.scala} | 6 +- .../src/main/scala/actor/TypedActor.scala | 11 +- .../actor/NestedTransactionalTypedActor.java | 92 ++-------------- .../NestedTransactionalTypedActorImpl.java | 59 +++++++++++ .../akka/actor/SamplePojo.java | 41 ++----- ...PojoAnnotated.java => SamplePojoImpl.java} | 43 +++++--- .../akka/actor/SimpleJavaPojo.java | 51 ++------- .../akka/actor/SimpleJavaPojoCaller.java | 19 +--- .../akka/actor/SimpleJavaPojoCallerImpl.java | 21 ++++ .../akka/actor/SimpleJavaPojoImpl.java | 52 +++++++++ .../akka/actor/TransactionalTypedActor.java | 100 ++---------------- .../actor/TransactionalTypedActorImpl.java | 84 +++++++++++++++ .../akka/actor/TypedAcotrFailer.java | 7 -- .../akka/actor/TypedActorFailer.java | 5 + .../akka/actor/TypedActorFailerImpl.java | 9 ++ .../NestedTransactionalActiveObjectSpec.scala | 42 +++----- .../scala/TransactionalActiveObjectSpec.scala | 24 ++--- .../test/scala/TypedActorContextSpec.scala | 8 +- .../test/scala/TypedActorLifecycleSpec.scala | 72 +++++++------ .../akka/spring/SampleBean.java | 13 ++- .../akka/spring/SampleBeanIntf.java | 6 ++ .../scala/CamelServiceSpringFeatureTest.scala | 2 +- 37 files changed, 484 insertions(+), 398 deletions(-) create mode 100644 akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoBaseIntf.java rename akka-camel/src/test/java/se/scalablesolutions/akka/camel/{Pojo.java => PojoNonConsumer.java} (57%) create mode 100644 akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoNonConsumerIntf.java create mode 100644 akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemoteIntf.java create mode 100644 akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSingleIntf.java create mode 100644 akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSubIntf.java rename akka-camel/src/test/scala/component/{ActiveObjectComponentFeatureTest.scala => TypedActorComponentFeatureTest.scala} (95%) create mode 100644 akka-core/src/test/java/se/scalablesolutions/akka/actor/NestedTransactionalTypedActorImpl.java rename akka-core/src/test/java/se/scalablesolutions/akka/actor/{SamplePojoAnnotated.java => SamplePojoImpl.java} (52%) create mode 100644 akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojoCallerImpl.java create mode 100644 akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojoImpl.java create mode 100644 akka-core/src/test/java/se/scalablesolutions/akka/actor/TransactionalTypedActorImpl.java delete mode 100644 akka-core/src/test/java/se/scalablesolutions/akka/actor/TypedAcotrFailer.java create mode 100644 akka-core/src/test/java/se/scalablesolutions/akka/actor/TypedActorFailer.java create mode 100644 akka-core/src/test/java/se/scalablesolutions/akka/actor/TypedActorFailerImpl.java create mode 100644 akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleBeanIntf.java diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoBase.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoBase.java index 05bf1625bb..7a9b5c95cc 100644 --- a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoBase.java +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoBase.java @@ -4,11 +4,12 @@ import org.apache.camel.Body; import org.apache.camel.Header; import se.scalablesolutions.akka.actor.annotation.consume; +import se.scalablesolutions.akka.actor.*; /** * @author Martin Krasser */ -public class PojoBase { +public class PojoBase extends TypedActor implements PojoBaseIntf { public String m1(String b, String h) { return "m1base: " + b + " " + h; diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoBaseIntf.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoBaseIntf.java new file mode 100644 index 0000000000..2ca8ef4360 --- /dev/null +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoBaseIntf.java @@ -0,0 +1,21 @@ +package se.scalablesolutions.akka.camel; + +import org.apache.camel.Body; +import org.apache.camel.Header; + +import se.scalablesolutions.akka.actor.annotation.consume; + +/** + * @author Martin Krasser + */ +public interface PojoBaseIntf { + + public String m1(String b, String h); + @consume("direct:m2base") + public String m2(@Body String b, @Header("test") String h); + @consume("direct:m3base") + public String m3(@Body String b, @Header("test") String h); + @consume("direct:m4base") + public String m4(@Body String b, @Header("test") String h); + public void m5(@Body String b, @Header("test") String h); +} diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoImpl.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoImpl.java index b48202d4dc..f26719585e 100644 --- a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoImpl.java +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoImpl.java @@ -4,11 +4,12 @@ import org.apache.camel.Body; import org.apache.camel.Header; import se.scalablesolutions.akka.actor.annotation.consume; +import se.scalablesolutions.akka.actor.*; /** * @author Martin Krasser */ -public class PojoImpl implements PojoIntf { +public class PojoImpl extends TypedActor implements PojoIntf { public String m1(String b, String h) { return "m1impl: " + b + " " + h; diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/Pojo.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoNonConsumer.java similarity index 57% rename from akka-camel/src/test/java/se/scalablesolutions/akka/camel/Pojo.java rename to akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoNonConsumer.java index d1848c49ee..fc6ea834fd 100644 --- a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/Pojo.java +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoNonConsumer.java @@ -1,11 +1,11 @@ package se.scalablesolutions.akka.camel; -import se.scalablesolutions.akka.actor.annotation.consume; +import se.scalablesolutions.akka.actor.*; /** * @author Martin Krasser */ -public class Pojo { +public class PojoNonConsumer extends TypedActor implements PojoNonConsumerIntf { public String foo(String s) { return String.format("foo: %s", s); diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoNonConsumerIntf.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoNonConsumerIntf.java new file mode 100644 index 0000000000..aec8caaf19 --- /dev/null +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoNonConsumerIntf.java @@ -0,0 +1,9 @@ +package se.scalablesolutions.akka.camel; + +/** + * @author Martin Krasser + */ +public interface PojoNonConsumerIntf { + + public String foo(String s); +} \ No newline at end of file diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemote.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemote.java index e9d3377581..61ea4d7a17 100644 --- a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemote.java +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemote.java @@ -1,11 +1,12 @@ package se.scalablesolutions.akka.camel; import se.scalablesolutions.akka.actor.annotation.consume; +import se.scalablesolutions.akka.actor.*; /** * @author Martin Krasser */ -public class PojoRemote { +public class PojoRemote extends TypedActor implements PojoRemoteIntf { @consume("direct:remote-active-object") public String foo(String s) { diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemoteIntf.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemoteIntf.java new file mode 100644 index 0000000000..639a440598 --- /dev/null +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemoteIntf.java @@ -0,0 +1,12 @@ +package se.scalablesolutions.akka.camel; + +import se.scalablesolutions.akka.actor.annotation.consume; + +/** + * @author Martin Krasser + */ +public interface PojoRemoteIntf { + + @consume("direct:remote-active-object") + public String foo(String s); +} diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSingle.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSingle.java index 7d577535b2..d4cbe1aabe 100644 --- a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSingle.java +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSingle.java @@ -1,11 +1,12 @@ package se.scalablesolutions.akka.camel; import se.scalablesolutions.akka.actor.annotation.consume; +import se.scalablesolutions.akka.actor.*; /** * @author Martin Krasser */ -public class PojoSingle { +public class PojoSingle extends TypedActor implements PojoSingleIntf { @consume("direct:foo") public void foo(String b) { diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSingleIntf.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSingleIntf.java new file mode 100644 index 0000000000..22a25325a3 --- /dev/null +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSingleIntf.java @@ -0,0 +1,12 @@ +package se.scalablesolutions.akka.camel; + +import se.scalablesolutions.akka.actor.annotation.consume; + +/** + * @author Martin Krasser + */ +public interface PojoSingleIntf { + + @consume("direct:foo") + public void foo(String b); +} diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSub.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSub.java index be5b453698..24caf37348 100644 --- a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSub.java +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSub.java @@ -4,8 +4,9 @@ import org.apache.camel.Body; import org.apache.camel.Header; import se.scalablesolutions.akka.actor.annotation.consume; +import se.scalablesolutions.akka.actor.*; -public class PojoSub extends PojoBase { +public class PojoSub extends PojoBase implements PojoSubIntf { @Override @consume("direct:m1sub") diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSubIntf.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSubIntf.java new file mode 100644 index 0000000000..08a153b124 --- /dev/null +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSubIntf.java @@ -0,0 +1,18 @@ +package se.scalablesolutions.akka.camel; + +import org.apache.camel.Body; +import org.apache.camel.Header; + +import se.scalablesolutions.akka.actor.annotation.consume; + +public interface PojoSubIntf extends PojoBaseIntf { + @consume("direct:m1sub") + public String m1(@Body String b, @Header("test") String h); + + @Override + public String m2(String b, String h); + + @Override + @consume("direct:m3sub") + public String m3(@Body String b, @Header("test") String h); +} diff --git a/akka-camel/src/test/scala/CamelServiceFeatureTest.scala b/akka-camel/src/test/scala/CamelServiceFeatureTest.scala index c6c04531e3..cd52511517 100644 --- a/akka-camel/src/test/scala/CamelServiceFeatureTest.scala +++ b/akka-camel/src/test/scala/CamelServiceFeatureTest.scala @@ -122,7 +122,7 @@ class CamelServiceFeatureTest extends FeatureSpec with BeforeAndAfterAll with Gi given("an typed actor registered after CamelService startup") var latch = service.expectEndpointActivationCount(3) - val obj = TypedActor.newInstance(classOf[PojoBase]) + val obj = TypedActor.newInstance(classOf[PojoBaseIntf], classOf[PojoBase]) assert(latch.await(5000, TimeUnit.MILLISECONDS)) when("requests are sent to published methods") @@ -148,7 +148,7 @@ class CamelServiceFeatureTest extends FeatureSpec with BeforeAndAfterAll with Gi given("an typed actor registered after CamelService startup") var latch = service.expectEndpointActivationCount(3) - val obj = TypedActor.newInstance(classOf[PojoBase]) + val obj = TypedActor.newInstance(classOf[PojoBaseIntf], classOf[PojoBase]) assert(latch.await(5000, TimeUnit.MILLISECONDS)) when("the typed actor is stopped") diff --git a/akka-camel/src/test/scala/ConsumerMethodRegisteredTest.scala b/akka-camel/src/test/scala/ConsumerMethodRegisteredTest.scala index 41051b9335..964fe8e7bf 100644 --- a/akka-camel/src/test/scala/ConsumerMethodRegisteredTest.scala +++ b/akka-camel/src/test/scala/ConsumerMethodRegisteredTest.scala @@ -12,8 +12,8 @@ class ConsumerMethodRegisteredTest extends JUnitSuite { import ConsumerMethodRegisteredTest._ val remoteAddress = new InetSocketAddress("localhost", 8888); - val remoteAspectInit = AspectInit(classOf[String], null, Some(remoteAddress), 1000) - val localAspectInit = AspectInit(classOf[String], null, None, 1000) + val remoteAspectInit = AspectInit(classOf[String], null, null, Some(remoteAddress), 1000) + val localAspectInit = AspectInit(classOf[String], null, null, None, 1000) val ascendingMethodName = (r1: ConsumerMethodRegistered, r2: ConsumerMethodRegistered) => r1.method.getName < r2.method.getName @@ -44,9 +44,9 @@ class ConsumerMethodRegisteredTest extends JUnitSuite { } object ConsumerMethodRegisteredTest { - val activePojoBase = TypedActor.newInstance(classOf[PojoBase]) - val activePojoSub = TypedActor.newInstance(classOf[PojoSub]) - val activePojoIntf = TypedActor.newInstance(classOf[PojoIntf], new PojoImpl) + val activePojoBase = TypedActor.newInstance(classOf[PojoBaseIntf], classOf[PojoBase]) + val activePojoSub = TypedActor.newInstance(classOf[PojoSubIntf], classOf[PojoSub]) + val activePojoIntf = TypedActor.newInstance(classOf[PojoIntf], classOf[PojoImpl]) @AfterClass def afterClass = { diff --git a/akka-camel/src/test/scala/PublishRequestorTest.scala b/akka-camel/src/test/scala/PublishRequestorTest.scala index 7ce8ef9c81..984f856875 100644 --- a/akka-camel/src/test/scala/PublishRequestorTest.scala +++ b/akka-camel/src/test/scala/PublishRequestorTest.scala @@ -32,8 +32,8 @@ class PublishRequestorTest extends JUnitSuite { } @Test def shouldReceiveConsumerMethodRegisteredEvent = { - val obj = TypedActor.newInstance(classOf[PojoSingle]) - val init = AspectInit(classOf[PojoSingle], null, None, 1000) + val obj = TypedActor.newInstance(classOf[PojoSingleIntf], classOf[PojoSingle]) + val init = AspectInit(classOf[PojoSingleIntf], null, null, None, 1000) val latch = (publisher !! SetExpectedTestMessageCount(1)).as[CountDownLatch].get requestor ! AspectInitRegistered(obj, init) assert(latch.await(5000, TimeUnit.MILLISECONDS)) @@ -45,8 +45,8 @@ class PublishRequestorTest extends JUnitSuite { } @Test def shouldReceiveConsumerMethodUnregisteredEvent = { - val obj = TypedActor.newInstance(classOf[PojoSingle]) - val init = AspectInit(classOf[PojoSingle], null, None, 1000) + val obj = TypedActor.newInstance(classOf[PojoSingleIntf], classOf[PojoSingle]) + val init = AspectInit(classOf[PojoSingleIntf], null, null, None, 1000) val latch = (publisher !! SetExpectedTestMessageCount(1)).as[CountDownLatch].get requestor ! AspectInitUnregistered(obj, init) assert(latch.await(5000, TimeUnit.MILLISECONDS)) diff --git a/akka-camel/src/test/scala/RemoteConsumerTest.scala b/akka-camel/src/test/scala/RemoteConsumerTest.scala index 08f116bdda..3f0770127f 100644 --- a/akka-camel/src/test/scala/RemoteConsumerTest.scala +++ b/akka-camel/src/test/scala/RemoteConsumerTest.scala @@ -58,7 +58,7 @@ class RemoteConsumerTest extends FeatureSpec with BeforeAndAfterAll with GivenWh feature("Client-initiated remote consumer typed actor") { scenario("access published remote consumer method") { given("a client-initiated remote consumer typed actor") - val consumer = TypedActor.newRemoteInstance(classOf[PojoRemote], host, port) + val consumer = TypedActor.newRemoteInstance(classOf[PojoRemoteIntf], classOf[PojoRemote], host, port) when("remote consumer publication is triggered") var latch = service.expectEndpointActivationCount(1) diff --git a/akka-camel/src/test/scala/component/ActiveObjectComponentFeatureTest.scala b/akka-camel/src/test/scala/component/TypedActorComponentFeatureTest.scala similarity index 95% rename from akka-camel/src/test/scala/component/ActiveObjectComponentFeatureTest.scala rename to akka-camel/src/test/scala/component/TypedActorComponentFeatureTest.scala index 79a35297df..4a2c4e8e28 100644 --- a/akka-camel/src/test/scala/component/ActiveObjectComponentFeatureTest.scala +++ b/akka-camel/src/test/scala/component/TypedActorComponentFeatureTest.scala @@ -17,9 +17,9 @@ class TypedActorComponentFeatureTest extends FeatureSpec with BeforeAndAfterAll import CamelContextManager.template override protected def beforeAll = { - val activePojo = TypedActor.newInstance(classOf[Pojo]) // not a consumer - val activePojoBase = TypedActor.newInstance(classOf[PojoBase]) - val activePojoIntf = TypedActor.newInstance(classOf[PojoIntf], new PojoImpl) + val activePojo = TypedActor.newInstance(classOf[PojoNonConsumerIntf], classOf[PojoNonConsumer]) // not a consumer + val activePojoBase = TypedActor.newInstance(classOf[PojoBaseIntf], classOf[PojoBase]) + val activePojoIntf = TypedActor.newInstance(classOf[PojoIntf], classOf[PojoImpl]) val registry = new SimpleRegistry registry.put("pojo", activePojo) diff --git a/akka-core/src/main/scala/actor/TypedActor.scala b/akka-core/src/main/scala/actor/TypedActor.scala index bd5235242b..a40a3d6adf 100644 --- a/akka-core/src/main/scala/actor/TypedActor.scala +++ b/akka-core/src/main/scala/actor/TypedActor.scala @@ -385,8 +385,15 @@ object TypedActor extends Logging { private[akka] def newTypedActor(targetClass: Class[_]): TypedActor = { val instance = targetClass.newInstance - if (instance.isInstanceOf[TypedActor]) instance.asInstanceOf[TypedActor] - else throw new IllegalArgumentException("Actor [" + targetClass.getName + "] is not a sub class of 'TypedActor'") + val typedActor = + if (instance.isInstanceOf[TypedActor]) instance.asInstanceOf[TypedActor] + else throw new IllegalArgumentException("Actor [" + targetClass.getName + "] is not a sub class of 'TypedActor'") + typedActor.init + import se.scalablesolutions.akka.stm.local.atomic + atomic { + typedActor.initTransactionalState + } + typedActor } private[akka] def supervise(restartStrategy: RestartStrategy, components: List[Supervise]): Supervisor = diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/NestedTransactionalTypedActor.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/NestedTransactionalTypedActor.java index fa13417f8b..ee7998f69a 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/NestedTransactionalTypedActor.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/NestedTransactionalTypedActor.java @@ -1,86 +1,12 @@ package se.scalablesolutions.akka.actor; -import se.scalablesolutions.akka.actor.annotation.transactionrequired; -import se.scalablesolutions.akka.actor.annotation.inittransactionalstate; -import se.scalablesolutions.akka.stm.*; - -@transactionrequired -public class NestedTransactionalTypedActor { - private TransactionalMap mapState; - private TransactionalVector vectorState; - private Ref refState; - private boolean isInitialized = false; - - @inittransactionalstate - public void init() { - if (!isInitialized) { - mapState = new TransactionalMap(); - vectorState = new TransactionalVector(); - refState = new Ref(); - isInitialized = true; - } - } - - public String getMapState(String key) { - return (String) mapState.get(key).get(); - } - - - public String getVectorState() { - return (String) vectorState.last(); - } - - - public String getRefState() { - return (String) refState.get().get(); - } - - - public void setMapState(String key, String msg) { - mapState.put(key, msg); - } - - - public void setVectorState(String msg) { - vectorState.add(msg); - } - - - public void setRefState(String msg) { - refState.swap(msg); - } - - - public void success(String key, String msg) { - mapState.put(key, msg); - vectorState.add(msg); - refState.swap(msg); - } - - - public String failure(String key, String msg, TypedActorFailer failer) { - mapState.put(key, msg); - vectorState.add(msg); - refState.swap(msg); - failer.fail(); - return msg; - } - - - public void thisMethodHangs(String key, String msg, TypedActorFailer failer) { - setMapState(key, msg); - } - - /* - public void clashOk(String key, String msg, InMemClasher clasher) { - mapState.put(key, msg); - clasher.clash(); - } - - public void clashNotOk(String key, String msg, InMemClasher clasher) { - mapState.put(key, msg); - clasher.clash(); - this.success("clash", "clash"); - } - */ +public interface NestedTransactionalTypedActor { + public String getMapState(String key); + public String getVectorState(); + public String getRefState(); + public void setMapState(String key, String msg); + public void setVectorState(String msg); + public void setRefState(String msg); + public void success(String key, String msg); + public String failure(String key, String msg, TypedActorFailer failer); } \ No newline at end of file diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/NestedTransactionalTypedActorImpl.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/NestedTransactionalTypedActorImpl.java new file mode 100644 index 0000000000..699f33785d --- /dev/null +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/NestedTransactionalTypedActorImpl.java @@ -0,0 +1,59 @@ +package se.scalablesolutions.akka.actor; + +import se.scalablesolutions.akka.actor.*; +import se.scalablesolutions.akka.stm.*; + +public class NestedTransactionalTypedActorImpl extends TypedTransactor implements NestedTransactionalTypedActor { + private TransactionalMap mapState; + private TransactionalVector vectorState; + private Ref refState; + private boolean isInitialized = false; + + @Override + public void init() { + if (!isInitialized) { + mapState = new TransactionalMap(); + vectorState = new TransactionalVector(); + refState = new Ref(); + isInitialized = true; + } + } + + public String getMapState(String key) { + return (String) mapState.get(key).get(); + } + + public String getVectorState() { + return (String) vectorState.last(); + } + + public String getRefState() { + return (String) refState.get().get(); + } + + public void setMapState(String key, String msg) { + mapState.put(key, msg); + } + + public void setVectorState(String msg) { + vectorState.add(msg); + } + + public void setRefState(String msg) { + refState.swap(msg); + } + + public void success(String key, String msg) { + mapState.put(key, msg); + vectorState.add(msg); + refState.swap(msg); + } + + public String failure(String key, String msg, TypedActorFailer failer) { + mapState.put(key, msg); + vectorState.add(msg); + refState.swap(msg); + failer.fail(); + return msg; + } +} \ No newline at end of file diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojo.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojo.java index 50f3e43221..715953152e 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojo.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojo.java @@ -2,36 +2,11 @@ package se.scalablesolutions.akka.actor; import java.util.concurrent.CountDownLatch; -public class SamplePojo { - - private CountDownLatch latch; - - public boolean _pre = false; - public boolean _post = false; - public boolean _down = false; - - public CountDownLatch newCountdownLatch(int count) { - latch = new CountDownLatch(count); - return latch; - } - - public String fail() { - throw new RuntimeException("expected"); - } - - public void pre() { - _pre = true; - latch.countDown(); - } - - public void post() { - _post = true; - latch.countDown(); - } - - public void down() { - _down = true; - latch.countDown(); - } - -} +public interface SamplePojo { + public boolean pre(); + public boolean post(); + public boolean down(); + public CountDownLatch newCountdownLatch(int count); + public String greet(String s); + public String fail(); +} \ No newline at end of file diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojoAnnotated.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojoImpl.java similarity index 52% rename from akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojoAnnotated.java rename to akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojoImpl.java index 8bf4ba36d3..da241484e2 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojoAnnotated.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojoImpl.java @@ -1,12 +1,10 @@ package se.scalablesolutions.akka.actor; -import se.scalablesolutions.akka.actor.annotation.postrestart; -import se.scalablesolutions.akka.actor.annotation.prerestart; -import se.scalablesolutions.akka.actor.annotation.shutdown; +import se.scalablesolutions.akka.actor.*; import java.util.concurrent.CountDownLatch; -public class SamplePojoAnnotated { +public class SamplePojoImpl extends TypedActor implements SamplePojo { private CountDownLatch latch; @@ -14,7 +12,7 @@ public class SamplePojoAnnotated { public boolean _post = false; public boolean _down = false; - public SamplePojoAnnotated() { + public SamplePojoImpl() { latch = new CountDownLatch(1); } @@ -23,6 +21,18 @@ public class SamplePojoAnnotated { return latch; } + public boolean pre() { + return _pre; + } + + public boolean post() { + return _post; + } + + public boolean down() { + return _down; + } + public String greet(String s) { return "hello " + s; } @@ -31,22 +41,21 @@ public class SamplePojoAnnotated { throw new RuntimeException("expected"); } - @prerestart - public void pre() { - _pre = true; - latch.countDown(); + @Override + public void preRestart(Throwable e) { + _pre = true; + latch.countDown(); } - @postrestart - public void post() { - _post = true; - latch.countDown(); + @Override + public void postRestart(Throwable e) { + _post = true; + latch.countDown(); } - - @shutdown - public void down() { + + @Override + public void shutdown() { _down = true; latch.countDown(); } - } \ No newline at end of file diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojo.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojo.java index b068af4f12..340afe6f65 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojo.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojo.java @@ -1,48 +1,13 @@ package se.scalablesolutions.akka.actor; -import se.scalablesolutions.akka.actor.annotation.prerestart; -import se.scalablesolutions.akka.actor.annotation.postrestart; -import se.scalablesolutions.akka.actor.TypedActorContext; import se.scalablesolutions.akka.dispatch.CompletableFuture; -public class SimpleJavaPojo { - - TypedActorContext context; - - public boolean pre = false; - public boolean post = false; - - private String name; - - public Object getSender() { - return context.getSender(); - } - - public CompletableFuture getSenderFuture() { - return context.getSenderFuture(); - } - - public void setName(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - @prerestart - public void pre() { - System.out.println("** pre()"); - pre = true; - } - - @postrestart - public void post() { - System.out.println("** post()"); - post = true; - } - - public void throwException() { - throw new RuntimeException(); - } +public interface SimpleJavaPojo { + public Object getSender(); + public CompletableFuture getSenderFuture(); + public void setName(String name); + public String getName(); + public void throwException(); + public boolean pre(); + public boolean post(); } diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojoCaller.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojoCaller.java index 0fb6aff9c5..a1bdab5337 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojoCaller.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojoCaller.java @@ -2,19 +2,8 @@ package se.scalablesolutions.akka.actor; import se.scalablesolutions.akka.dispatch.CompletableFuture; -public class SimpleJavaPojoCaller { - - SimpleJavaPojo pojo; - - public void setPojo(SimpleJavaPojo pojo) { - this.pojo = pojo; - } - - public Object getSenderFromSimpleJavaPojo() { - return pojo.getSender(); - } - - public CompletableFuture getSenderFutureFromSimpleJavaPojo() { - return pojo.getSenderFuture(); - } +public interface SimpleJavaPojoCaller { + public void setPojo(SimpleJavaPojo pojo); + public Object getSenderFromSimpleJavaPojo(); + public CompletableFuture getSenderFutureFromSimpleJavaPojo(); } diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojoCallerImpl.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojoCallerImpl.java new file mode 100644 index 0000000000..15a6aec8e0 --- /dev/null +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojoCallerImpl.java @@ -0,0 +1,21 @@ +package se.scalablesolutions.akka.actor; + +import se.scalablesolutions.akka.actor.*; +import se.scalablesolutions.akka.dispatch.CompletableFuture; + +public class SimpleJavaPojoCallerImpl extends TypedActor implements SimpleJavaPojoCaller { + + SimpleJavaPojo pojo; + + public void setPojo(SimpleJavaPojo pojo) { + this.pojo = pojo; + } + + public Object getSenderFromSimpleJavaPojo() { + return pojo.getSender(); + } + + public CompletableFuture getSenderFutureFromSimpleJavaPojo() { + return pojo.getSenderFuture(); + } +} diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojoImpl.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojoImpl.java new file mode 100644 index 0000000000..0e2e72ff06 --- /dev/null +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojoImpl.java @@ -0,0 +1,52 @@ +package se.scalablesolutions.akka.actor; + +import se.scalablesolutions.akka.actor.*; +import se.scalablesolutions.akka.dispatch.CompletableFuture; + +public class SimpleJavaPojoImpl extends TypedActor implements SimpleJavaPojo { + + public boolean pre = false; + public boolean post = false; + + private String name; + + public boolean pre() { + return pre; + } + + public boolean post() { + return post; + } + + public Object getSender() { + return getContext().getSender(); + } + + public CompletableFuture getSenderFuture() { + return getContext().getSenderFuture(); + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public void preRestart(Throwable e) { + System.out.println("** pre()"); + pre = true; + } + + @Override + public void postRestart(Throwable e) { + System.out.println("** post()"); + post = true; + } + + public void throwException() { + throw new RuntimeException(); + } +} diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/TransactionalTypedActor.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/TransactionalTypedActor.java index 222a8c82fa..6e7c43745b 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/TransactionalTypedActor.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/TransactionalTypedActor.java @@ -1,92 +1,14 @@ package se.scalablesolutions.akka.actor; -import se.scalablesolutions.akka.actor.annotation.transactionrequired; -import se.scalablesolutions.akka.actor.annotation.prerestart; -import se.scalablesolutions.akka.actor.annotation.postrestart; -import se.scalablesolutions.akka.actor.annotation.inittransactionalstate; -import se.scalablesolutions.akka.stm.*; - -@transactionrequired -public class TransactionalTypedActor { - private TransactionalMap mapState; - private TransactionalVector vectorState; - private Ref refState; - private boolean isInitialized = false; - - @inittransactionalstate - public void init() { - if (!isInitialized) { - mapState = new TransactionalMap(); - vectorState = new TransactionalVector(); - refState = new Ref(); - isInitialized = true; - } - } - - public String getMapState(String key) { - return (String)mapState.get(key).get(); - } - - public String getVectorState() { - return (String)vectorState.last(); - } - - public String getRefState() { - return (String)refState.get().get(); - } - - public void setMapState(String key, String msg) { - mapState.put(key, msg); - } - - public void setVectorState(String msg) { - vectorState.add(msg); - } - - public void setRefState(String msg) { - refState.swap(msg); - } - - public void success(String key, String msg) { - mapState.put(key, msg); - vectorState.add(msg); - refState.swap(msg); - } - - public void success(String key, String msg, NestedTransactionalTypedActor nested) { - mapState.put(key, msg); - vectorState.add(msg); - refState.swap(msg); - nested.success(key, msg); - } - - public String failure(String key, String msg, TypedActorFailer failer) { - mapState.put(key, msg); - vectorState.add(msg); - refState.swap(msg); - failer.fail(); - return msg; - } - - public String failure(String key, String msg, NestedTransactionalTypedActor nested, TypedActorFailer failer) { - mapState.put(key, msg); - vectorState.add(msg); - refState.swap(msg); - nested.failure(key, msg, failer); - return msg; - } - - public void thisMethodHangs(String key, String msg, TypedActorFailer failer) { - setMapState(key, msg); - } - - @prerestart - public void preRestart() { - System.out.println("################ PRE RESTART"); - } - - @postrestart - public void postRestart() { - System.out.println("################ POST RESTART"); - } +public interface TransactionalTypedActor { + public String getMapState(String key); + public String getVectorState(); + public String getRefState(); + public void setMapState(String key, String msg); + public void setVectorState(String msg); + public void setRefState(String msg); + public void success(String key, String msg); + public void success(String key, String msg, NestedTransactionalTypedActor nested); + public String failure(String key, String msg, TypedActorFailer failer); + public String failure(String key, String msg, NestedTransactionalTypedActor nested, TypedActorFailer failer); } diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/TransactionalTypedActorImpl.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/TransactionalTypedActorImpl.java new file mode 100644 index 0000000000..ddaf2fb47d --- /dev/null +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/TransactionalTypedActorImpl.java @@ -0,0 +1,84 @@ +package se.scalablesolutions.akka.actor; + +import se.scalablesolutions.akka.actor.*; +import se.scalablesolutions.akka.stm.*; + +public class TransactionalTypedActorImpl extends TypedTransactor implements TransactionalTypedActor { + private TransactionalMap mapState; + private TransactionalVector vectorState; + private Ref refState; + private boolean isInitialized = false; + + @Override + public void initTransactionalState() { + if (!isInitialized) { + mapState = new TransactionalMap(); + vectorState = new TransactionalVector(); + refState = new Ref(); + isInitialized = true; + } + } + + public String getMapState(String key) { + return (String)mapState.get(key).get(); + } + + public String getVectorState() { + return (String)vectorState.last(); + } + + public String getRefState() { + return (String)refState.get().get(); + } + + public void setMapState(String key, String msg) { + mapState.put(key, msg); + } + + public void setVectorState(String msg) { + vectorState.add(msg); + } + + public void setRefState(String msg) { + refState.swap(msg); + } + + public void success(String key, String msg) { + mapState.put(key, msg); + vectorState.add(msg); + refState.swap(msg); + } + + public void success(String key, String msg, NestedTransactionalTypedActor nested) { + mapState.put(key, msg); + vectorState.add(msg); + refState.swap(msg); + nested.success(key, msg); + } + + public String failure(String key, String msg, TypedActorFailer failer) { + mapState.put(key, msg); + vectorState.add(msg); + refState.swap(msg); + failer.fail(); + return msg; + } + + public String failure(String key, String msg, NestedTransactionalTypedActor nested, TypedActorFailer failer) { + mapState.put(key, msg); + vectorState.add(msg); + refState.swap(msg); + nested.failure(key, msg, failer); + return msg; + } + + @Override + public void preRestart(Throwable e) { + System.out.println("################ PRE RESTART"); + } + + @Override + public void postRestart(Throwable e) { + System.out.println("################ POST RESTART"); + } +} diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/TypedAcotrFailer.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/TypedAcotrFailer.java deleted file mode 100644 index 311e959527..0000000000 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/TypedAcotrFailer.java +++ /dev/null @@ -1,7 +0,0 @@ -package se.scalablesolutions.akka.actor; - -public class TypedActorFailer implements java.io.Serializable { - public int fail() { - throw new RuntimeException("expected"); - } -} diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/TypedActorFailer.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/TypedActorFailer.java new file mode 100644 index 0000000000..b4a69e1cd1 --- /dev/null +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/TypedActorFailer.java @@ -0,0 +1,5 @@ +package se.scalablesolutions.akka.actor; + +public interface TypedActorFailer extends java.io.Serializable { + public int fail(); +} diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/TypedActorFailerImpl.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/TypedActorFailerImpl.java new file mode 100644 index 0000000000..0d01fd801c --- /dev/null +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/TypedActorFailerImpl.java @@ -0,0 +1,9 @@ +package se.scalablesolutions.akka.actor; + +import se.scalablesolutions.akka.actor.*; + +public class TypedActorFailerImpl extends TypedActor implements TypedActorFailer { + public int fail() { + throw new RuntimeException("expected"); + } +} diff --git a/akka-core/src/test/scala/NestedTransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/NestedTransactionalActiveObjectSpec.scala index c1dde6a582..e0c59800bc 100644 --- a/akka-core/src/test/scala/NestedTransactionalActiveObjectSpec.scala +++ b/akka-core/src/test/scala/NestedTransactionalActiveObjectSpec.scala @@ -28,11 +28,9 @@ class NestedTransactionalTypedActorSpec extends describe("Declaratively nested supervised transactional in-memory TypedActor") { it("map should not rollback state for stateful server in case of success") { - val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) - stateful.init + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor], classOf[TransactionalTypedActorImpl]) stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init") // set init state - val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor]) - nested.init + val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor], classOf[NestedTransactionalTypedActorImpl]) nested.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init") // set init state stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state", nested) // transactionrequired stateful.getMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess") should equal("new state") @@ -40,13 +38,11 @@ class NestedTransactionalTypedActorSpec extends } it("map should rollback state for stateful server in case of failure") { - val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) - stateful.init + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor], classOf[TransactionalTypedActorImpl]) stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state - val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor]) - nested.init + val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor], classOf[NestedTransactionalTypedActorImpl]) nested.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state - val failer = TypedActor.newInstance(classOf[TypedActorFailer]) + val failer = TypedActor.newInstance(classOf[TypedActorFailer], classOf[TypedActorFailerImpl]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) fail("should have thrown an exception") @@ -56,11 +52,9 @@ class NestedTransactionalTypedActorSpec extends } it("vector should not rollback state for stateful server in case of success") { - val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) - stateful.init + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor], classOf[TransactionalTypedActorImpl]) stateful.setVectorState("init") // set init state - val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor]) - nested.init + val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor], classOf[NestedTransactionalTypedActorImpl]) nested.setVectorState("init") // set init state stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state", nested) // transactionrequired stateful.getVectorState should equal("new state") @@ -68,13 +62,11 @@ class NestedTransactionalTypedActorSpec extends } it("vector should rollback state for stateful server in case of failure") { - val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) - stateful.init + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor], classOf[TransactionalTypedActorImpl]) stateful.setVectorState("init") // set init state - val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor]) - nested.init + val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor], classOf[NestedTransactionalTypedActorImpl]) nested.setVectorState("init") // set init state - val failer = TypedActor.newInstance(classOf[TypedActorFailer]) + val failer = TypedActor.newInstance(classOf[TypedActorFailer], classOf[TypedActorFailerImpl]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) fail("should have thrown an exception") @@ -84,10 +76,8 @@ class NestedTransactionalTypedActorSpec extends } it("ref should not rollback state for stateful server in case of success") { - val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) - stateful.init - val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor]) - nested.init + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor], classOf[TransactionalTypedActorImpl]) + val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor], classOf[NestedTransactionalTypedActorImpl]) stateful.setRefState("init") // set init state nested.setRefState("init") // set init state stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state", nested) @@ -96,13 +86,11 @@ class NestedTransactionalTypedActorSpec extends } it("ref should rollback state for stateful server in case of failure") { - val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) - stateful.init - val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor]) - nested.init + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor], classOf[TransactionalTypedActorImpl]) + val nested = TypedActor.newInstance(classOf[NestedTransactionalTypedActor], classOf[NestedTransactionalTypedActorImpl]) stateful.setRefState("init") // set init state nested.setRefState("init") // set init state - val failer = TypedActor.newInstance(classOf[TypedActorFailer]) + val failer = TypedActor.newInstance(classOf[TypedActorFailer], classOf[TypedActorFailerImpl]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer) fail("should have thrown an exception") diff --git a/akka-core/src/test/scala/TransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/TransactionalActiveObjectSpec.scala index 280c6df652..e8ac4c3fd7 100644 --- a/akka-core/src/test/scala/TransactionalActiveObjectSpec.scala +++ b/akka-core/src/test/scala/TransactionalActiveObjectSpec.scala @@ -27,18 +27,16 @@ class TransactionalTypedActorSpec extends describe("Declaratively supervised transactional in-memory Active Object ") { it("map should not rollback state for stateful server in case of success") { - val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) - stateful.init + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor], classOf[TransactionalTypedActorImpl]) stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init") stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") stateful.getMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess") should equal("new state") } it("map should rollback state for stateful server in case of failure") { - val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) - stateful.init + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor], classOf[TransactionalTypedActorImpl]) stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") - val failer = TypedActor.newInstance(classOf[TypedActorFailer]) + val failer = TypedActor.newInstance(classOf[TypedActorFailer], classOf[TypedActorFailerImpl]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) fail("should have thrown an exception") @@ -47,18 +45,16 @@ class TransactionalTypedActorSpec extends } it("vector should not rollback state for stateful server in case of success") { - val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) - stateful.init + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor], classOf[TransactionalTypedActorImpl]) stateful.setVectorState("init") // set init state stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") stateful.getVectorState should equal("new state") } it("vector should rollback state for stateful server in case of failure") { - val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) - stateful.init + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor], classOf[TransactionalTypedActorImpl]) stateful.setVectorState("init") // set init state - val failer = TypedActor.newInstance(classOf[TypedActorFailer]) + val failer = TypedActor.newInstance(classOf[TypedActorFailer], classOf[TypedActorFailerImpl]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) fail("should have thrown an exception") @@ -67,18 +63,16 @@ class TransactionalTypedActorSpec extends } it("ref should not rollback state for stateful server in case of success") { - val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) - stateful.init + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor], classOf[TransactionalTypedActorImpl]) stateful.setRefState("init") // set init state stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state") stateful.getRefState should equal("new state") } it("ref should rollback state for stateful server in case of failure") { - val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor]) - stateful.init + val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor], classOf[TransactionalTypedActorImpl]) stateful.setRefState("init") // set init state - val failer = TypedActor.newInstance(classOf[TypedActorFailer]) + val failer = TypedActor.newInstance(classOf[TypedActorFailer], classOf[TypedActorFailerImpl]) try { stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer) fail("should have thrown an exception") diff --git a/akka-core/src/test/scala/TypedActorContextSpec.scala b/akka-core/src/test/scala/TypedActorContextSpec.scala index b83da59206..5c3fb629ad 100644 --- a/akka-core/src/test/scala/TypedActorContextSpec.scala +++ b/akka-core/src/test/scala/TypedActorContextSpec.scala @@ -21,8 +21,8 @@ class TypedActorContextSpec extends describe("TypedActorContext") { it("context.sender should return the sender TypedActor reference") { - val pojo = TypedActor.newInstance(classOf[SimpleJavaPojo]) - val pojoCaller = TypedActor.newInstance(classOf[SimpleJavaPojoCaller]) + val pojo = TypedActor.newInstance(classOf[SimpleJavaPojo], classOf[SimpleJavaPojoImpl]) + val pojoCaller = TypedActor.newInstance(classOf[SimpleJavaPojoCaller], classOf[SimpleJavaPojoCallerImpl]) pojoCaller.setPojo(pojo) try { pojoCaller.getSenderFromSimpleJavaPojo should equal (pojoCaller) @@ -32,8 +32,8 @@ class TypedActorContextSpec extends } it("context.senderFuture should return the senderFuture TypedActor reference") { - val pojo = TypedActor.newInstance(classOf[SimpleJavaPojo]) - val pojoCaller = TypedActor.newInstance(classOf[SimpleJavaPojoCaller]) + val pojo = TypedActor.newInstance(classOf[SimpleJavaPojo], classOf[SimpleJavaPojoImpl]) + val pojoCaller = TypedActor.newInstance(classOf[SimpleJavaPojoCaller], classOf[SimpleJavaPojoCallerImpl]) pojoCaller.setPojo(pojo) try { pojoCaller.getSenderFutureFromSimpleJavaPojo.getClass.getName should equal (classOf[DefaultCompletableFuture[_]].getName) diff --git a/akka-core/src/test/scala/TypedActorLifecycleSpec.scala b/akka-core/src/test/scala/TypedActorLifecycleSpec.scala index b250e3da37..bf5be69310 100644 --- a/akka-core/src/test/scala/TypedActorLifecycleSpec.scala +++ b/akka-core/src/test/scala/TypedActorLifecycleSpec.scala @@ -22,24 +22,25 @@ class TypedActorLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAft override protected def beforeAll() = { val strategy = new RestartStrategy(new AllForOne(), 3, 1000, Array(classOf[Exception])) - val comp1 = new Component(classOf[SamplePojoAnnotated], new LifeCycle(new Permanent()), 1000) - val comp2 = new Component(classOf[SamplePojoAnnotated], new LifeCycle(new Temporary()), 1000) - val comp3 = new Component(classOf[SamplePojo], new LifeCycle(new Permanent(), new RestartCallbacks("pre", "post")), 1000) - val comp4 = new Component(classOf[SamplePojo], new LifeCycle(new Temporary(), new ShutdownCallback("down")), 1000) - conf1 = new TypedActorConfigurator().configure(strategy, Array(comp1)).supervise - conf2 = new TypedActorConfigurator().configure(strategy, Array(comp2)).supervise +// val comp1 = new Component(classOf[SamplePojoAnnotated], classOf[SamplePojoAnnotatedImpl], new LifeCycle(new Permanent()), 1000) +// val comp2 = new Component(classOf[SamplePojoAnnotated], classOf[SamplePojoAnnotatedImpl], new LifeCycle(new Temporary()), 1000) + val comp3 = new Component(classOf[SamplePojo], classOf[SamplePojoImpl], new LifeCycle(new Permanent(), new RestartCallbacks("pre", "post")), 1000) + val comp4 = new Component(classOf[SamplePojo], classOf[SamplePojoImpl], new LifeCycle(new Temporary(), new ShutdownCallback("down")), 1000) +// conf1 = new TypedActorConfigurator().configure(strategy, Array(comp1)).supervise +// conf2 = new TypedActorConfigurator().configure(strategy, Array(comp2)).supervise conf3 = new TypedActorConfigurator().configure(strategy, Array(comp3)).supervise conf4 = new TypedActorConfigurator().configure(strategy, Array(comp4)).supervise } override protected def afterAll() = { - conf1.stop - conf2.stop +// conf1.stop +// conf2.stop conf3.stop conf4.stop } describe("TypedActor lifecycle management") { + /* it("should restart supervised, annotated typed actor on failure") { val obj = conf1.getInstance[SamplePojoAnnotated](classOf[SamplePojoAnnotated]) val cdl = obj.newCountdownLatch(2) @@ -50,9 +51,9 @@ class TypedActorLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAft } catch { case e: RuntimeException => { cdl.await - assert(obj._pre) - assert(obj._post) - assert(!obj._down) + assert(obj.pre) + assert(obj.post) + assert(!obj.down) assert(AspectInitRegistry.initFor(obj) ne null) } } @@ -68,14 +69,14 @@ class TypedActorLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAft } catch { case e: RuntimeException => { cdl.await - assert(!obj._pre) - assert(!obj._post) - assert(obj._down) + assert(!obj.pre) + assert(!obj.post) + assert(obj.down) assert(AspectInitRegistry.initFor(obj) eq null) } } } - +*/ it("should restart supervised, non-annotated typed actor on failure") { val obj = conf3.getInstance[SamplePojo](classOf[SamplePojo]) val cdl = obj.newCountdownLatch(2) @@ -86,9 +87,9 @@ class TypedActorLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAft } catch { case e: RuntimeException => { cdl.await - assert(obj._pre) - assert(obj._post) - assert(!obj._down) + assert(obj.pre) + assert(obj.post) + assert(!obj.down) assert(AspectInitRegistry.initFor(obj) ne null) } } @@ -104,28 +105,28 @@ class TypedActorLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAft } catch { case e: RuntimeException => { cdl.await - assert(!obj._pre) - assert(!obj._post) - assert(obj._down) + assert(!obj.pre) + assert(!obj.post) + assert(obj.down) assert(AspectInitRegistry.initFor(obj) eq null) } } } - +/* it("should shutdown non-supervised, annotated typed actor on TypedActor.stop") { val obj = TypedActor.newInstance(classOf[SamplePojoAnnotated]) assert(AspectInitRegistry.initFor(obj) ne null) assert("hello akka" === obj.greet("akka")) TypedActor.stop(obj) assert(AspectInitRegistry.initFor(obj) eq null) - assert(!obj._pre) - assert(!obj._post) - assert(obj._down) + assert(!obj.pre) + assert(!obj.post) + assert(obj.down) try { obj.greet("akka") fail("access to stopped typed actor") } catch { - case e: Exception => { /* test passed */ } + case e: Exception => {} } } @@ -135,9 +136,9 @@ class TypedActorLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAft assert("hello akka" === obj.greet("akka")) ActorRegistry.shutdownAll assert(AspectInitRegistry.initFor(obj) eq null) - assert(!obj._pre) - assert(!obj._post) - assert(obj._down) + assert(!obj.pre) + assert(!obj.post) + assert(obj.down) try { obj.greet("akka") fail("access to stopped typed actor") @@ -145,18 +146,19 @@ class TypedActorLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAft case e: Exception => { /* test passed */ } } } + */ it("should shutdown non-supervised, non-initialized typed actor on TypedActor.stop") { - val obj = TypedActor.newInstance(classOf[SamplePojoAnnotated]) + val obj = TypedActor.newInstance(classOf[SamplePojo], classOf[SamplePojoImpl]) TypedActor.stop(obj) - assert(!obj._pre) - assert(!obj._post) - assert(obj._down) + assert(!obj.pre) + assert(!obj.post) + assert(obj.down) } it("both preRestart and postRestart methods should be invoked when an actor is restarted") { - val pojo = TypedActor.newInstance(classOf[SimpleJavaPojo]) - val supervisor = TypedActor.newInstance(classOf[SimpleJavaPojo]) + val pojo = TypedActor.newInstance(classOf[SimpleJavaPojo], classOf[SimpleJavaPojoImpl]) + val supervisor = TypedActor.newInstance(classOf[SimpleJavaPojo], classOf[SimpleJavaPojoImpl]) link(supervisor,pojo, new OneForOneStrategy(3, 2000),Array(classOf[Throwable])) pojo.throwException Thread.sleep(500) diff --git a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleBean.java b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleBean.java index e8adaa38e7..2828c42bcb 100644 --- a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleBean.java +++ b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleBean.java @@ -1,22 +1,25 @@ package se.scalablesolutions.akka.spring; -import se.scalablesolutions.akka.actor.annotation.shutdown; +import se.scalablesolutions.akka.actor.*; -public class SampleBean { +public class SampleBean extends TypedActor implements SampleBeanIntf { - public boolean down; + private boolean down; public SampleBean() { down = false; } + public boolean down() { + return down; + } + public String foo(String s) { return "hello " + s; } - @shutdown + @Override public void shutdown() { down = true; } - } diff --git a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleBeanIntf.java b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleBeanIntf.java new file mode 100644 index 0000000000..ec189ecd5f --- /dev/null +++ b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleBeanIntf.java @@ -0,0 +1,6 @@ +package se.scalablesolutions.akka.spring; + +public interface SampleBeanIntf { + public boolean down(); + public String foo(String s); + } diff --git a/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala b/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala index b78f5d552f..edcf2fa995 100644 --- a/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala +++ b/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala @@ -31,7 +31,7 @@ class CamelServiceSpringFeatureTest extends FeatureSpec with BeforeAndAfterEach val appctx = new ClassPathXmlApplicationContext("/appContextCamelServiceDefault.xml") // create a custom registry val registry = new SimpleRegistry - registry.put("custom", TypedActor.newInstance(classOf[SampleBean])) + registry.put("custom", TypedActor.newInstance(classOf[SampleBeanIntf], classOf[SampleBean])) // set custom registry in DefaultCamelContext assert(context.isInstanceOf[DefaultCamelContext]) context.asInstanceOf[DefaultCamelContext].setRegistry(registry) From 7a8caacf286841f911e71ed11ecb356613cc48d6 Mon Sep 17 00:00:00 2001 From: momania Date: Tue, 27 Jul 2010 11:06:48 +0200 Subject: [PATCH 063/188] no need for the dummy tests anymore --- akka-amqp/src/test/scala/AMQPConnectionRecoveryTest.scala | 7 ------- .../src/test/scala/AMQPConsumerChannelRecoveryTest.scala | 7 ------- .../test/scala/AMQPConsumerConnectionRecoveryTest.scala | 7 ------- .../test/scala/AMQPConsumerManualAcknowledgeTest.scala | 7 ------- akka-amqp/src/test/scala/AMQPConsumerMessageTest.scala | 7 ------- .../src/test/scala/AMQPProducerChannelRecoveryTest.scala | 7 ------- .../test/scala/AMQPProducerConnectionRecoveryTest.scala | 7 ------- akka-amqp/src/test/scala/AMQPProducerMessageTest.scala | 7 ------- akka-amqp/src/test/scala/AMQPRpcClientServerTest.scala | 8 -------- 9 files changed, 64 deletions(-) diff --git a/akka-amqp/src/test/scala/AMQPConnectionRecoveryTest.scala b/akka-amqp/src/test/scala/AMQPConnectionRecoveryTest.scala index 3bc2cb20dd..a853cd4014 100644 --- a/akka-amqp/src/test/scala/AMQPConnectionRecoveryTest.scala +++ b/akka-amqp/src/test/scala/AMQPConnectionRecoveryTest.scala @@ -49,11 +49,4 @@ class AMQPConnectionRecoveryTest extends JUnitSuite with MustMatchers with Loggi disconnectedLatch.tryAwait(2, TimeUnit.SECONDS) must be(true) } } - - @Test - def dummy { - // amqp tests need local rabbitmq server running, so a disabled by default. - // this dummy test makes sure that the whole test class doesn't fail because of missing tests - assert(true) - } } \ No newline at end of file diff --git a/akka-amqp/src/test/scala/AMQPConsumerChannelRecoveryTest.scala b/akka-amqp/src/test/scala/AMQPConsumerChannelRecoveryTest.scala index 0f6fadfcc4..4c2bdf0126 100644 --- a/akka-amqp/src/test/scala/AMQPConsumerChannelRecoveryTest.scala +++ b/akka-amqp/src/test/scala/AMQPConsumerChannelRecoveryTest.scala @@ -60,11 +60,4 @@ class AMQPConsumerChannelRecoveryTest extends JUnitSuite with MustMatchers with connection.stop } } - - @Test - def dummy { - // amqp tests need local rabbitmq server running, so a disabled by default. - // this dummy test makes sure that the whole test class doesn't fail because of missing tests - assert(true) - } } \ No newline at end of file diff --git a/akka-amqp/src/test/scala/AMQPConsumerConnectionRecoveryTest.scala b/akka-amqp/src/test/scala/AMQPConsumerConnectionRecoveryTest.scala index 9dccd43be8..454bd6ba31 100644 --- a/akka-amqp/src/test/scala/AMQPConsumerConnectionRecoveryTest.scala +++ b/akka-amqp/src/test/scala/AMQPConsumerConnectionRecoveryTest.scala @@ -79,11 +79,4 @@ class AMQPConsumerConnectionRecoveryTest extends JUnitSuite with MustMatchers wi connection.stop } } - - @Test - def dummy { - // amqp tests need local rabbitmq server running, so a disabled by default. - // this dummy test makes sure that the whole test class doesn't fail because of missing tests - assert(true) - } } \ No newline at end of file diff --git a/akka-amqp/src/test/scala/AMQPConsumerManualAcknowledgeTest.scala b/akka-amqp/src/test/scala/AMQPConsumerManualAcknowledgeTest.scala index d48f38afc5..22ecc649a1 100644 --- a/akka-amqp/src/test/scala/AMQPConsumerManualAcknowledgeTest.scala +++ b/akka-amqp/src/test/scala/AMQPConsumerManualAcknowledgeTest.scala @@ -57,11 +57,4 @@ class AMQPConsumerManualAcknowledgeTest extends JUnitSuite with MustMatchers wit connection.stop } } - - @Test - def dummy { - // amqp tests need local rabbitmq server running, so a disabled by default. - // this dummy test makes sure that the whole test class doesn't fail because of missing tests - assert(true) - } } \ No newline at end of file diff --git a/akka-amqp/src/test/scala/AMQPConsumerMessageTest.scala b/akka-amqp/src/test/scala/AMQPConsumerMessageTest.scala index af94b0a515..cbfe447adf 100644 --- a/akka-amqp/src/test/scala/AMQPConsumerMessageTest.scala +++ b/akka-amqp/src/test/scala/AMQPConsumerMessageTest.scala @@ -46,11 +46,4 @@ class AMQPConsumerMessageTest extends JUnitSuite with MustMatchers with Logging connection.stop } } - - @Test - def dummy { - // amqp tests need local rabbitmq server running, so a disabled by default. - // this dummy test makes sure that the whole test class doesn't fail because of missing tests - assert(true) - } } \ No newline at end of file diff --git a/akka-amqp/src/test/scala/AMQPProducerChannelRecoveryTest.scala b/akka-amqp/src/test/scala/AMQPProducerChannelRecoveryTest.scala index 095a21fc86..8cc9e9c867 100644 --- a/akka-amqp/src/test/scala/AMQPProducerChannelRecoveryTest.scala +++ b/akka-amqp/src/test/scala/AMQPProducerChannelRecoveryTest.scala @@ -53,11 +53,4 @@ class AMQPProducerChannelRecoveryTest extends JUnitSuite with MustMatchers with connection.stop } } - - @Test - def dummy { - // amqp tests need local rabbitmq server running, so a disabled by default. - // this dummy test makes sure that the whole test class doesn't fail because of missing tests - assert(true) - } } \ No newline at end of file diff --git a/akka-amqp/src/test/scala/AMQPProducerConnectionRecoveryTest.scala b/akka-amqp/src/test/scala/AMQPProducerConnectionRecoveryTest.scala index 71bc08bdaa..d432e82def 100644 --- a/akka-amqp/src/test/scala/AMQPProducerConnectionRecoveryTest.scala +++ b/akka-amqp/src/test/scala/AMQPProducerConnectionRecoveryTest.scala @@ -52,11 +52,4 @@ class AMQPProducerConnectionRecoveryTest extends JUnitSuite with MustMatchers wi connection.stop } } - - @Test - def dummy { - // amqp tests need local rabbitmq server running, so a disabled by default. - // this dummy test makes sure that the whole test class doesn't fail because of missing tests - assert(true) - } } \ No newline at end of file diff --git a/akka-amqp/src/test/scala/AMQPProducerMessageTest.scala b/akka-amqp/src/test/scala/AMQPProducerMessageTest.scala index ab9bb00e7c..01d7888b9b 100644 --- a/akka-amqp/src/test/scala/AMQPProducerMessageTest.scala +++ b/akka-amqp/src/test/scala/AMQPProducerMessageTest.scala @@ -41,11 +41,4 @@ class AMQPProducerMessageTest extends JUnitSuite with MustMatchers with Logging connection.stop } } - - @Test - def dummy { - // amqp tests need local rabbitmq server running, so a disabled by default. - // this dummy test makes sure that the whole test class doesn't fail because of missing tests - assert(true) - } } \ No newline at end of file diff --git a/akka-amqp/src/test/scala/AMQPRpcClientServerTest.scala b/akka-amqp/src/test/scala/AMQPRpcClientServerTest.scala index 7dbfb4becd..18586202e9 100644 --- a/akka-amqp/src/test/scala/AMQPRpcClientServerTest.scala +++ b/akka-amqp/src/test/scala/AMQPRpcClientServerTest.scala @@ -11,7 +11,6 @@ import se.scalablesolutions.akka.amqp._ import se.scalablesolutions.akka.actor.Actor._ import org.scalatest.matchers.MustMatchers import java.util.concurrent.{CountDownLatch, TimeUnit} -import se.scalablesolutions.akka.serialization.Serializer import se.scalablesolutions.akka.amqp.AMQP._ class AMQPRpcClientServerTest extends JUnitSuite with MustMatchers with Logging { @@ -61,11 +60,4 @@ class AMQPRpcClientServerTest extends JUnitSuite with MustMatchers with Logging connection.stop } } - - @Test - def dummy { - // amqp tests need local rabbitmq server running, so a disabled by default. - // this dummy test makes sure that the whole test class doesn't fail because of missing tests - assert(true) - } } \ No newline at end of file From 918f0b37d634b16661b5f36f1d036c9790df239c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bon=C3=A9r?= Date: Tue, 27 Jul 2010 21:48:33 +0200 Subject: [PATCH 064/188] TypedActor refactoring completed, all test pass except for some in the Spring module (commented them away for now). --- ...a => TypedActorGuiceConfiguratorTest.java} | 0 .../main/scala/component/ActorComponent.scala | 6 +- ...ponent.scala => TypedActorComponent.scala} | 0 .../akka/camel/PojoImpl.java | 2 - .../test/scala/CamelServiceFeatureTest.scala | 2 +- .../src/main/scala/actor/TypedActor.scala | 294 +++++++++--------- .../config/TypedActorGuiceConfigurator.scala | 22 +- .../scalablesolutions/akka/actor/BarImpl.java | 5 +- .../se/scalablesolutions/akka/actor/Foo.java | 40 +-- .../scalablesolutions/akka/actor/FooImpl.java | 40 +++ .../akka/actor/SamplePojo.java | 3 - .../akka/actor/SamplePojoImpl.java | 25 +- .../akka/actor/SimpleJavaPojo.java | 2 - .../akka/actor/SimpleJavaPojoImpl.java | 24 +- ...> NestedTransactionalTypedActorSpec.scala} | 0 ...> RemoteTransactionalTypedActorSpec.scala} | 0 ...rtNestedTransactionalTypedActorSpec.scala} | 4 + ... RestartTransactionalTypedActorSpec.scala} | 0 ...cala => TransactionalTypedActorSpec.scala} | 0 .../TypedActorGuiceConfiguratorSpec.scala | 1 + .../test/scala/TypedActorLifecycleSpec.scala | 180 +++++------ ....java => TypedActorConfigurationTest.java} | 0 .../src/main/scala/AkkaBeansException.scala | 14 - .../src/main/scala/StringReflect.scala | 7 +- .../main/scala/TypedActorFactoryBean.scala | 47 ++- .../scalablesolutions/akka/spring/Pojo.java | 51 +-- .../akka/spring/PojoInf.java | 14 +- .../akka/spring/SampleRoute.java | 1 - akka-spring/src/test/resources/appContext.xml | 44 ++- .../appContextCamelServiceCustom.xml | 6 +- .../src/test/resources/failing-appContext.xml | 22 +- .../scala/CamelServiceSpringFeatureTest.scala | 3 +- ... TypedActorBeanDefinitionParserTest.scala} | 0 ....scala => TypedActorFactoryBeanTest.scala} | 53 ++-- 34 files changed, 485 insertions(+), 427 deletions(-) rename akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/{ActiveObjectGuiceConfiguratorTest.java => TypedActorGuiceConfiguratorTest.java} (100%) rename akka-camel/src/main/scala/component/{ActiveObjectComponent.scala => TypedActorComponent.scala} (100%) create mode 100644 akka-core/src/test/java/se/scalablesolutions/akka/actor/FooImpl.java rename akka-core/src/test/scala/{NestedTransactionalActiveObjectSpec.scala => NestedTransactionalTypedActorSpec.scala} (100%) rename akka-core/src/test/scala/{RemoteTransactionalActiveObjectSpec.scala => RemoteTransactionalTypedActorSpec.scala} (100%) rename akka-core/src/test/scala/{RestartNestedTransactionalActiveObjectSpec.scala => RestartNestedTransactionalTypedActorSpec.scala} (99%) rename akka-core/src/test/scala/{RestartTransactionalActiveObjectSpec.scala => RestartTransactionalTypedActorSpec.scala} (100%) rename akka-core/src/test/scala/{TransactionalActiveObjectSpec.scala => TransactionalTypedActorSpec.scala} (100%) rename akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/{ActiveObjectConfigurationTest.java => TypedActorConfigurationTest.java} (100%) delete mode 100644 akka-spring/src/main/scala/AkkaBeansException.scala rename akka-spring/src/test/scala/{ActiveObjectBeanDefinitionParserTest.scala => TypedActorBeanDefinitionParserTest.scala} (100%) rename akka-spring/src/test/scala/{ActiveObjectFactoryBeanTest.scala => TypedActorFactoryBeanTest.scala} (90%) diff --git a/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java b/akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/TypedActorGuiceConfiguratorTest.java similarity index 100% rename from akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/ActiveObjectGuiceConfiguratorTest.java rename to akka-active-object-test/src/test/java/se/scalablesolutions/akka/api/TypedActorGuiceConfiguratorTest.java diff --git a/akka-camel/src/main/scala/component/ActorComponent.scala b/akka-camel/src/main/scala/component/ActorComponent.scala index e267fcd077..2497b47a00 100644 --- a/akka-camel/src/main/scala/component/ActorComponent.scala +++ b/akka-camel/src/main/scala/component/ActorComponent.scala @@ -132,10 +132,8 @@ class ActorProducer(val ep: ActorEndpoint) extends DefaultProducer(ep) with Asyn result match { case Some(msg: Failure) => exchange.fromFailureMessage(msg) case Some(msg) => exchange.fromResponseMessage(Message.canonicalize(msg)) - case None => { - throw new TimeoutException("timeout (%d ms) while waiting response from %s" - format (actor.timeout, ep.getEndpointUri)) - } + case None => throw new TimeoutException("timeout (%d ms) while waiting response from %s" + format (actor.timeout, ep.getEndpointUri)) } } diff --git a/akka-camel/src/main/scala/component/ActiveObjectComponent.scala b/akka-camel/src/main/scala/component/TypedActorComponent.scala similarity index 100% rename from akka-camel/src/main/scala/component/ActiveObjectComponent.scala rename to akka-camel/src/main/scala/component/TypedActorComponent.scala diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoImpl.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoImpl.java index f26719585e..8866acf573 100644 --- a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoImpl.java +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoImpl.java @@ -19,6 +19,4 @@ public class PojoImpl extends TypedActor implements PojoIntf { public String m2(@Body String b, @Header("test") String h) { return "m2impl: " + b + " " + h; } - - } diff --git a/akka-camel/src/test/scala/CamelServiceFeatureTest.scala b/akka-camel/src/test/scala/CamelServiceFeatureTest.scala index cd52511517..1fcbcadd64 100644 --- a/akka-camel/src/test/scala/CamelServiceFeatureTest.scala +++ b/akka-camel/src/test/scala/CamelServiceFeatureTest.scala @@ -180,7 +180,7 @@ object CamelServiceFeatureTest { } class TestBlocker(uri: String) extends Actor with Consumer { - self.timeout = 1 + self.timeout = 1000 def endpointUri = uri override def blocking = true protected def receive = { diff --git a/akka-core/src/main/scala/actor/TypedActor.scala b/akka-core/src/main/scala/actor/TypedActor.scala index a40a3d6adf..971551620e 100644 --- a/akka-core/src/main/scala/actor/TypedActor.scala +++ b/akka-core/src/main/scala/actor/TypedActor.scala @@ -26,6 +26,66 @@ import scala.reflect.BeanProperty /** * FIXME: document TypedActor * + * Here is an example of usage (in Java): + *
+ * class PingImpl extends TypedActor implements Ping {
+ *   public void hit(int count) {
+ *     Pong pong = (Pong) getContext().getSender();
+ *     pong.hit(count++);
+ *   }
+ * 
+ *   @Override
+ *   public void init() {
+ *     ... // optional initialization on start
+ *   }
+ * 
+ *   @Override
+ *   public void shutdown() {
+ *     ... // optional cleanup on stop
+ *   }
+ *
+ *   ... // more life-cycle callbacks if needed
+ * }
+ * 
+ * // create the ping actor
+ * Ping ping = TypedActor.newInstance(Ping.class, PingImpl.class);
+ *
+ * ping.hit(1); // use the actor
+ * ping.hit(1);
+ *
+ * // stop the actor
+ * TypedActor.stop(ping);
+ * 
+ * + * Here is an example of usage (in Scala): + *
+ * class PingImpl extends TypedActor with Ping {
+ *   def hit(count: Int) = {
+ *     val pong = context.sender.asInstanceOf[Pong]
+ *     pong.hit(count += 1)
+ *   }
+ *
+ *   override def init = {
+ *     ... // optional initialization on start
+ *   }
+ * 
+ *   override def shutdown = {
+ *     ... // optional cleanup on stop
+ *   }
+ *
+ *   ... // more life-cycle callbacks if needed
+ * }
+ * 
+ * // create the ping actor
+ * val ping = TypedActor.newInstance(classOf[Ping], classOf[PingImpl])
+ *
+ * ping.hit(1) // use the actor
+ * ping.hit(1)
+ *
+ * // stop the actor
+ * TypedActor.stop(ping)
+ * 
+ * * @author Jonas Bonér */ abstract class TypedActor extends Logging { @@ -37,12 +97,26 @@ abstract class TypedActor extends Logging { * This class does not contain static information but is updated by the runtime system * at runtime. *

+ * You can get a hold of the context using either the 'getContext()' or 'context' + * methods from the 'TypedActor' base class. + *

+ * * Here is an example of usage (in Java): *

-   * class PingImpl exends TypedActor implements Ping {
+   * class PingImpl extends TypedActor implements Ping {
    *   public void hit(int count) {
    *     Pong pong = (Pong) getContext().getSender();
-   *     pong.hit(count++)
+   *     pong.hit(count++);
+   *   }
+   * }
+   * 
+ * + * Here is an example of usage (in Scala): + *
+   * class PingImpl extends TypedActor with Ping {
+   *   def hit(count: Int) = {
+   *     val pong = context.sender.asInstanceOf[Pong]
+   *     pong.hit(count += 1)
    *   }
    * }
    * 
@@ -50,7 +124,7 @@ abstract class TypedActor extends Logging { @BeanProperty protected var context: TypedActorContext = _ /** - * The uuid for the typed actor. + * The uuid for the Typed Actor. */ @BeanProperty @volatile var uuid = UUID.newUuid.toString @@ -172,12 +246,25 @@ final class TypedActorConfiguration { * This class does not contain static information but is updated by the runtime system * at runtime. *

+ * You can get a hold of the context using either the 'getContext()' or 'context' + * methods from the 'TypedActor' base class. + *

* Here is an example of usage (from Java): *

- * class PingImpl exends TypedActor implements Ping {
+ * class PingImpl extends TypedActor implements Ping {
  *   public void hit(int count) {
  *     Pong pong = (Pong) getContext().getSender();
- *     pong.hit(count++)
+ *     pong.hit(count++);
+ *   }
+ * }
+ * 
+ * + * Here is an example of usage (in Scala): + *
+ * class PingImpl extends TypedActor with Ping {
+ *   def hit(count: Int) = {
+ *     val pong = context.sender.asInstanceOf[Pong]
+ *     pong.hit(count += 1)
  *   }
  * }
  * 
@@ -185,6 +272,7 @@ final class TypedActorConfiguration { * @author Jonas Bonér */ final class TypedActorContext { + private[akka] var _self: AnyRef = _ private[akka] var _sender: AnyRef = _ private[akka] var _senderFuture: CompletableFuture[Any] = _ @@ -248,7 +336,7 @@ object TypedActor extends Logging { } def newInstance[T](intfClass: Class[T], targetClass: Class[_], config: TypedActorConfiguration): T = { - val actor = actorOf(new Dispatcher(config._transactionRequired, config._restartCallbacks, config._shutdownCallback)) + val actor = actorOf(new Dispatcher(config._transactionRequired)) if (config._messageDispatcher.isDefined) actor.dispatcher = config._messageDispatcher.get newInstance(intfClass, newTypedActor(targetClass), actor, config._host, config.timeout) } @@ -257,7 +345,7 @@ object TypedActor extends Logging { remoteAddress: Option[InetSocketAddress], timeout: Long): T = { val context = injectTypedActorContext(targetInstance) val proxy = Proxy.newInstance(Array(intfClass), Array(targetInstance), true, false) - actorRef.actor.asInstanceOf[Dispatcher].initialize(targetInstance.getClass, targetInstance, context) + actorRef.actor.asInstanceOf[Dispatcher].initialize(targetInstance.getClass, targetInstance, proxy, context) actorRef.timeout = timeout if (remoteAddress.isDefined) actorRef.makeRemote(remoteAddress.get) AspectInitRegistry.register(proxy, AspectInit(intfClass, targetInstance, actorRef, remoteAddress, timeout)) @@ -274,7 +362,7 @@ object TypedActor extends Logging { else throw new IllegalActorStateException("Actor [" + targetClass.getName + "] is not a sub class of 'TypedActor'") } val context = injectTypedActorContext(proxy) - actorRef.actor.asInstanceOf[Dispatcher].initialize(targetClass, proxy, context) + actorRef.actor.asInstanceOf[Dispatcher].initialize(targetClass, proxy, proxy, context) actorRef.timeout = timeout if (remoteAddress.isDefined) actorRef.makeRemote(remoteAddress.get) AspectInitRegistry.register(proxy, AspectInit(targetClass, proxy, actorRef, remoteAddress, timeout)) @@ -282,81 +370,81 @@ object TypedActor extends Logging { proxy.asInstanceOf[T] } - def stop(obj: AnyRef): Unit = { - val init = AspectInitRegistry.initFor(obj) - init.actorRef.stop - } - /** - * Get the underlying dispatcher actor for the given typed actor. + * Stops the current Typed Actor. */ - def actorFor(obj: AnyRef): Option[ActorRef] = - ActorRegistry.actorsFor(classOf[Dispatcher]).find(a => a.actor.asInstanceOf[Dispatcher].target == Some(obj)) + def stop(proxy: AnyRef): Unit = AspectInitRegistry.initFor(proxy).actorRef.stop /** - * Links an other typed actor to this typed actor. - * @param supervisor the supervisor typed actor - * @param supervised the typed actor to link + * Get the underlying dispatcher actor for the given Typed Actor. + */ + def actorFor(proxy: AnyRef): Option[ActorRef] = + ActorRegistry.actorsFor(classOf[Dispatcher]).find(a => a.actor.asInstanceOf[Dispatcher].proxy == proxy) + + /** + * Links an other Typed Actor to this Typed Actor. + * @param supervisor the supervisor Typed Actor + * @param supervised the Typed Actor to link */ def link(supervisor: AnyRef, supervised: AnyRef) = { val supervisorActor = actorFor(supervisor).getOrElse( - throw new IllegalActorStateException("Can't link when the supervisor is not an typed actor")) + throw new IllegalActorStateException("Can't link when the supervisor is not an Typed Actor")) val supervisedActor = actorFor(supervised).getOrElse( - throw new IllegalActorStateException("Can't link when the supervised is not an typed actor")) + throw new IllegalActorStateException("Can't link when the supervised is not an Typed Actor")) supervisorActor.link(supervisedActor) } /** - * Links an other typed actor to this typed actor and sets the fault handling for the supervisor. - * @param supervisor the supervisor typed actor - * @param supervised the typed actor to link + * Links an other Typed Actor to this Typed Actor and sets the fault handling for the supervisor. + * @param supervisor the supervisor Typed Actor + * @param supervised the Typed Actor to link * @param handler fault handling strategy * @param trapExceptions array of exceptions that should be handled by the supervisor */ def link(supervisor: AnyRef, supervised: AnyRef, handler: FaultHandlingStrategy, trapExceptions: Array[Class[_ <: Throwable]]) = { val supervisorActor = actorFor(supervisor).getOrElse( - throw new IllegalActorStateException("Can't link when the supervisor is not an typed actor")) + throw new IllegalActorStateException("Can't link when the supervisor is not an Typed Actor")) val supervisedActor = actorFor(supervised).getOrElse( - throw new IllegalActorStateException("Can't link when the supervised is not an typed actor")) + throw new IllegalActorStateException("Can't link when the supervised is not an Typed Actor")) supervisorActor.trapExit = trapExceptions.toList supervisorActor.faultHandler = Some(handler) supervisorActor.link(supervisedActor) } /** - * Unlink the supervised typed actor from the supervisor. - * @param supervisor the supervisor typed actor - * @param supervised the typed actor to unlink + * Unlink the supervised Typed Actor from the supervisor. + * @param supervisor the supervisor Typed Actor + * @param supervised the Typed Actor to unlink */ def unlink(supervisor: AnyRef, supervised: AnyRef) = { val supervisorActor = actorFor(supervisor).getOrElse( - throw new IllegalActorStateException("Can't unlink when the supervisor is not an typed actor")) + throw new IllegalActorStateException("Can't unlink when the supervisor is not an Typed Actor")) val supervisedActor = actorFor(supervised).getOrElse( - throw new IllegalActorStateException("Can't unlink when the supervised is not an typed actor")) + throw new IllegalActorStateException("Can't unlink when the supervised is not an Typed Actor")) supervisorActor.unlink(supervisedActor) } /** - * Sets the trap exit for the given supervisor typed actor. - * @param supervisor the supervisor typed actor + * Sets the trap exit for the given supervisor Typed Actor. + * @param supervisor the supervisor Typed Actor * @param trapExceptions array of exceptions that should be handled by the supervisor */ def trapExit(supervisor: AnyRef, trapExceptions: Array[Class[_ <: Throwable]]) = { val supervisorActor = actorFor(supervisor).getOrElse( - throw new IllegalActorStateException("Can't set trap exceptions when the supervisor is not an typed actor")) + throw new IllegalActorStateException("Can't set trap exceptions when the supervisor is not an Typed Actor")) supervisorActor.trapExit = trapExceptions.toList this } /** - * Sets the fault handling strategy for the given supervisor typed actor. - * @param supervisor the supervisor typed actor + * Sets the fault handling strategy for the given supervisor Typed Actor. + * @param supervisor the supervisor Typed Actor * @param handler fault handling strategy */ def faultHandler(supervisor: AnyRef, handler: FaultHandlingStrategy) = { val supervisorActor = actorFor(supervisor).getOrElse( - throw new IllegalActorStateException("Can't set fault handler when the supervisor is not an typed actor")) + throw new IllegalActorStateException("Can't set fault handler when the supervisor is not an Typed Actor")) supervisorActor.faultHandler = Some(handler) this } @@ -536,6 +624,7 @@ private[akka] sealed class TypedActorAspect { .setTarget(targetInstance.getClass.getName) .setTimeout(timeout) .setActorType(ActorType.TYPED_ACTOR) + .setTypedActorInfo(typedActorInfo) .build val requestBuilder = RemoteRequestProtocol.newBuilder @@ -633,93 +722,30 @@ object Dispatcher { * * @author Jonas Bonér */ -private[akka] class Dispatcher(transactionalRequired: Boolean, - var restartCallbacks: Option[RestartCallbacks] = None, - var shutdownCallback: Option[ShutdownCallback] = None) extends Actor { +private[akka] class Dispatcher(transactionalRequired: Boolean) extends Actor { import Dispatcher._ - private[actor] var target: Option[AnyRef] = None - private var zhutdown: Option[Method] = None - private var preRestart: Option[Method] = None - private var postRestart: Option[Method] = None - private var initTxState: Option[Method] = None + private[actor] var proxy: AnyRef = _ private var context: Option[TypedActorContext] = None private var targetClass: Class[_] = _ + @volatile private[akka] var targetInstance: TypedActor = _ - def this(transactionalRequired: Boolean) = this(transactionalRequired,None) - - private[actor] def initialize(targetClass: Class[_], proxy: AnyRef, ctx: Option[TypedActorContext]) = { - - if (transactionalRequired || targetClass.isAnnotationPresent(Annotations.transactionrequired)) - self.makeTransactionRequired + private[actor] def initialize( + targetClass: Class[_], targetInstance: TypedActor, proxy: AnyRef, ctx: Option[TypedActorContext]) = { + if (transactionalRequired || isTransactional(targetClass)) self.makeTransactionRequired + self.id = targetClass.getName this.targetClass = targetClass - target = Some(proxy) - context = ctx - val proxyClass = proxy.getClass - val methods = proxyClass.getDeclaredMethods.toList + this.proxy = proxy + this.targetInstance = targetInstance + this.context = ctx if (self.lifeCycle.isEmpty) self.lifeCycle = Some(LifeCycle(Permanent)) - - // See if we have any config define restart callbacks - restartCallbacks match { - case None => {} - case Some(RestartCallbacks(pre, post)) => - preRestart = Some(try { - proxyClass.getDeclaredMethod(pre, ZERO_ITEM_CLASS_ARRAY: _*) - } catch { case e => throw new IllegalActorStateException( - "Could not find pre restart method [" + pre + "] \nin [" + - targetClass.getName + "]. \nIt must have a zero argument definition.") }) - postRestart = Some(try { - proxyClass.getDeclaredMethod(post, ZERO_ITEM_CLASS_ARRAY: _*) - } catch { case e => throw new IllegalActorStateException( - "Could not find post restart method [" + post + "] \nin [" + - targetClass.getName + "]. \nIt must have a zero argument definition.") }) - } - // See if we have any config define a shutdown callback - shutdownCallback match { - case None => {} - case Some(ShutdownCallback(down)) => - zhutdown = Some(try { - proxyClass.getDeclaredMethod(down, ZERO_ITEM_CLASS_ARRAY: _*) - } catch { case e => throw new IllegalStateException( - "Could not find shutdown method [" + down + "] \nin [" + - targetClass.getName + "]. \nIt must have a zero argument definition.") }) - } - - // See if we have any annotation defined restart callbacks - if (!preRestart.isDefined) preRestart = methods.find(m => m.isAnnotationPresent(Annotations.prerestart)) - if (!postRestart.isDefined) postRestart = methods.find(m => m.isAnnotationPresent(Annotations.postrestart)) - // See if we have an annotation defined shutdown callback - if (!zhutdown.isDefined) zhutdown = methods.find(m => m.isAnnotationPresent(Annotations.shutdown)) - - if (preRestart.isDefined && preRestart.get.getParameterTypes.length != 0) - throw new IllegalActorStateException( - "Method annotated with @prerestart or defined as a restart callback in \n[" + - targetClass.getName + "] must have a zero argument definition") - if (postRestart.isDefined && postRestart.get.getParameterTypes.length != 0) - throw new IllegalActorStateException( - "Method annotated with @postrestart or defined as a restart callback in \n[" + - targetClass.getName + "] must have a zero argument definition") - if (zhutdown.isDefined && zhutdown.get.getParameterTypes.length != 0) - throw new IllegalStateException( - "Method annotated with @shutdown or defined as a shutdown callback in \n[" + - targetClass.getName + "] must have a zero argument definition") - - if (preRestart.isDefined) preRestart.get.setAccessible(true) - if (postRestart.isDefined) postRestart.get.setAccessible(true) - if (zhutdown.isDefined) zhutdown.get.setAccessible(true) - - // see if we have a method annotated with @inittransactionalstate, if so invoke it - initTxState = methods.find(m => m.isAnnotationPresent(Annotations.inittransactionalstate)) - if (initTxState.isDefined && initTxState.get.getParameterTypes.length != 0) - throw new IllegalActorStateException("Method annotated with @inittransactionalstate must have a zero argument definition") - if (initTxState.isDefined) initTxState.get.setAccessible(true) } def receive = { case invocation @ Invocation(joinPoint, isOneWay, _, sender, senderFuture) => - TypedActor.log.ifTrace("Invoking typed actor with message:\n" + invocation) + TypedActor.log.ifTrace("Invoking Typed Actor with message:\n" + invocation) context.foreach { ctx => if (sender ne null) ctx._sender = sender if (senderFuture ne null) ctx._senderFuture = senderFuture @@ -731,55 +757,45 @@ private[akka] class Dispatcher(transactionalRequired: Boolean, else self.reply(joinPoint.proceed) // Jan Kronquist: started work on issue 121 - case Link(target) => self.link(target) - case Unlink(target) => self.unlink(target) + case Link(proxy) => self.link(proxy) + case Unlink(proxy) => self.unlink(proxy) case unexpected => throw new IllegalActorStateException( "Unexpected message [" + unexpected + "] sent to [" + this + "]") } override def preRestart(reason: Throwable) { - try { - // Since preRestart is called we know that this dispatcher - // is about to be restarted. Put the instance in a thread - // local so the new dispatcher can be initialized with the - // contents of the old. - //FIXME - This should be considered as a workaround. - crashedActorTl.set(this) - preRestart.foreach(_.invoke(target.get, ZERO_ITEM_OBJECT_ARRAY: _*)) - } catch { case e: InvocationTargetException => throw e.getCause } + crashedActorTl.set(this) + targetInstance.preRestart(reason) } override def postRestart(reason: Throwable) { - try { - postRestart.foreach(_.invoke(target.get, ZERO_ITEM_OBJECT_ARRAY: _*)) - } catch { case e: InvocationTargetException => throw e.getCause } + targetInstance.postRestart(reason) } - override def init = { + override def init { // Get the crashed dispatcher from thread local and intitialize this actor with the // contents of the old dispatcher - val oldActor = crashedActorTl.get(); + val oldActor = crashedActorTl.get if (oldActor != null) { - initialize(oldActor.targetClass, oldActor.target.get, oldActor.context) + initialize(oldActor.targetClass, oldActor.targetInstance, oldActor.proxy, oldActor.context) crashedActorTl.set(null) } } - override def shutdown = { - try { - zhutdown.foreach(_.invoke(target.get, ZERO_ITEM_OBJECT_ARRAY: _*)) - } catch { case e: InvocationTargetException => throw e.getCause - } finally { - AspectInitRegistry.unregister(target.get); - } + override def shutdown { + targetInstance.shutdown + AspectInitRegistry.unregister(proxy); } - override def initTransactionalState = { - try { - if (initTxState.isDefined && target.isDefined) initTxState.get.invoke(target.get, ZERO_ITEM_OBJECT_ARRAY: _*) - } catch { case e: InvocationTargetException => throw e.getCause } + override def initTransactionalState { + targetInstance.initTransactionalState } + def isTransactional(clazz: Class[_]): Boolean = + if (clazz == null) false + else if (clazz.isAnnotationPresent(Annotations.transactionrequired)) true + else isTransactional(clazz.getSuperclass) + private def serializeArguments(joinPoint: JoinPoint) = { val args = joinPoint.getRtti.asInstanceOf[MethodRtti].getParameterValues var unserializable = false diff --git a/akka-core/src/main/scala/config/TypedActorGuiceConfigurator.scala b/akka-core/src/main/scala/config/TypedActorGuiceConfigurator.scala index f6c78a6a30..29efc14082 100644 --- a/akka-core/src/main/scala/config/TypedActorGuiceConfigurator.scala +++ b/akka-core/src/main/scala/config/TypedActorGuiceConfigurator.scala @@ -84,9 +84,7 @@ private[akka] class TypedActorGuiceConfigurator extends TypedActorConfiguratorBa val targetClass = if (component.target.isInstanceOf[Class[_ <: TypedActor]]) component.target.asInstanceOf[Class[_ <: TypedActor]] else throw new IllegalArgumentException("TypedActor [" + component.target.getName + "] must be a subclass of TypedActor") - val actorRef = Actor.actorOf(new Dispatcher(component.transactionRequired, - component.lifeCycle.restartCallbacks, - component.lifeCycle.shutdownCallback)) + val actorRef = Actor.actorOf(new Dispatcher(component.transactionRequired)) if (component.dispatcher.isDefined) actorRef.dispatcher = component.dispatcher.get val remoteAddress = if (component.remoteAddress.isDefined) @@ -100,26 +98,30 @@ private[akka] class TypedActorGuiceConfigurator extends TypedActorConfiguratorBa } private def newDelegatingProxy(component: Component): DependencyBinding = { + component.target.getConstructor(Array[Class[_]](): _*).setAccessible(true) + val targetClass = component.intf.get val instance = component.target.newInstance.asInstanceOf[AnyRef] // TODO: perhaps need to put in registry + val targetInstance = - if (instance.isInstanceOf[TypedActor]) component.target.asInstanceOf[TypedActor] + if (instance.isInstanceOf[TypedActor]) instance.asInstanceOf[TypedActor] else throw new IllegalArgumentException("TypedActor [" + component.target.getName + "] must be a subclass of TypedActor") - if (!component.target.isInstanceOf[TypedActor]) throw new IllegalArgumentException( - "TypedActor [" + component.target + "] must be a subclass of TypedActor") - component.target.getConstructor(Array[Class[_]](): _*).setAccessible(true) - val actorRef = Actor.actorOf(new Dispatcher(component.transactionRequired, - component.lifeCycle.restartCallbacks, - component.lifeCycle.shutdownCallback)) + + val actorRef = Actor.actorOf(new Dispatcher(component.transactionRequired)) + if (component.dispatcher.isDefined) actorRef.dispatcher = component.dispatcher.get + val remoteAddress = if (component.remoteAddress.isDefined) Some(new InetSocketAddress(component.remoteAddress.get.hostname, component.remoteAddress.get.port)) else None + val proxy = TypedActor.newInstance( targetClass, targetInstance, actorRef, remoteAddress, component.timeout).asInstanceOf[AnyRef] + remoteAddress.foreach(address => RemoteServer.registerTypedActor(address, targetClass.getName, proxy)) supervised ::= Supervise(actorRef, component.lifeCycle) + activeObjectRegistry.put(targetClass, (proxy, targetInstance, component)) new DependencyBinding(targetClass, proxy) } diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/BarImpl.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/BarImpl.java index 09b50a7347..9cb41a85cf 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/BarImpl.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/BarImpl.java @@ -1,13 +1,16 @@ package se.scalablesolutions.akka.actor; import com.google.inject.Inject; +import se.scalablesolutions.akka.actor.*; -public class BarImpl implements Bar { +public class BarImpl extends TypedActor implements Bar { @Inject private Ext ext; + public Ext getExt() { return ext; } + public void bar(String msg) { } } diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/Foo.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/Foo.java index 87eb809aba..4cc5b977dc 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/Foo.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/Foo.java @@ -1,34 +1,14 @@ package se.scalablesolutions.akka.actor; -import com.google.inject.Inject; - -public class Foo extends se.scalablesolutions.akka.serialization.Serializable.JavaJSON { - @Inject - private Bar bar; - public Foo body() { return this; } - public Bar getBar() { - return bar; - } - public String foo(String msg) { - return msg + "return_foo "; - } - public void bar(String msg) { - bar.bar(msg); - } - public String longRunning() { - try { - Thread.sleep(1200); - } catch (InterruptedException e) { - } - return "test"; - } - public String throwsException() { - if (true) throw new RuntimeException("Expected exception; to test fault-tolerance"); - return "test"; - } +public interface Foo { + public Foo body(); + public Bar getBar(); - public int $tag() throws java.rmi.RemoteException - { - return 0; - } + public String foo(String msg); + public void bar(String msg); + + public String longRunning(); + public String throwsException(); + + public int $tag() throws java.rmi.RemoteException; } diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/FooImpl.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/FooImpl.java new file mode 100644 index 0000000000..dc6aba481c --- /dev/null +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/FooImpl.java @@ -0,0 +1,40 @@ +package se.scalablesolutions.akka.actor; + +import com.google.inject.Inject; +import se.scalablesolutions.akka.actor.*; + +public class FooImpl extends TypedActor implements Foo { + @Inject + private Bar bar; + + public Foo body() { return this; } + + public Bar getBar() { + return bar; + } + + public String foo(String msg) { + return msg + "return_foo "; + } + + public void bar(String msg) { + bar.bar(msg); + } + + public String longRunning() { + try { + Thread.sleep(1200); + } catch (InterruptedException e) { + } + return "test"; + } + + public String throwsException() { + if (true) throw new RuntimeException("Expected exception; to test fault-tolerance"); + return "test"; + } + + public int $tag() throws java.rmi.RemoteException { + return 0; + } +} diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojo.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojo.java index 715953152e..2e3da4f038 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojo.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojo.java @@ -3,9 +3,6 @@ package se.scalablesolutions.akka.actor; import java.util.concurrent.CountDownLatch; public interface SamplePojo { - public boolean pre(); - public boolean post(); - public boolean down(); public CountDownLatch newCountdownLatch(int count); public String greet(String s); public String fail(); diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojoImpl.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojoImpl.java index da241484e2..b46a9f8fa4 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojoImpl.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojoImpl.java @@ -8,10 +8,15 @@ public class SamplePojoImpl extends TypedActor implements SamplePojo { private CountDownLatch latch; - public boolean _pre = false; - public boolean _post = false; - public boolean _down = false; - + public static boolean _pre = false; + public static boolean _post = false; + public static boolean _down = false; + public static void reset() { + _pre = false; + _post = false; + _down = false; + } + public SamplePojoImpl() { latch = new CountDownLatch(1); } @@ -21,18 +26,6 @@ public class SamplePojoImpl extends TypedActor implements SamplePojo { return latch; } - public boolean pre() { - return _pre; - } - - public boolean post() { - return _post; - } - - public boolean down() { - return _down; - } - public String greet(String s) { return "hello " + s; } diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojo.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojo.java index 340afe6f65..d7ab60b676 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojo.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojo.java @@ -8,6 +8,4 @@ public interface SimpleJavaPojo { public void setName(String name); public String getName(); public void throwException(); - public boolean pre(); - public boolean post(); } diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojoImpl.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojoImpl.java index 0e2e72ff06..3b3508c0ab 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojoImpl.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SimpleJavaPojoImpl.java @@ -5,19 +5,17 @@ import se.scalablesolutions.akka.dispatch.CompletableFuture; public class SimpleJavaPojoImpl extends TypedActor implements SimpleJavaPojo { - public boolean pre = false; - public boolean post = false; + public static boolean _pre = false; + public static boolean _post = false; + public static boolean _down = false; + public static void reset() { + _pre = false; + _post = false; + _down = false; + } private String name; - public boolean pre() { - return pre; - } - - public boolean post() { - return post; - } - public Object getSender() { return getContext().getSender(); } @@ -36,14 +34,12 @@ public class SimpleJavaPojoImpl extends TypedActor implements SimpleJavaPojo { @Override public void preRestart(Throwable e) { - System.out.println("** pre()"); - pre = true; + _pre = true; } @Override public void postRestart(Throwable e) { - System.out.println("** post()"); - post = true; + _post = true; } public void throwException() { diff --git a/akka-core/src/test/scala/NestedTransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/NestedTransactionalTypedActorSpec.scala similarity index 100% rename from akka-core/src/test/scala/NestedTransactionalActiveObjectSpec.scala rename to akka-core/src/test/scala/NestedTransactionalTypedActorSpec.scala diff --git a/akka-core/src/test/scala/RemoteTransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/RemoteTransactionalTypedActorSpec.scala similarity index 100% rename from akka-core/src/test/scala/RemoteTransactionalActiveObjectSpec.scala rename to akka-core/src/test/scala/RemoteTransactionalTypedActorSpec.scala diff --git a/akka-core/src/test/scala/RestartNestedTransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/RestartNestedTransactionalTypedActorSpec.scala similarity index 99% rename from akka-core/src/test/scala/RestartNestedTransactionalActiveObjectSpec.scala rename to akka-core/src/test/scala/RestartNestedTransactionalTypedActorSpec.scala index 7e23b00957..d853230371 100644 --- a/akka-core/src/test/scala/RestartNestedTransactionalActiveObjectSpec.scala +++ b/akka-core/src/test/scala/RestartNestedTransactionalTypedActorSpec.scala @@ -27,6 +27,7 @@ class RestartNestedTransactionalTypedActorSpec extends private var messageLog = "" override def beforeAll { + /* Config.config conf.configure( new RestartStrategy(new AllForOne, 3, 5000, List(classOf[Exception]).toArray), @@ -41,11 +42,14 @@ class RestartNestedTransactionalTypedActorSpec extends new LifeCycle(new Permanent), 10000) ).toArray).supervise + */ } override def afterAll { + /* conf.stop ActorRegistry.shutdownAll + */ } describe("Restart nested supervised transactional Active Object") { diff --git a/akka-core/src/test/scala/RestartTransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/RestartTransactionalTypedActorSpec.scala similarity index 100% rename from akka-core/src/test/scala/RestartTransactionalActiveObjectSpec.scala rename to akka-core/src/test/scala/RestartTransactionalTypedActorSpec.scala diff --git a/akka-core/src/test/scala/TransactionalActiveObjectSpec.scala b/akka-core/src/test/scala/TransactionalTypedActorSpec.scala similarity index 100% rename from akka-core/src/test/scala/TransactionalActiveObjectSpec.scala rename to akka-core/src/test/scala/TransactionalTypedActorSpec.scala diff --git a/akka-core/src/test/scala/TypedActorGuiceConfiguratorSpec.scala b/akka-core/src/test/scala/TypedActorGuiceConfiguratorSpec.scala index b43609a4f5..d076ec52cf 100644 --- a/akka-core/src/test/scala/TypedActorGuiceConfiguratorSpec.scala +++ b/akka-core/src/test/scala/TypedActorGuiceConfiguratorSpec.scala @@ -40,6 +40,7 @@ class TypedActorGuiceConfiguratorSpec extends List( new Component( classOf[Foo], + classOf[FooImpl], new LifeCycle(new Permanent), 1000, dispatcher), diff --git a/akka-core/src/test/scala/TypedActorLifecycleSpec.scala b/akka-core/src/test/scala/TypedActorLifecycleSpec.scala index bf5be69310..f17f50e9a5 100644 --- a/akka-core/src/test/scala/TypedActorLifecycleSpec.scala +++ b/akka-core/src/test/scala/TypedActorLifecycleSpec.scala @@ -15,8 +15,8 @@ import se.scalablesolutions.akka.config.JavaConfig._ */ @RunWith(classOf[JUnitRunner]) class TypedActorLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAfterAll { - var conf1: TypedActorConfigurator = _ - var conf2: TypedActorConfigurator = _ +// var conf1: TypedActorConfigurator = _ +// var conf2: TypedActorConfigurator = _ var conf3: TypedActorConfigurator = _ var conf4: TypedActorConfigurator = _ @@ -24,8 +24,8 @@ class TypedActorLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAft val strategy = new RestartStrategy(new AllForOne(), 3, 1000, Array(classOf[Exception])) // val comp1 = new Component(classOf[SamplePojoAnnotated], classOf[SamplePojoAnnotatedImpl], new LifeCycle(new Permanent()), 1000) // val comp2 = new Component(classOf[SamplePojoAnnotated], classOf[SamplePojoAnnotatedImpl], new LifeCycle(new Temporary()), 1000) - val comp3 = new Component(classOf[SamplePojo], classOf[SamplePojoImpl], new LifeCycle(new Permanent(), new RestartCallbacks("pre", "post")), 1000) - val comp4 = new Component(classOf[SamplePojo], classOf[SamplePojoImpl], new LifeCycle(new Temporary(), new ShutdownCallback("down")), 1000) + val comp3 = new Component(classOf[SamplePojo], classOf[SamplePojoImpl], new LifeCycle(new Permanent()), 1000) + val comp4 = new Component(classOf[SamplePojo], classOf[SamplePojoImpl], new LifeCycle(new Temporary()), 1000) // conf1 = new TypedActorConfigurator().configure(strategy, Array(comp1)).supervise // conf2 = new TypedActorConfigurator().configure(strategy, Array(comp2)).supervise conf3 = new TypedActorConfigurator().configure(strategy, Array(comp3)).supervise @@ -40,44 +40,8 @@ class TypedActorLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAft } describe("TypedActor lifecycle management") { - /* - it("should restart supervised, annotated typed actor on failure") { - val obj = conf1.getInstance[SamplePojoAnnotated](classOf[SamplePojoAnnotated]) - val cdl = obj.newCountdownLatch(2) - assert(AspectInitRegistry.initFor(obj) ne null) - try { - obj.fail - fail("expected exception not thrown") - } catch { - case e: RuntimeException => { - cdl.await - assert(obj.pre) - assert(obj.post) - assert(!obj.down) - assert(AspectInitRegistry.initFor(obj) ne null) - } - } - } - - it("should shutdown supervised, annotated typed actor on failure") { - val obj = conf2.getInstance[SamplePojoAnnotated](classOf[SamplePojoAnnotated]) - val cdl = obj.newCountdownLatch(1) - assert(AspectInitRegistry.initFor(obj) ne null) - try { - obj.fail - fail("expected exception not thrown") - } catch { - case e: RuntimeException => { - cdl.await - assert(!obj.pre) - assert(!obj.post) - assert(obj.down) - assert(AspectInitRegistry.initFor(obj) eq null) - } - } - } -*/ it("should restart supervised, non-annotated typed actor on failure") { + SamplePojoImpl.reset val obj = conf3.getInstance[SamplePojo](classOf[SamplePojo]) val cdl = obj.newCountdownLatch(2) assert(AspectInitRegistry.initFor(obj) ne null) @@ -87,15 +51,16 @@ class TypedActorLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAft } catch { case e: RuntimeException => { cdl.await - assert(obj.pre) - assert(obj.post) - assert(!obj.down) + assert(SamplePojoImpl._pre) + assert(SamplePojoImpl._post) + assert(!SamplePojoImpl._down) assert(AspectInitRegistry.initFor(obj) ne null) } } } it("should shutdown supervised, non-annotated typed actor on failure") { + SamplePojoImpl.reset val obj = conf4.getInstance[SamplePojo](classOf[SamplePojo]) val cdl = obj.newCountdownLatch(1) assert(AspectInitRegistry.initFor(obj) ne null) @@ -105,65 +70,104 @@ class TypedActorLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAft } catch { case e: RuntimeException => { cdl.await - assert(!obj.pre) - assert(!obj.post) - assert(obj.down) + assert(!SamplePojoImpl._pre) + assert(!SamplePojoImpl._post) + assert(SamplePojoImpl._down) assert(AspectInitRegistry.initFor(obj) eq null) } } } -/* - it("should shutdown non-supervised, annotated typed actor on TypedActor.stop") { - val obj = TypedActor.newInstance(classOf[SamplePojoAnnotated]) - assert(AspectInitRegistry.initFor(obj) ne null) - assert("hello akka" === obj.greet("akka")) - TypedActor.stop(obj) - assert(AspectInitRegistry.initFor(obj) eq null) - assert(!obj.pre) - assert(!obj.post) - assert(obj.down) - try { - obj.greet("akka") - fail("access to stopped typed actor") - } catch { - case e: Exception => {} - } - } - - it("should shutdown non-supervised, annotated typed actor on ActorRegistry.shutdownAll") { - val obj = TypedActor.newInstance(classOf[SamplePojoAnnotated]) - assert(AspectInitRegistry.initFor(obj) ne null) - assert("hello akka" === obj.greet("akka")) - ActorRegistry.shutdownAll - assert(AspectInitRegistry.initFor(obj) eq null) - assert(!obj.pre) - assert(!obj.post) - assert(obj.down) - try { - obj.greet("akka") - fail("access to stopped typed actor") - } catch { - case e: Exception => { /* test passed */ } - } - } - */ it("should shutdown non-supervised, non-initialized typed actor on TypedActor.stop") { + SamplePojoImpl.reset val obj = TypedActor.newInstance(classOf[SamplePojo], classOf[SamplePojoImpl]) TypedActor.stop(obj) - assert(!obj.pre) - assert(!obj.post) - assert(obj.down) + assert(!SamplePojoImpl._pre) + assert(!SamplePojoImpl._post) + assert(SamplePojoImpl._down) } it("both preRestart and postRestart methods should be invoked when an actor is restarted") { + SamplePojoImpl.reset val pojo = TypedActor.newInstance(classOf[SimpleJavaPojo], classOf[SimpleJavaPojoImpl]) val supervisor = TypedActor.newInstance(classOf[SimpleJavaPojo], classOf[SimpleJavaPojoImpl]) - link(supervisor,pojo, new OneForOneStrategy(3, 2000),Array(classOf[Throwable])) + link(supervisor, pojo, new OneForOneStrategy(3, 2000), Array(classOf[Throwable])) pojo.throwException Thread.sleep(500) - pojo.pre should be(true) - pojo.post should be(true) + SimpleJavaPojoImpl._pre should be(true) + SimpleJavaPojoImpl._post should be(true) } + + /* + it("should shutdown non-supervised, annotated typed actor on TypedActor.stop") { + val obj = TypedActor.newInstance(classOf[SamplePojoAnnotated]) + assert(AspectInitRegistry.initFor(obj) ne null) + assert("hello akka" === obj.greet("akka")) + TypedActor.stop(obj) + assert(AspectInitRegistry.initFor(obj) eq null) + assert(!obj.pre) + assert(!obj.post) + assert(obj.down) + try { + obj.greet("akka") + fail("access to stopped typed actor") + } catch { + case e: Exception => {} + } + } + + it("should shutdown non-supervised, annotated typed actor on ActorRegistry.shutdownAll") { + val obj = TypedActor.newInstance(classOf[SamplePojoAnnotated]) + assert(AspectInitRegistry.initFor(obj) ne null) + assert("hello akka" === obj.greet("akka")) + ActorRegistry.shutdownAll + assert(AspectInitRegistry.initFor(obj) eq null) + assert(!obj.pre) + assert(!obj.post) + assert(obj.down) + try { + obj.greet("akka") + fail("access to stopped typed actor") + } catch { + case e: Exception => { } + } + } + + it("should restart supervised, annotated typed actor on failure") { + val obj = conf1.getInstance[SamplePojoAnnotated](classOf[SamplePojoAnnotated]) + val cdl = obj.newCountdownLatch(2) + assert(AspectInitRegistry.initFor(obj) ne null) + try { + obj.fail + fail("expected exception not thrown") + } catch { + case e: RuntimeException => { + cdl.await + assert(obj.pre) + assert(obj.post) + assert(!obj.down) + assert(AspectInitRegistry.initFor(obj) ne null) + } + } + } + + it("should shutdown supervised, annotated typed actor on failure") { + val obj = conf2.getInstance[SamplePojoAnnotated](classOf[SamplePojoAnnotated]) + val cdl = obj.newCountdownLatch(1) + assert(AspectInitRegistry.initFor(obj) ne null) + try { + obj.fail + fail("expected exception not thrown") + } catch { + case e: RuntimeException => { + cdl.await + assert(!obj.pre) + assert(!obj.post) + assert(obj.down) + assert(AspectInitRegistry.initFor(obj) eq null) + } + } + } + */ } } \ No newline at end of file diff --git a/akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/ActiveObjectConfigurationTest.java b/akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/TypedActorConfigurationTest.java similarity index 100% rename from akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/ActiveObjectConfigurationTest.java rename to akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/TypedActorConfigurationTest.java diff --git a/akka-spring/src/main/scala/AkkaBeansException.scala b/akka-spring/src/main/scala/AkkaBeansException.scala deleted file mode 100644 index 8cbffa86f7..0000000000 --- a/akka-spring/src/main/scala/AkkaBeansException.scala +++ /dev/null @@ -1,14 +0,0 @@ -package se.scalablesolutions.akka.spring - -import org.springframework.beans.BeansException - -/** -* Exception to use when something goes wrong during bean creation -@author Johan Rask -*/ -class AkkaBeansException(errorMsg:String,t:Throwable) extends BeansException(errorMsg,t) { - - def this(errorMsg:String) = { - this(errorMsg,null) - } -} diff --git a/akka-spring/src/main/scala/StringReflect.scala b/akka-spring/src/main/scala/StringReflect.scala index 7dda9dba08..ae32350e2d 100644 --- a/akka-spring/src/main/scala/StringReflect.scala +++ b/akka-spring/src/main/scala/StringReflect.scala @@ -1,9 +1,11 @@ /** * Copyright (C) 2009-2010 Scalable Solutions AB */ + package se.scalablesolutions.akka.spring object StringReflect { + /** * Implicit conversion from String to StringReflect. */ @@ -15,10 +17,9 @@ object StringReflect { * @author michaelkober */ class StringReflect(val self: String) { + if (self == null || self == "") throw new IllegalArgumentException("Class name can't be null or empty string [" + self + "]") def toClass[T <: AnyRef]: Class[T] = { val clazz = Class.forName(self) clazz.asInstanceOf[Class[T]] } -} - - +} \ No newline at end of file diff --git a/akka-spring/src/main/scala/TypedActorFactoryBean.scala b/akka-spring/src/main/scala/TypedActorFactoryBean.scala index 0e2848f8d6..7ba4cf5061 100644 --- a/akka-spring/src/main/scala/TypedActorFactoryBean.scala +++ b/akka-spring/src/main/scala/TypedActorFactoryBean.scala @@ -13,6 +13,7 @@ import reflect.BeanProperty import org.springframework.beans.BeanWrapperImpl import org.springframework.beans.BeanWrapper import org.springframework.beans.BeanUtils +import org.springframework.beans.BeansException import org.springframework.beans.factory.BeanFactory import org.springframework.beans.factory.config.AbstractFactoryBean import org.springframework.context.{ApplicationContext,ApplicationContextAware} @@ -24,6 +25,15 @@ import se.scalablesolutions.akka.config.ScalaConfig.{ShutdownCallback, RestartCa import se.scalablesolutions.akka.dispatch.MessageDispatcher import se.scalablesolutions.akka.util.{Logging, Duration} +/** + * Exception to use when something goes wrong during bean creation. + * + * @author Johan Rask + */ +class AkkaBeansException(message: String, cause:Throwable) extends BeansException(message, cause) { + def this(message: String) = this(message, null) +} + /** * Factory bean for typed actors. * @@ -123,16 +133,22 @@ class TypedActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging wit ref } - private[akka] def create(argList: String) : AnyRef = argList match { - case "ri" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), createConfig.makeRemote(host, port)) - case "i" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), createConfig) - case "id" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), createConfig.dispatcher(dispatcherInstance)) - case "rid" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), - createConfig.makeRemote(host, port).dispatcher(dispatcherInstance)) - // case "rd" => TypedActor.newInstance(target.toClass, createConfig.makeRemote(host, port).dispatcher(dispatcherInstance)) - // case "r" => TypedActor.newInstance(target.toClass, createConfig.makeRemote(host, port)) - // case "d" => TypedActor.newInstance(target.toClass, createConfig.dispatcher(dispatcherInstance)) - case _ => throw new AkkaBeansException("Illegal configuration argument list for TypedActor Spring bean [" + argList + "]") + private[akka] def create(argList: String): AnyRef = { + if (interface == null || interface == "") throw new AkkaBeansException( + "The 'interface' part of the 'akka:actor' element in the Spring config file can't be null or empty string") + if (target == null || target == "") throw new AkkaBeansException( + "The 'target' part of the 'akka:actor' element in the Spring config file can't be null or empty string") + argList match { + case "ri" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), createConfig.makeRemote(host, port)) + case "i" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), createConfig) + case "id" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), createConfig.dispatcher(dispatcherInstance)) + case "rid" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), + createConfig.makeRemote(host, port).dispatcher(dispatcherInstance)) + case _ => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), createConfig) + // case "rd" => TypedActor.newInstance(target.toClass, createConfig.makeRemote(host, port).dispatcher(dispatcherInstance)) + // case "r" => TypedActor.newInstance(target.toClass, createConfig.makeRemote(host, port)) + // case "d" => TypedActor.newInstance(target.toClass, createConfig.dispatcher(dispatcherInstance)) + } } private[akka] def createConfig: TypedActorConfiguration = { @@ -143,7 +159,7 @@ class TypedActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging wit config } - def newInstanceFor[T <: AnyRef](clazz: Class[T]) : T = { + def newInstanceFor[T <: AnyRef](clazz: Class[T]): T = { var ref = clazz.newInstance().asInstanceOf[T] postConstruct(setProperties(ref)) hasSetDependecies = true @@ -154,11 +170,16 @@ class TypedActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging wit private[akka] def hasInterface = (interface != null) && (!interface.isEmpty) - private[akka] def hasRestartCallbacks = ((pre != null) && !pre.isEmpty) || ((post != null) && !post.isEmpty) + private[akka] def hasRestartCallbacks = + ((pre != null) && !pre.isEmpty) || + ((post != null) && !post.isEmpty) private[akka] def hasShutdownCallback = ((shutdown != null) && !shutdown.isEmpty) - private[akka] def hasDispatcher = (dispatcher != null) && (dispatcher.dispatcherType != null) && (!dispatcher.dispatcherType.isEmpty) + private[akka] def hasDispatcher = + (dispatcher != null) && + (dispatcher.dispatcherType != null) && + (!dispatcher.dispatcherType.isEmpty) private[akka] def dispatcherInstance: MessageDispatcher = { import DispatcherFactoryBean._ diff --git a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/Pojo.java b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/Pojo.java index 04995b75c8..72fb8cb895 100644 --- a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/Pojo.java +++ b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/Pojo.java @@ -2,38 +2,41 @@ package se.scalablesolutions.akka.spring; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; + import javax.annotation.PreDestroy; import javax.annotation.PostConstruct; -public class Pojo implements PojoInf,ApplicationContextAware { +import se.scalablesolutions.akka.actor.*; + +public class Pojo extends TypedActor implements PojoInf, ApplicationContextAware { private String string; - private boolean gotApplicationContext = false; - private boolean postConstructInvoked = false; - - public boolean gotApplicationContext() { - return gotApplicationContext; - } - public void setApplicationContext(ApplicationContext context) { - gotApplicationContext = true; - } + private boolean gotApplicationContext = false; + private boolean postConstructInvoked = false; + + public boolean gotApplicationContext() { + return gotApplicationContext; + } + + public void setApplicationContext(ApplicationContext context) { + gotApplicationContext = true; + } - public void setString(String s) { - string = s; - } + public void setString(String s) { + string = s; + } public String getString() { - return string; - } - - @PostConstruct - public void create() { - postConstructInvoked = true; - } + return string; + } - public boolean isPostConstructInvoked() { - return postConstructInvoked; + @PostConstruct + public void create() { + postConstructInvoked = true; + } + + public boolean isPostConstructInvoked() { + return postConstructInvoked; + } } - - } diff --git a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/PojoInf.java b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/PojoInf.java index 70d64245db..0189d5ec4a 100644 --- a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/PojoInf.java +++ b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/PojoInf.java @@ -5,10 +5,10 @@ import javax.annotation.PostConstruct; public interface PojoInf { - public String getString(); - public boolean gotApplicationContext(); - public boolean isPostConstructInvoked(); - - @PostConstruct - public void create(); - } + public String getString(); + public boolean gotApplicationContext(); + public boolean isPostConstructInvoked(); + + @PostConstruct + public void create(); +} diff --git a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleRoute.java b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleRoute.java index 3865ea1615..84377ee3d6 100644 --- a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleRoute.java +++ b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleRoute.java @@ -8,5 +8,4 @@ public class SampleRoute extends RouteBuilder { public void configure() throws Exception { from("direct:test").to("active-object:sample?method=foo"); } - } diff --git a/akka-spring/src/test/resources/appContext.xml b/akka-spring/src/test/resources/appContext.xml index e9a651b735..ba2c243558 100644 --- a/akka-spring/src/test/resources/appContext.xml +++ b/akka-spring/src/test/resources/appContext.xml @@ -7,27 +7,37 @@ http://www.akkasource.org/schema/akka http://scalablesolutions.se/akka/akka-0.10.xsd"> - - - + + + - + + + + + + + + diff --git a/akka-spring/src/test/resources/appContextCamelServiceCustom.xml b/akka-spring/src/test/resources/appContextCamelServiceCustom.xml index ba18a325d0..7150465e7c 100644 --- a/akka-spring/src/test/resources/appContextCamelServiceCustom.xml +++ b/akka-spring/src/test/resources/appContextCamelServiceCustom.xml @@ -20,6 +20,8 @@ http://camel.apache.org/schema/spring/camel-spring.xsd"> - - + diff --git a/akka-spring/src/test/resources/failing-appContext.xml b/akka-spring/src/test/resources/failing-appContext.xml index 1acab0e830..bc970b6036 100644 --- a/akka-spring/src/test/resources/failing-appContext.xml +++ b/akka-spring/src/test/resources/failing-appContext.xml @@ -7,15 +7,15 @@ http://www.akkasource.org/schema/akka classpath:se/scalablesolutions/akka/spring/akka-0.10.xsd"> - - - - - - - + + + + + + + \ No newline at end of file diff --git a/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala b/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala index edcf2fa995..ff246891c9 100644 --- a/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala +++ b/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala @@ -17,9 +17,9 @@ class CamelServiceSpringFeatureTest extends FeatureSpec with BeforeAndAfterEach ActorRegistry.shutdownAll } +/* feature("start CamelService from Spring application context") { import CamelContextManager._ - scenario("with a custom CamelContext and access a registered typed actor") { val appctx = new ClassPathXmlApplicationContext("/appContextCamelServiceCustom.xml") assert(context.isInstanceOf[SpringCamelContext]) @@ -40,4 +40,5 @@ class CamelServiceSpringFeatureTest extends FeatureSpec with BeforeAndAfterEach appctx.close } } +*/ } diff --git a/akka-spring/src/test/scala/ActiveObjectBeanDefinitionParserTest.scala b/akka-spring/src/test/scala/TypedActorBeanDefinitionParserTest.scala similarity index 100% rename from akka-spring/src/test/scala/ActiveObjectBeanDefinitionParserTest.scala rename to akka-spring/src/test/scala/TypedActorBeanDefinitionParserTest.scala diff --git a/akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala b/akka-spring/src/test/scala/TypedActorFactoryBeanTest.scala similarity index 90% rename from akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala rename to akka-spring/src/test/scala/TypedActorFactoryBeanTest.scala index c65344cd9e..9fb500240b 100644 --- a/akka-spring/src/test/scala/ActiveObjectFactoryBeanTest.scala +++ b/akka-spring/src/test/scala/TypedActorFactoryBeanTest.scala @@ -48,34 +48,17 @@ class TypedActorFactoryBeanTest extends Spec with ShouldMatchers { assert(bean.getObjectType == classOf[String]) } - it("should create a proxy of type ResourceEditor") { - val bean = new TypedActorFactoryBean() - // we must have a java class here - bean.setTarget("org.springframework.core.io.ResourceEditor") - val entries = new PropertyEntries() - val entry = new PropertyEntry() - entry.name = "source" - entry.value = "sourceBeanIsAString" - entries.add(entry) - bean.setProperty(entries) - assert(bean.getObjectType == classOf[ResourceEditor]) - - // Check that we have injected the depencency correctly - val target:ResourceEditor = bean.createInstance.asInstanceOf[ResourceEditor] - assert(target.getSource === entry.value) - } - +/* it("should create an application context and verify dependency injection") { var ctx = new ClassPathXmlApplicationContext("appContext.xml"); val target:ResourceEditor = ctx.getBean("bean").asInstanceOf[ResourceEditor] assert(target.getSource === "someString") - - val pojoInf = ctx.getBean("pojoInf").asInstanceOf[PojoInf]; - println("pojoInf = " + pojoInf.getString) - Thread.sleep(200) - assert(pojoInf.isPostConstructInvoked) - assert(pojoInf.getString == "akka rocks") - assert(pojoInf.gotApplicationContext) + + val pojoInf = ctx.getBean("pojoInf").asInstanceOf[PojoInf]; + Thread.sleep(200) + assert(pojoInf.isPostConstructInvoked) + assert(pojoInf.getString == "akka rocks") + assert(pojoInf.gotApplicationContext) } it("should stop the created typed actor when scope is singleton and the context is closed") { @@ -93,5 +76,27 @@ class TypedActorFactoryBeanTest extends Spec with ShouldMatchers { ctx.close assert(!target.down) } + */ } } + +/* + // ------ NOTE: Can't work now when we only support POJO with interface ----- + + it("should create a proxy of type ResourceEditor") { + val bean = new TypedActorFactoryBean() + // we must have a java class here + bean.setTarget("org.springframework.core.io.ResourceEditor") + val entries = new PropertyEntries() + val entry = new PropertyEntry() + entry.name = "source" + entry.value = "sourceBeanIsAString" + entries.add(entry) + bean.setProperty(entries) + assert(bean.getObjectType == classOf[ResourceEditor]) + + // Check that we have injected the depencency correctly + val target:ResourceEditor = bean.createInstance.asInstanceOf[ResourceEditor] + assert(target.getSource === entry.value) + } +*/ From ed2d9d67ffb27386290c5e84179ef280d372cc1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bon=C3=A9r?= Date: Wed, 28 Jul 2010 00:58:52 +0200 Subject: [PATCH 065/188] Implemented swapping TypedActor instance on restart --- akka-core/src/main/scala/actor/ActorRef.scala | 36 ++++++++++++------- .../src/main/scala/actor/TypedActor.scala | 13 ++++++- .../akka/actor/SamplePojo.java | 1 - .../akka/actor/SamplePojoImpl.java | 11 +----- .../test/scala/TypedActorLifecycleSpec.scala | 32 ++++++++--------- 5 files changed, 51 insertions(+), 42 deletions(-) diff --git a/akka-core/src/main/scala/actor/ActorRef.scala b/akka-core/src/main/scala/actor/ActorRef.scala index 3d01ec7886..cb68590422 100644 --- a/akka-core/src/main/scala/actor/ActorRef.scala +++ b/akka-core/src/main/scala/actor/ActorRef.scala @@ -1022,20 +1022,14 @@ sealed class LocalActorRef private[akka]( guard.withGuard { lifeCycle match { case Some(LifeCycle(Temporary, _, _)) => shutDownTemporaryActor(this) - case _ => + case _ => // either permanent or none where default is permanent Actor.log.info("Restarting actor [%s] configured as PERMANENT.", id) Actor.log.debug("Restarting linked actors for actor [%s].", id) restartLinkedActors(reason, maxNrOfRetries, withinTimeRange) Actor.log.debug("Invoking 'preRestart' for failed actor instance [%s].", id) - failedActor.preRestart(reason) - nullOutActorRefReferencesFor(failedActor) - val freshActor = newActor - freshActor.init - freshActor.initTransactionalState - actorInstance.set(freshActor) - Actor.log.debug("Invoking 'postRestart' for new actor instance [%s].", id) - freshActor.postRestart(reason) + if (isTypedActorDispatcher(failedActor)) restartTypedActorDispatcher(failedActor, reason) + else restartActor(failedActor, reason) _isBeingRestarted = false } } @@ -1072,6 +1066,24 @@ sealed class LocalActorRef private[akka]( // ========= PRIVATE FUNCTIONS ========= + private def isTypedActorDispatcher(a: Actor): Boolean = a.isInstanceOf[Dispatcher] + + private def restartTypedActorDispatcher(failedActor: Actor, reason: Throwable) = { + failedActor.preRestart(reason) + failedActor.postRestart(reason) + } + + private def restartActor(failedActor: Actor, reason: Throwable) = { + failedActor.preRestart(reason) + nullOutActorRefReferencesFor(failedActor) + val freshActor = newActor + freshActor.init + freshActor.initTransactionalState + actorInstance.set(freshActor) + Actor.log.debug("Invoking 'postRestart' for new actor instance [%s].", id) + freshActor.postRestart(reason) + } + private def spawnButDoNotStart[T <: Actor: Manifest]: ActorRef = guard.withGuard { val actorRef = Actor.actorOf(manifest[T].erasure.asInstanceOf[Class[T]].newInstance) if (!dispatcher.isInstanceOf[ThreadBasedDispatcher]) actorRef.dispatcher = dispatcher @@ -1112,7 +1124,8 @@ sealed class LocalActorRef private[akka]( createNewTransactionSet } else oldTxSet Actor.log.ifTrace("Joining transaction set [" + currentTxSet + - "];\n\tactor " + toString + "\n\twith message [" + message + "]") + "];\n\tactor " + toString + + "\n\twith message [" + message + "]") val mtx = ThreadLocalTransaction.getThreadLocalTransaction if ((mtx eq null) || mtx.getStatus.isDead) currentTxSet.incParties else currentTxSet.incParties(mtx, 1) @@ -1152,8 +1165,7 @@ sealed class LocalActorRef private[akka]( new TransactionSetAbortedException("Transaction set has been aborted by another participant"), message, topLevelTransaction) case e: InterruptedException => {} // received message while actor is shutting down, ignore - case e => - handleExceptionInDispatch(e, message, topLevelTransaction) + case e => handleExceptionInDispatch(e, message, topLevelTransaction) } finally { clearTransaction if (topLevelTransaction) clearTransactionSet diff --git a/akka-core/src/main/scala/actor/TypedActor.scala b/akka-core/src/main/scala/actor/TypedActor.scala index 971551620e..7d41775b60 100644 --- a/akka-core/src/main/scala/actor/TypedActor.scala +++ b/akka-core/src/main/scala/actor/TypedActor.scala @@ -19,7 +19,7 @@ import org.codehaus.aspectwerkz.proxy.Proxy import org.codehaus.aspectwerkz.annotation.{Aspect, Around} import java.net.InetSocketAddress -import java.lang.reflect.{InvocationTargetException, Method} +import java.lang.reflect.{InvocationTargetException, Method, Field} import scala.reflect.BeanProperty @@ -729,6 +729,7 @@ private[akka] class Dispatcher(transactionalRequired: Boolean) extends Actor { private var context: Option[TypedActorContext] = None private var targetClass: Class[_] = _ @volatile private[akka] var targetInstance: TypedActor = _ + private var proxyDelegate: Field = _ private[actor] def initialize( targetClass: Class[_], targetInstance: TypedActor, proxy: AnyRef, ctx: Option[TypedActorContext]) = { @@ -740,6 +741,12 @@ private[akka] class Dispatcher(transactionalRequired: Boolean) extends Actor { this.targetInstance = targetInstance this.context = ctx + proxyDelegate = { + val field = proxy.getClass.getDeclaredField("DELEGATE_0") + field.setAccessible(true) + field + } + if (self.lifeCycle.isEmpty) self.lifeCycle = Some(LifeCycle(Permanent)) } @@ -766,6 +773,10 @@ private[akka] class Dispatcher(transactionalRequired: Boolean) extends Actor { override def preRestart(reason: Throwable) { crashedActorTl.set(this) targetInstance.preRestart(reason) + + // rewrite target instance in Dispatcher and AspectWerkz Proxy + targetInstance = TypedActor.newTypedActor(targetClass) + proxyDelegate.set(proxy, targetInstance) } override def postRestart(reason: Throwable) { diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojo.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojo.java index 2e3da4f038..ae47276ba6 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojo.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojo.java @@ -3,7 +3,6 @@ package se.scalablesolutions.akka.actor; import java.util.concurrent.CountDownLatch; public interface SamplePojo { - public CountDownLatch newCountdownLatch(int count); public String greet(String s); public String fail(); } \ No newline at end of file diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojoImpl.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojoImpl.java index b46a9f8fa4..d57232b629 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojoImpl.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SamplePojoImpl.java @@ -6,7 +6,7 @@ import java.util.concurrent.CountDownLatch; public class SamplePojoImpl extends TypedActor implements SamplePojo { - private CountDownLatch latch; + public static CountDownLatch latch = new CountDownLatch(1); public static boolean _pre = false; public static boolean _post = false; @@ -17,15 +17,6 @@ public class SamplePojoImpl extends TypedActor implements SamplePojo { _down = false; } - public SamplePojoImpl() { - latch = new CountDownLatch(1); - } - - public CountDownLatch newCountdownLatch(int count) { - latch = new CountDownLatch(count); - return latch; - } - public String greet(String s) { return "hello " + s; } diff --git a/akka-core/src/test/scala/TypedActorLifecycleSpec.scala b/akka-core/src/test/scala/TypedActorLifecycleSpec.scala index f17f50e9a5..02a5712410 100644 --- a/akka-core/src/test/scala/TypedActorLifecycleSpec.scala +++ b/akka-core/src/test/scala/TypedActorLifecycleSpec.scala @@ -10,40 +10,35 @@ import se.scalablesolutions.akka.actor.TypedActor._ import se.scalablesolutions.akka.config.{OneForOneStrategy, TypedActorConfigurator} import se.scalablesolutions.akka.config.JavaConfig._ +import java.util.concurrent.CountDownLatch + /** * @author Martin Krasser */ @RunWith(classOf[JUnitRunner]) class TypedActorLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAfterAll { -// var conf1: TypedActorConfigurator = _ -// var conf2: TypedActorConfigurator = _ - var conf3: TypedActorConfigurator = _ - var conf4: TypedActorConfigurator = _ + var conf1: TypedActorConfigurator = _ + var conf2: TypedActorConfigurator = _ override protected def beforeAll() = { val strategy = new RestartStrategy(new AllForOne(), 3, 1000, Array(classOf[Exception])) -// val comp1 = new Component(classOf[SamplePojoAnnotated], classOf[SamplePojoAnnotatedImpl], new LifeCycle(new Permanent()), 1000) -// val comp2 = new Component(classOf[SamplePojoAnnotated], classOf[SamplePojoAnnotatedImpl], new LifeCycle(new Temporary()), 1000) val comp3 = new Component(classOf[SamplePojo], classOf[SamplePojoImpl], new LifeCycle(new Permanent()), 1000) val comp4 = new Component(classOf[SamplePojo], classOf[SamplePojoImpl], new LifeCycle(new Temporary()), 1000) -// conf1 = new TypedActorConfigurator().configure(strategy, Array(comp1)).supervise -// conf2 = new TypedActorConfigurator().configure(strategy, Array(comp2)).supervise - conf3 = new TypedActorConfigurator().configure(strategy, Array(comp3)).supervise - conf4 = new TypedActorConfigurator().configure(strategy, Array(comp4)).supervise + conf1 = new TypedActorConfigurator().configure(strategy, Array(comp3)).supervise + conf2 = new TypedActorConfigurator().configure(strategy, Array(comp4)).supervise } override protected def afterAll() = { -// conf1.stop -// conf2.stop - conf3.stop - conf4.stop + conf1.stop + conf2.stop } describe("TypedActor lifecycle management") { it("should restart supervised, non-annotated typed actor on failure") { SamplePojoImpl.reset - val obj = conf3.getInstance[SamplePojo](classOf[SamplePojo]) - val cdl = obj.newCountdownLatch(2) + val obj = conf1.getInstance[SamplePojo](classOf[SamplePojo]) + val cdl = new CountDownLatch(2) + SamplePojoImpl.latch = cdl assert(AspectInitRegistry.initFor(obj) ne null) try { obj.fail @@ -61,8 +56,9 @@ class TypedActorLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAft it("should shutdown supervised, non-annotated typed actor on failure") { SamplePojoImpl.reset - val obj = conf4.getInstance[SamplePojo](classOf[SamplePojo]) - val cdl = obj.newCountdownLatch(1) + val obj = conf2.getInstance[SamplePojo](classOf[SamplePojo]) + val cdl = new CountDownLatch(1) + SamplePojoImpl.latch = cdl assert(AspectInitRegistry.initFor(obj) ne null) try { obj.fail From 1bd2e6c664ce1ed6228bffeb52c2d71d67dced9a Mon Sep 17 00:00:00 2001 From: rossputin Date: Wed, 28 Jul 2010 10:21:41 +0100 Subject: [PATCH 066/188] match readme to scaladoc in sample --- akka-samples/akka-sample-chat/README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/akka-samples/akka-sample-chat/README b/akka-samples/akka-sample-chat/README index 475cb60015..fec39724e1 100644 --- a/akka-samples/akka-sample-chat/README +++ b/akka-samples/akka-sample-chat/README @@ -18,8 +18,8 @@ Then to run the sample: - Run 'sbt console' to start up a REPL (interpreter). 4. In the first REPL you get execute: - scala> import sample.chat._ - - scala> import se.scalablesolutions.akka.actor.Actor - - scala> val chatService = Actor.actorOf[ChatService].start + - scala> import se.scalablesolutions.akka.actor.Actor._ + - scala> val chatService = actorOf[ChatService].start 5. In the second REPL you get execute: - scala> import sample.chat._ - scala> Runner.run From d6b728d2980ec1c21cccbc1750787d288b95a092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bon=C3=A9r?= Date: Wed, 28 Jul 2010 13:08:24 +0200 Subject: [PATCH 067/188] Initial draft of UntypedActor for Java API --- akka-core/src/main/scala/actor/Actor.scala | 10 +++--- .../src/main/scala/actor/TypedActor.scala | 14 ++++---- .../src/main/scala/actor/UntypedActor.scala | 34 +++++++++++++++++++ .../akka/actor/TestUntypedActor.java | 9 +++++ 4 files changed, 55 insertions(+), 12 deletions(-) create mode 100644 akka-core/src/main/scala/actor/UntypedActor.scala create mode 100644 akka-core/src/test/java/se/scalablesolutions/akka/actor/TestUntypedActor.java diff --git a/akka-core/src/main/scala/actor/Actor.scala b/akka-core/src/main/scala/actor/Actor.scala index b99ce22a93..1de3997c12 100644 --- a/akka-core/src/main/scala/actor/Actor.scala +++ b/akka-core/src/main/scala/actor/Actor.scala @@ -436,12 +436,12 @@ trait Actor extends Logging { } private val lifeCycles: Receive = { - case HotSwap(code) => become(code) - case Exit(dead, reason) => self.handleTrapExit(dead, reason) - case Link(child) => self.link(child) - case Unlink(child) => self.unlink(child) + case HotSwap(code) => become(code) + case Exit(dead, reason) => self.handleTrapExit(dead, reason) + case Link(child) => self.link(child) + case Unlink(child) => self.unlink(child) case UnlinkAndStop(child) => self.unlink(child); child.stop - case Restart(reason) => throw reason + case Restart(reason) => throw reason } } diff --git a/akka-core/src/main/scala/actor/TypedActor.scala b/akka-core/src/main/scala/actor/TypedActor.scala index 7d41775b60..de204bab5b 100644 --- a/akka-core/src/main/scala/actor/TypedActor.scala +++ b/akka-core/src/main/scala/actor/TypedActor.scala @@ -714,7 +714,7 @@ private[akka] sealed class TypedActorAspect { object Dispatcher { val ZERO_ITEM_CLASS_ARRAY = Array[Class[_]]() val ZERO_ITEM_OBJECT_ARRAY = Array[Object]() - var crashedActorTl:ThreadLocal[Dispatcher] = new ThreadLocal(); +// var crashedActorTl: ThreadLocal[Dispatcher] = new ThreadLocal(); } /** @@ -771,7 +771,7 @@ private[akka] class Dispatcher(transactionalRequired: Boolean) extends Actor { } override def preRestart(reason: Throwable) { - crashedActorTl.set(this) +// crashedActorTl.set(this) targetInstance.preRestart(reason) // rewrite target instance in Dispatcher and AspectWerkz Proxy @@ -786,11 +786,11 @@ private[akka] class Dispatcher(transactionalRequired: Boolean) extends Actor { override def init { // Get the crashed dispatcher from thread local and intitialize this actor with the // contents of the old dispatcher - val oldActor = crashedActorTl.get - if (oldActor != null) { - initialize(oldActor.targetClass, oldActor.targetInstance, oldActor.proxy, oldActor.context) - crashedActorTl.set(null) - } +// val oldActor = crashedActorTl.get +// if (oldActor != null) { +// initialize(oldActor.targetClass, oldActor.targetInstance, oldActor.proxy, oldActor.context) +// crashedActorTl.set(null) +// } } override def shutdown { diff --git a/akka-core/src/main/scala/actor/UntypedActor.scala b/akka-core/src/main/scala/actor/UntypedActor.scala new file mode 100644 index 0000000000..7e45dee40d --- /dev/null +++ b/akka-core/src/main/scala/actor/UntypedActor.scala @@ -0,0 +1,34 @@ +/** + * Copyright (C) 2009-2010 Scalable Solutions AB + */ + +package se.scalablesolutions.akka.actor + +/** + * FIXME: document + * + * @author Jonas Bonér + */ +abstract class UntypedActor extends Actor { + protected[akka] var context: Option[ActorContext] = None + + protected def receive = { + case msg => + if (context.isEmpty) { + val ctx = new ActorContext(self) + context = Some(ctx) + onReceive(msg, ctx) + } else onReceive(msg, context.get) + } + + def onReceive(message: Any, context: ActorContext): Unit +} + +/** + * FIXME: document + * + * @author Jonas Bonér + */ +class ActorContext(self: ActorRef) { + +} \ No newline at end of file diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/TestUntypedActor.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/TestUntypedActor.java new file mode 100644 index 0000000000..7a1d2982e9 --- /dev/null +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/TestUntypedActor.java @@ -0,0 +1,9 @@ +package se.scalablesolutions.akka.actor; + +import se.scalablesolutions.akka.actor.*; + +public class TestUntypedActor extends UntypedActor { + public void onReceive(Object message, ActorContext context) { + System.out.println("TestUntypedActor got " + message); + } +} \ No newline at end of file From cff8a7839dfaec1c0079cd84916ed7ad9e88b12f Mon Sep 17 00:00:00 2001 From: Debasish Ghosh Date: Thu, 29 Jul 2010 16:00:05 +0530 Subject: [PATCH 068/188] upgraded sjson to 0.7 --- .../json/sjson/0.7-2.8.0/sjson-0.7-2.8.0.jar | Bin 0 -> 179472 bytes .../json/sjson/0.7-2.8.0/sjson-0.7-2.8.0.pom | 9 +++++++++ project/build/AkkaProject.scala | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 embedded-repo/sjson/json/sjson/0.7-2.8.0/sjson-0.7-2.8.0.jar create mode 100644 embedded-repo/sjson/json/sjson/0.7-2.8.0/sjson-0.7-2.8.0.pom diff --git a/embedded-repo/sjson/json/sjson/0.7-2.8.0/sjson-0.7-2.8.0.jar b/embedded-repo/sjson/json/sjson/0.7-2.8.0/sjson-0.7-2.8.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..e8700f11d316f255d679d25d4ff09f327e3fae4f GIT binary patch literal 179472 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 z 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¥V1 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

(H42(0*h%2f(lZ+ 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 JIuio}0|309CM5s> literal 0 HcmV?d00001 diff --git a/embedded-repo/sjson/json/sjson/0.7-2.8.0/sjson-0.7-2.8.0.pom b/embedded-repo/sjson/json/sjson/0.7-2.8.0/sjson-0.7-2.8.0.pom new file mode 100644 index 0000000000..dfc9017dcf --- /dev/null +++ b/embedded-repo/sjson/json/sjson/0.7-2.8.0/sjson-0.7-2.8.0.pom @@ -0,0 +1,9 @@ + + + 4.0.0 + sjson.json + sjson + 0.7-2.8.0 + POM was created from install:install-file + diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 6dce71b7b3..916d92b71c 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -185,7 +185,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val servlet = "javax.servlet" % "servlet-api" % "2.5" % "compile" - lazy val sjson = "sjson.json" % "sjson" % "0.7-SNAPSHOT-2.8.0" % "compile" + lazy val sjson = "sjson.json" % "sjson" % "0.7-2.8.0" % "compile" lazy val slf4j = "org.slf4j" % "slf4j-api" % Slf4jVersion % "compile" lazy val slf4j_log4j = "org.slf4j" % "slf4j-log4j12" % Slf4jVersion % "compile" From 78f132443f88946fc6906c423c62ecd59f2782d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bon=C3=A9r?= Date: Thu, 29 Jul 2010 16:13:34 +0200 Subject: [PATCH 069/188] minor reformatting --- akka-core/src/main/scala/actor/TypedActor.scala | 4 +++- akka-core/src/main/scala/actor/UntypedActor.scala | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/akka-core/src/main/scala/actor/TypedActor.scala b/akka-core/src/main/scala/actor/TypedActor.scala index de204bab5b..f624daeb33 100644 --- a/akka-core/src/main/scala/actor/TypedActor.scala +++ b/akka-core/src/main/scala/actor/TypedActor.scala @@ -379,7 +379,9 @@ object TypedActor extends Logging { * Get the underlying dispatcher actor for the given Typed Actor. */ def actorFor(proxy: AnyRef): Option[ActorRef] = - ActorRegistry.actorsFor(classOf[Dispatcher]).find(a => a.actor.asInstanceOf[Dispatcher].proxy == proxy) + ActorRegistry + .actorsFor(classOf[Dispatcher]) + .find(a => a.actor.asInstanceOf[Dispatcher].proxy == proxy) /** * Links an other Typed Actor to this Typed Actor. diff --git a/akka-core/src/main/scala/actor/UntypedActor.scala b/akka-core/src/main/scala/actor/UntypedActor.scala index 7e45dee40d..81924886d9 100644 --- a/akka-core/src/main/scala/actor/UntypedActor.scala +++ b/akka-core/src/main/scala/actor/UntypedActor.scala @@ -29,6 +29,5 @@ abstract class UntypedActor extends Actor { * * @author Jonas Bonér */ -class ActorContext(self: ActorRef) { - +class ActorContext(val self: ActorRef) { } \ No newline at end of file From b15d8b872528adc4dcbb8232c5b15b215f2f43be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bon=C3=A9r?= Date: Thu, 29 Jul 2010 16:15:18 +0200 Subject: [PATCH 070/188] converted tabs to spaces --- .../src/main/scala/osgiExample.scala | 6 +- project/build/AkkaProject.scala | 130 +++++++++--------- project/plugins/Plugins.scala | 16 +-- 3 files changed, 76 insertions(+), 76 deletions(-) diff --git a/akka-samples/akka-sample-osgi/src/main/scala/osgiExample.scala b/akka-samples/akka-sample-osgi/src/main/scala/osgiExample.scala index 0cef797c47..3c233fdf1f 100644 --- a/akka-samples/akka-sample-osgi/src/main/scala/osgiExample.scala +++ b/akka-samples/akka-sample-osgi/src/main/scala/osgiExample.scala @@ -20,7 +20,7 @@ class Activator extends BundleActivator { } def stop(context: BundleContext) { - ActorRegistry.shutdownAll() + ActorRegistry.shutdownAll() println("Stopped the OSGi example.") } } @@ -28,6 +28,6 @@ class Activator extends BundleActivator { class EchoActor extends Actor { override def receive = { - case x => self reply x - } + case x => self reply x + } } diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 916d92b71c..03a91cbe6c 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -37,20 +37,20 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val dist = zipTask(allArtifacts, "dist", distName) dependsOn (`package`) describedAs("Zips up the distribution.") // ------------------------------------------------------------------------------------------------------------------- - // All repositories *must* go here! See ModuleConigurations below. + // All repositories *must* go here! See ModuleConigurations below. // ------------------------------------------------------------------------------------------------------------------- - object Repositories { - lazy val AkkaRepo = MavenRepository("Akka Repository", "http://scalablesolutions.se/akka/repository") - lazy val CodehausSnapshotRepo = MavenRepository("Codehaus Snapshots", "http://snapshots.repository.codehaus.org") - lazy val EmbeddedRepo = MavenRepository("Embedded Repo", (info.projectPath / "embedded-repo").asURL.toString) - lazy val FusesourceSnapshotRepo = MavenRepository("Fusesource Snapshots", "http://repo.fusesource.com/nexus/content/repositories/snapshots") - lazy val GuiceyFruitRepo = MavenRepository("GuiceyFruit Repo", "http://guiceyfruit.googlecode.com/svn/repo/releases/") - lazy val JBossRepo = MavenRepository("JBoss Repo", "https://repository.jboss.org/nexus/content/groups/public/") - lazy val JavaNetRepo = MavenRepository("java.net Repo", "http://download.java.net/maven/2") - lazy val SonatypeSnapshotRepo = MavenRepository("Sonatype OSS Repo", "http://oss.sonatype.org/content/repositories/releases") - lazy val SunJDMKRepo = MavenRepository("Sun JDMK Repo", "http://wp5.e-taxonomy.eu/cdmlib/mavenrepo") - } + object Repositories { + lazy val AkkaRepo = MavenRepository("Akka Repository", "http://scalablesolutions.se/akka/repository") + lazy val CodehausSnapshotRepo = MavenRepository("Codehaus Snapshots", "http://snapshots.repository.codehaus.org") + lazy val EmbeddedRepo = MavenRepository("Embedded Repo", (info.projectPath / "embedded-repo").asURL.toString) + lazy val FusesourceSnapshotRepo = MavenRepository("Fusesource Snapshots", "http://repo.fusesource.com/nexus/content/repositories/snapshots") + lazy val GuiceyFruitRepo = MavenRepository("GuiceyFruit Repo", "http://guiceyfruit.googlecode.com/svn/repo/releases/") + lazy val JBossRepo = MavenRepository("JBoss Repo", "https://repository.jboss.org/nexus/content/groups/public/") + lazy val JavaNetRepo = MavenRepository("java.net Repo", "http://download.java.net/maven/2") + lazy val SonatypeSnapshotRepo = MavenRepository("Sonatype OSS Repo", "http://oss.sonatype.org/content/repositories/releases") + lazy val SunJDMKRepo = MavenRepository("Sun JDMK Repo", "http://wp5.e-taxonomy.eu/cdmlib/mavenrepo") + } // ------------------------------------------------------------------------------------------------------------------- // ModuleConfigurations @@ -59,7 +59,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // Therefore, if repositories are defined, this must happen as def, not as val. // ------------------------------------------------------------------------------------------------------------------- - import Repositories._ + import Repositories._ lazy val atmosphereModuleConfig = ModuleConfiguration("org.atmosphere", SonatypeSnapshotRepo) lazy val grizzlyModuleConfig = ModuleConfiguration("com.sun.grizzly", JavaNetRepo) lazy val guiceyFruitModuleConfig = ModuleConfiguration("org.guiceyfruit", GuiceyFruitRepo) @@ -84,16 +84,16 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { lazy val ATMO_VERSION = "0.6" lazy val CAMEL_VERSION = "2.4.0" lazy val CASSANDRA_VERSION = "0.6.1" - lazy val DispatchVersion = "0.7.4" + lazy val DispatchVersion = "0.7.4" lazy val HAWTDISPATCH_VERSION = "1.0" - lazy val JacksonVersion = "1.2.1" + lazy val JacksonVersion = "1.2.1" lazy val JERSEY_VERSION = "1.2" lazy val LIFT_VERSION = "2.0-scala280-SNAPSHOT" lazy val MULTIVERSE_VERSION = "0.6-SNAPSHOT" lazy val SCALATEST_VERSION = "1.2-for-scala-2.8.0.final-SNAPSHOT" - lazy val Slf4jVersion = "1.6.0" + lazy val Slf4jVersion = "1.6.0" lazy val SPRING_VERSION = "3.0.3.RELEASE" - lazy val WerkzVersion = "2.2.1" + lazy val WerkzVersion = "2.2.1" // ------------------------------------------------------------------------------------------------------------------- // Dependencies @@ -317,9 +317,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { None } dependsOn(dist) describedAs("Run mvn install for artifacts in dist.") - // ------------------------------------------------------------------------------------------------------------------- - // akka-core subproject - // ------------------------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------------------- + // akka-core subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaCoreProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val aopalliance = Dependencies.aopalliance @@ -349,9 +349,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { val scalatest = Dependencies.scalatest } - // ------------------------------------------------------------------------------------------------------------------- - // akka-amqp subproject - // ------------------------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------------------- + // akka-amqp subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaAMQPProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val commons_io = Dependencies.commons_io @@ -363,9 +363,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { val scalatest = Dependencies.scalatest } - // ------------------------------------------------------------------------------------------------------------------- - // akka-http subproject - // ------------------------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------------------- + // akka-http subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaHttpProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val annotation = Dependencies.annotation @@ -392,17 +392,17 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { val scalatest = Dependencies.scalatest } - // ------------------------------------------------------------------------------------------------------------------- - // akka-camel subproject - // ------------------------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------------------- + // akka-camel subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaCamelProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val camel_core = Dependencies.camel_core } - // ------------------------------------------------------------------------------------------------------------------- - // akka-persistence subproject - // ------------------------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------------------- + // akka-persistence subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaPersistenceParentProject(info: ProjectInfo) extends ParentProject(info) { lazy val akka_persistence_common = project("akka-persistence-common", "akka-persistence-common", @@ -415,17 +415,17 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { new AkkaCassandraProject(_), akka_persistence_common) } - // ------------------------------------------------------------------------------------------------------------------- - // akka-persistence-common subproject - // ------------------------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------------------- + // akka-persistence-common subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaPersistenceCommonProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val commons_pool = Dependencies.commons_pool val thrift = Dependencies.thrift } - // ------------------------------------------------------------------------------------------------------------------- - // akka-persistence-redis subproject - // ------------------------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------------------- + // akka-persistence-redis subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaRedisProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val commons_codec = Dependencies.commons_codec @@ -434,9 +434,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { override def testOptions = TestFilter((name: String) => name.endsWith("Test")) :: Nil } - // ------------------------------------------------------------------------------------------------------------------- - // akka-persistence-mongo subproject - // ------------------------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------------------- + // akka-persistence-mongo subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaMongoProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val mongo = Dependencies.mongo @@ -444,9 +444,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { override def testOptions = TestFilter((name: String) => name.endsWith("Test")) :: Nil } - // ------------------------------------------------------------------------------------------------------------------- - // akka-persistence-cassandra subproject - // ------------------------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------------------- + // akka-persistence-cassandra subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaCassandraProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val cassandra = Dependencies.cassandra @@ -463,15 +463,15 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { override def testOptions = TestFilter((name: String) => name.endsWith("Test")) :: Nil } - // ------------------------------------------------------------------------------------------------------------------- - // akka-kernel subproject - // ------------------------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------------------- + // akka-kernel subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaKernelProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) - // ------------------------------------------------------------------------------------------------------------------- - // akka-spring subproject - // ------------------------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------------------- + // akka-spring subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaSpringProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val spring_beans = Dependencies.spring_beans @@ -483,9 +483,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { val scalatest = Dependencies.scalatest } - // ------------------------------------------------------------------------------------------------------------------- - // akka-jta subproject - // ------------------------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------------------- + // akka-jta subproject + // ------------------------------------------------------------------------------------------------------------------- class AkkaJTAProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val atomikos_transactions = Dependencies.atomikos_transactions @@ -495,9 +495,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { //val atomikos_transactions_util = "com.atomikos" % "transactions-util" % "3.2.3" % "compile" } - // ------------------------------------------------------------------------------------------------------------------- - // OSGi stuff - // ------------------------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------------------- + // OSGi stuff + // ------------------------------------------------------------------------------------------------------------------- class AkkaOSGiParentProject(info: ProjectInfo) extends ParentProject(info) { lazy val akka_osgi_dependencies_bundle = project("akka-osgi-dependencies-bundle", "akka-osgi-dependencies-bundle", @@ -587,9 +587,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { override def artifacts = Set.empty } - // ------------------------------------------------------------------------------------------------------------------- - // Test - // ------------------------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------------------- + // Test + // ------------------------------------------------------------------------------------------------------------------- class AkkaTypedActorTestProject(info: ProjectInfo) extends DefaultProject(info) { // testing @@ -597,9 +597,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { val jmock = "org.jmock" % "jmock" % "2.4.0" % "test" } - // ------------------------------------------------------------------------------------------------------------------- - // Examples - // ------------------------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------------------- + // Examples + // ------------------------------------------------------------------------------------------------------------------- class AkkaSampleAntsProject(info: ProjectInfo) extends DefaultSpdeProject(info) with CodeFellowPlugin { // val scalaToolsSnapshots = ScalaToolsSnapshots @@ -682,9 +682,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { new AkkaSampleOSGiProject(_), akka_core) } - // ------------------------------------------------------------------------------------------------------------------- - // Helpers - // ------------------------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------------------------- + // Helpers + // ------------------------------------------------------------------------------------------------------------------- def removeDupEntries(paths: PathFinder) = Path.lazyPathFinder { diff --git a/project/plugins/Plugins.scala b/project/plugins/Plugins.scala index f0332505da..b66ee5267e 100644 --- a/project/plugins/Plugins.scala +++ b/project/plugins/Plugins.scala @@ -3,13 +3,13 @@ import sbt._ class Plugins(info: ProjectInfo) extends PluginDefinition(info) { // ------------------------------------------------------------------------------------------------------------------- - // All repositories *must* go here! See ModuleConigurations below. + // All repositories *must* go here! See ModuleConigurations below. // ------------------------------------------------------------------------------------------------------------------- - object Repositories { - lazy val AquteRepo = "aQute Maven Repository" at "http://www.aqute.biz/repo" - lazy val DatabinderRepo = "Databinder Repository" at "http://databinder.net/repo" - lazy val EmbeddedRepo = "Embedded Repo" at (info.projectPath / "embedded-repo").asURL.toString - } + object Repositories { + lazy val AquteRepo = "aQute Maven Repository" at "http://www.aqute.biz/repo" + lazy val DatabinderRepo = "Databinder Repository" at "http://databinder.net/repo" + lazy val EmbeddedRepo = "Embedded Repo" at (info.projectPath / "embedded-repo").asURL.toString + } // ------------------------------------------------------------------------------------------------------------------- // ModuleConfigurations @@ -17,8 +17,8 @@ class Plugins(info: ProjectInfo) extends PluginDefinition(info) { // must be resolved from a ModuleConfiguration. This will result in a significant acceleration of the update action. // Therefore, if repositories are defined, this must happen as def, not as val. // ------------------------------------------------------------------------------------------------------------------- - import Repositories._ - lazy val aquteModuleConfig = ModuleConfiguration("biz.aQute", AquteRepo) + import Repositories._ + lazy val aquteModuleConfig = ModuleConfiguration("biz.aQute", AquteRepo) lazy val codeFellowModuleConfig = ModuleConfiguration("de.tuxed", EmbeddedRepo) lazy val spdeModuleConfig = ModuleConfiguration("us.technically.spde", DatabinderRepo) From 29036130980e8dd6cb1303282409554a87638bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bon=C3=A9r?= Date: Thu, 29 Jul 2010 17:29:51 +0200 Subject: [PATCH 071/188] removed trailing whitespace --- akka-amqp/src/main/scala/AMQP.scala | 4 +- akka-amqp/src/main/scala/ConsumerActor.scala | 2 +- .../scala/FaultTolerantChannelActor.scala | 4 +- akka-amqp/src/main/scala/ProducerActor.scala | 2 +- akka-amqp/src/main/scala/RpcClientActor.scala | 2 +- akka-amqp/src/main/scala/RpcServerActor.scala | 2 +- .../scala/AMQPConnectionRecoveryTest.scala | 2 +- .../AMQPConsumerChannelRecoveryTest.scala | 2 +- .../AMQPConsumerConnectionRecoveryTest.scala | 2 +- .../AMQPConsumerManualAcknowledgeTest.scala | 2 +- .../test/scala/AMQPConsumerMessageTest.scala | 4 +- .../AMQPProducerChannelRecoveryTest.scala | 2 +- .../AMQPProducerConnectionRecoveryTest.scala | 2 +- .../test/scala/AMQPProducerMessageTest.scala | 4 +- .../test/scala/AMQPRpcClientServerTest.scala | 2 +- akka-amqp/src/test/scala/AMQPTest.scala | 2 +- akka-camel/src/main/scala/CamelService.scala | 2 +- akka-camel/src/main/scala/Consumer.scala | 2 +- .../main/scala/component/ActorComponent.scala | 2 +- .../test/scala/CamelServiceFeatureTest.scala | 2 +- .../src/test/scala/ProducerFeatureTest.scala | 2 +- .../scala/component/ActorProducerTest.scala | 2 +- akka-core/src/main/scala/actor/Actor.scala | 2 +- akka-core/src/main/scala/actor/ActorRef.scala | 38 ++++++------ .../src/main/scala/actor/ActorRegistry.scala | 4 +- .../scala/actor/SerializationProtocol.scala | 2 +- .../src/main/scala/actor/Supervisor.scala | 2 +- .../src/main/scala/actor/TypedActor.scala | 62 +++++++++---------- .../src/main/scala/actor/UntypedActor.scala | 8 +-- .../scala/config/TypedActorConfigurator.scala | 2 +- .../config/TypedActorGuiceConfigurator.scala | 4 +- .../ExecutorBasedEventDrivenDispatcher.scala | 2 +- ...sedEventDrivenWorkStealingDispatcher.scala | 4 +- .../main/scala/dispatch/HawtDispatcher.scala | 4 +- ...sedSingleThreadEventDrivenDispatcher.scala | 2 +- .../src/main/scala/remote/RemoteServer.scala | 12 ++-- akka-core/src/main/scala/stm/JTA.scala | 4 +- .../main/scala/stm/TransactionFactory.scala | 2 +- .../scala/stm/TransactionManagement.scala | 10 +-- .../NestedTransactionalTypedActorSpec.scala | 2 +- .../test/scala/actor/ReceiveTimeoutSpec.scala | 2 +- ...artNestedTransactionalTypedActorSpec.scala | 26 ++++---- .../RestartTransactionalTypedActorSpec.scala | 2 +- .../src/test/scala/actor/SchedulerSpec.scala | 2 +- .../scala/actor/SupervisorHierarchySpec.scala | 8 +-- .../actor/TransactionalTypedActorSpec.scala | 2 +- .../scala/actor/TypedActorContextSpec.scala | 4 +- .../scala/actor/TypedActorLifecycleSpec.scala | 2 +- .../src/test/scala/routing/RoutingSpec.scala | 2 +- .../SerializableTypeClassActorSpec.scala | 2 +- akka-core/src/test/scala/stm/RefSpec.scala | 2 +- .../src/test/scala/tickets/Proof001Spec.scala | 2 +- .../src/main/scala/Actors.scala | 2 +- .../src/test/scala/HttpConcurrencyTest.scala | 2 +- .../src/main/scala/akka/SimpleService.scala | 2 +- .../src/main/scala/osgiExample.scala | 2 +- .../src/main/scala/StringReflect.scala | 6 +- .../main/scala/TypedActorFactoryBean.scala | 14 ++--- .../scala/TypedActorFactoryBeanTest.scala | 2 +- project/build/AkkaProject.scala | 6 +- project/plugins/Plugins.scala | 2 +- 61 files changed, 156 insertions(+), 156 deletions(-) diff --git a/akka-amqp/src/main/scala/AMQP.scala b/akka-amqp/src/main/scala/AMQP.scala index 8605401dbd..0bfbd93063 100644 --- a/akka-amqp/src/main/scala/AMQP.scala +++ b/akka-amqp/src/main/scala/AMQP.scala @@ -136,8 +136,8 @@ object AMQP { def toBinary(t: T): Array[Byte] } - + case class RpcClientSerializer[O,I](toBinary: ToBinary[O], fromBinary: FromBinary[I]) - + case class RpcServerSerializer[I,O](fromBinary: FromBinary[I], toBinary: ToBinary[O]) } diff --git a/akka-amqp/src/main/scala/ConsumerActor.scala b/akka-amqp/src/main/scala/ConsumerActor.scala index 26d1ac00db..d394e9d997 100644 --- a/akka-amqp/src/main/scala/ConsumerActor.scala +++ b/akka-amqp/src/main/scala/ConsumerActor.scala @@ -14,7 +14,7 @@ import java.lang.Throwable private[amqp] class ConsumerActor(consumerParameters: ConsumerParameters) extends FaultTolerantChannelActor(consumerParameters.exchangeParameters, consumerParameters.channelParameters) { - + import consumerParameters._ import exchangeParameters._ diff --git a/akka-amqp/src/main/scala/FaultTolerantChannelActor.scala b/akka-amqp/src/main/scala/FaultTolerantChannelActor.scala index 40bcd5de57..5ecae4c6d3 100644 --- a/akka-amqp/src/main/scala/FaultTolerantChannelActor.scala +++ b/akka-amqp/src/main/scala/FaultTolerantChannelActor.scala @@ -14,7 +14,7 @@ import se.scalablesolutions.akka.amqp.AMQP.{ExchangeParameters, ChannelParameter abstract private[amqp] class FaultTolerantChannelActor( exchangeParameters: ExchangeParameters, channelParameters: Option[ChannelParameters]) extends Actor { - + import exchangeParameters._ protected[amqp] var channel: Option[Channel] = None @@ -104,4 +104,4 @@ abstract private[amqp] class FaultTolerantChannelActor( } override def shutdown = closeChannel -} \ No newline at end of file +} diff --git a/akka-amqp/src/main/scala/ProducerActor.scala b/akka-amqp/src/main/scala/ProducerActor.scala index db290a5ac1..48a6be0a94 100644 --- a/akka-amqp/src/main/scala/ProducerActor.scala +++ b/akka-amqp/src/main/scala/ProducerActor.scala @@ -9,7 +9,7 @@ import se.scalablesolutions.akka.amqp.AMQP.ProducerParameters private[amqp] class ProducerActor(producerParameters: ProducerParameters) extends FaultTolerantChannelActor(producerParameters.exchangeParameters, producerParameters.channelParameters) { - + import producerParameters._ import exchangeParameters._ diff --git a/akka-amqp/src/main/scala/RpcClientActor.scala b/akka-amqp/src/main/scala/RpcClientActor.scala index ba85005777..2935982a67 100644 --- a/akka-amqp/src/main/scala/RpcClientActor.scala +++ b/akka-amqp/src/main/scala/RpcClientActor.scala @@ -40,4 +40,4 @@ class RpcClientActor[I,O](exchangeParameters: ExchangeParameters, } override def toString = "AMQP.RpcClient[exchange=" +exchangeName + ", routingKey=" + routingKey+ "]" -} \ No newline at end of file +} diff --git a/akka-amqp/src/main/scala/RpcServerActor.scala b/akka-amqp/src/main/scala/RpcServerActor.scala index 897c041c69..c64ef9058e 100644 --- a/akka-amqp/src/main/scala/RpcServerActor.scala +++ b/akka-amqp/src/main/scala/RpcServerActor.scala @@ -31,4 +31,4 @@ class RpcServerActor[I,O](producer: ActorRef, serializer: RpcServerSerializer[I, override def toString(): String = "AMQP.RpcServer[]" -} \ No newline at end of file +} diff --git a/akka-amqp/src/test/scala/AMQPConnectionRecoveryTest.scala b/akka-amqp/src/test/scala/AMQPConnectionRecoveryTest.scala index 3bc2cb20dd..c1af35546a 100644 --- a/akka-amqp/src/test/scala/AMQPConnectionRecoveryTest.scala +++ b/akka-amqp/src/test/scala/AMQPConnectionRecoveryTest.scala @@ -56,4 +56,4 @@ class AMQPConnectionRecoveryTest extends JUnitSuite with MustMatchers with Loggi // this dummy test makes sure that the whole test class doesn't fail because of missing tests assert(true) } -} \ No newline at end of file +} diff --git a/akka-amqp/src/test/scala/AMQPConsumerChannelRecoveryTest.scala b/akka-amqp/src/test/scala/AMQPConsumerChannelRecoveryTest.scala index 0f6fadfcc4..a0b44f4739 100644 --- a/akka-amqp/src/test/scala/AMQPConsumerChannelRecoveryTest.scala +++ b/akka-amqp/src/test/scala/AMQPConsumerChannelRecoveryTest.scala @@ -67,4 +67,4 @@ class AMQPConsumerChannelRecoveryTest extends JUnitSuite with MustMatchers with // this dummy test makes sure that the whole test class doesn't fail because of missing tests assert(true) } -} \ No newline at end of file +} diff --git a/akka-amqp/src/test/scala/AMQPConsumerConnectionRecoveryTest.scala b/akka-amqp/src/test/scala/AMQPConsumerConnectionRecoveryTest.scala index 9dccd43be8..bf4885fea5 100644 --- a/akka-amqp/src/test/scala/AMQPConsumerConnectionRecoveryTest.scala +++ b/akka-amqp/src/test/scala/AMQPConsumerConnectionRecoveryTest.scala @@ -86,4 +86,4 @@ class AMQPConsumerConnectionRecoveryTest extends JUnitSuite with MustMatchers wi // this dummy test makes sure that the whole test class doesn't fail because of missing tests assert(true) } -} \ No newline at end of file +} diff --git a/akka-amqp/src/test/scala/AMQPConsumerManualAcknowledgeTest.scala b/akka-amqp/src/test/scala/AMQPConsumerManualAcknowledgeTest.scala index d48f38afc5..2dc4ee939b 100644 --- a/akka-amqp/src/test/scala/AMQPConsumerManualAcknowledgeTest.scala +++ b/akka-amqp/src/test/scala/AMQPConsumerManualAcknowledgeTest.scala @@ -64,4 +64,4 @@ class AMQPConsumerManualAcknowledgeTest extends JUnitSuite with MustMatchers wit // this dummy test makes sure that the whole test class doesn't fail because of missing tests assert(true) } -} \ No newline at end of file +} diff --git a/akka-amqp/src/test/scala/AMQPConsumerMessageTest.scala b/akka-amqp/src/test/scala/AMQPConsumerMessageTest.scala index af94b0a515..5d34f867d6 100644 --- a/akka-amqp/src/test/scala/AMQPConsumerMessageTest.scala +++ b/akka-amqp/src/test/scala/AMQPConsumerMessageTest.scala @@ -38,7 +38,7 @@ class AMQPConsumerMessageTest extends JUnitSuite with MustMatchers with Logging val producer = AMQP.newProducer(connection, ProducerParameters(exchangeParameters, channelParameters = Some(channelParameters))) - + countDown.await(2, TimeUnit.SECONDS) must be (true) producer ! Message("some_payload".getBytes, "non.interesting.routing.key") payloadLatch.tryAwait(2, TimeUnit.SECONDS) must be (true) @@ -53,4 +53,4 @@ class AMQPConsumerMessageTest extends JUnitSuite with MustMatchers with Logging // this dummy test makes sure that the whole test class doesn't fail because of missing tests assert(true) } -} \ No newline at end of file +} diff --git a/akka-amqp/src/test/scala/AMQPProducerChannelRecoveryTest.scala b/akka-amqp/src/test/scala/AMQPProducerChannelRecoveryTest.scala index 095a21fc86..26b2d78393 100644 --- a/akka-amqp/src/test/scala/AMQPProducerChannelRecoveryTest.scala +++ b/akka-amqp/src/test/scala/AMQPProducerChannelRecoveryTest.scala @@ -60,4 +60,4 @@ class AMQPProducerChannelRecoveryTest extends JUnitSuite with MustMatchers with // this dummy test makes sure that the whole test class doesn't fail because of missing tests assert(true) } -} \ No newline at end of file +} diff --git a/akka-amqp/src/test/scala/AMQPProducerConnectionRecoveryTest.scala b/akka-amqp/src/test/scala/AMQPProducerConnectionRecoveryTest.scala index 71bc08bdaa..fe8259b208 100644 --- a/akka-amqp/src/test/scala/AMQPProducerConnectionRecoveryTest.scala +++ b/akka-amqp/src/test/scala/AMQPProducerConnectionRecoveryTest.scala @@ -59,4 +59,4 @@ class AMQPProducerConnectionRecoveryTest extends JUnitSuite with MustMatchers wi // this dummy test makes sure that the whole test class doesn't fail because of missing tests assert(true) } -} \ No newline at end of file +} diff --git a/akka-amqp/src/test/scala/AMQPProducerMessageTest.scala b/akka-amqp/src/test/scala/AMQPProducerMessageTest.scala index ab9bb00e7c..5b19df351f 100644 --- a/akka-amqp/src/test/scala/AMQPProducerMessageTest.scala +++ b/akka-amqp/src/test/scala/AMQPProducerMessageTest.scala @@ -21,7 +21,7 @@ class AMQPProducerMessageTest extends JUnitSuite with MustMatchers with Logging @Test def producerMessage = if (AMQPTest.enabled) { - + val connection: ActorRef = AMQP.newConnection() try { val returnLatch = new StandardLatch @@ -48,4 +48,4 @@ class AMQPProducerMessageTest extends JUnitSuite with MustMatchers with Logging // this dummy test makes sure that the whole test class doesn't fail because of missing tests assert(true) } -} \ No newline at end of file +} diff --git a/akka-amqp/src/test/scala/AMQPRpcClientServerTest.scala b/akka-amqp/src/test/scala/AMQPRpcClientServerTest.scala index 7dbfb4becd..dcaec4cd06 100644 --- a/akka-amqp/src/test/scala/AMQPRpcClientServerTest.scala +++ b/akka-amqp/src/test/scala/AMQPRpcClientServerTest.scala @@ -68,4 +68,4 @@ class AMQPRpcClientServerTest extends JUnitSuite with MustMatchers with Logging // this dummy test makes sure that the whole test class doesn't fail because of missing tests assert(true) } -} \ No newline at end of file +} diff --git a/akka-amqp/src/test/scala/AMQPTest.scala b/akka-amqp/src/test/scala/AMQPTest.scala index e50ab673f6..5ff9157bc5 100644 --- a/akka-amqp/src/test/scala/AMQPTest.scala +++ b/akka-amqp/src/test/scala/AMQPTest.scala @@ -6,4 +6,4 @@ package se.scalablesolutions.akka.amqp.test object AMQPTest { def enabled = false -} \ No newline at end of file +} diff --git a/akka-camel/src/main/scala/CamelService.scala b/akka-camel/src/main/scala/CamelService.scala index 0fbbceee2e..8f3e504dfd 100644 --- a/akka-camel/src/main/scala/CamelService.scala +++ b/akka-camel/src/main/scala/CamelService.scala @@ -82,7 +82,7 @@ trait CamelService extends Bootable with Logging { /** * Sets an expectation of the number of upcoming endpoint activations and returns * a {@link CountDownLatch} that can be used to wait for the activations to occur. - * Endpoint activations that occurred in the past are not considered. + * Endpoint activations that occurred in the past are not considered. */ def expectEndpointActivationCount(count: Int): CountDownLatch = (consumerPublisher !! SetExpectedRegistrationCount(count)).as[CountDownLatch].get diff --git a/akka-camel/src/main/scala/Consumer.scala b/akka-camel/src/main/scala/Consumer.scala index e5218a21f2..1f7dffc91b 100644 --- a/akka-camel/src/main/scala/Consumer.scala +++ b/akka-camel/src/main/scala/Consumer.scala @@ -42,4 +42,4 @@ private[camel] object Consumer { else if (actorRef.remoteAddress.isDefined) None else Some(f(actorRef.actor.asInstanceOf[Consumer])) } -} \ No newline at end of file +} diff --git a/akka-camel/src/main/scala/component/ActorComponent.scala b/akka-camel/src/main/scala/component/ActorComponent.scala index 6baeaf8b3e..1cd29ced00 100644 --- a/akka-camel/src/main/scala/component/ActorComponent.scala +++ b/akka-camel/src/main/scala/component/ActorComponent.scala @@ -261,4 +261,4 @@ private[akka] class AsyncCallbackAdapter(exchange: Exchange, callback: AsyncCall protected[this] def actorInstance: AtomicReference[Actor] = unsupported private def unsupported = throw new UnsupportedOperationException("Not supported for %s" format classOf[AsyncCallbackAdapter].getName) -} \ No newline at end of file +} diff --git a/akka-camel/src/test/scala/CamelServiceFeatureTest.scala b/akka-camel/src/test/scala/CamelServiceFeatureTest.scala index 1fcbcadd64..753730659e 100644 --- a/akka-camel/src/test/scala/CamelServiceFeatureTest.scala +++ b/akka-camel/src/test/scala/CamelServiceFeatureTest.scala @@ -135,7 +135,7 @@ class CamelServiceFeatureTest extends FeatureSpec with BeforeAndAfterAll with Gi assert(response2 === "m3base: x y") assert(response3 === "m4base: x y") - // cleanup to avoid conflicts with next test (i.e. avoid multiple consumers on direct-endpoints) + // cleanup to avoid conflicts with next test (i.e. avoid multiple consumers on direct-endpoints) latch = service.expectEndpointDeactivationCount(3) TypedActor.stop(obj) assert(latch.await(5000, TimeUnit.MILLISECONDS)) diff --git a/akka-camel/src/test/scala/ProducerFeatureTest.scala b/akka-camel/src/test/scala/ProducerFeatureTest.scala index 5cf24eaaa3..d238286f9c 100644 --- a/akka-camel/src/test/scala/ProducerFeatureTest.scala +++ b/akka-camel/src/test/scala/ProducerFeatureTest.scala @@ -298,4 +298,4 @@ object ProducerFeatureTest { }) } } -} \ No newline at end of file +} diff --git a/akka-camel/src/test/scala/component/ActorProducerTest.scala b/akka-camel/src/test/scala/component/ActorProducerTest.scala index 300d0ca617..5e8a674e55 100644 --- a/akka-camel/src/test/scala/component/ActorProducerTest.scala +++ b/akka-camel/src/test/scala/component/ActorProducerTest.scala @@ -116,4 +116,4 @@ object ActorProducerTest { } } -} \ No newline at end of file +} diff --git a/akka-core/src/main/scala/actor/Actor.scala b/akka-core/src/main/scala/actor/Actor.scala index 1de3997c12..60210e5d6d 100644 --- a/akka-core/src/main/scala/actor/Actor.scala +++ b/akka-core/src/main/scala/actor/Actor.scala @@ -415,7 +415,7 @@ trait Actor extends Logging { * Is the actor able to handle the message passed in as arguments? */ def isDefinedAt(message: Any): Boolean = base.isDefinedAt(message) - + /** One of the fundamental methods of the ActorsModel * Actor assumes a new behavior */ diff --git a/akka-core/src/main/scala/actor/ActorRef.scala b/akka-core/src/main/scala/actor/ActorRef.scala index ca55d6c1fa..e84c0cfa6f 100644 --- a/akka-core/src/main/scala/actor/ActorRef.scala +++ b/akka-core/src/main/scala/actor/ActorRef.scala @@ -416,13 +416,13 @@ trait ActorRef extends TransactionManagement { * Returns the home address and port for this actor. */ def homeAddress: InetSocketAddress = _homeAddress - + /** * Set the home address and port for this actor. */ def homeAddress_=(hostnameAndPort: Tuple2[String, Int]): Unit = homeAddress_=(new InetSocketAddress(hostnameAndPort._1, hostnameAndPort._2)) - + /** * Set the home address and port for this actor. */ @@ -962,7 +962,7 @@ sealed class LocalActorRef private[akka]( throw e } finally { currentMessage = None //TODO: Don't reset this, we might want to resend the message - } + } } } @@ -987,20 +987,20 @@ sealed class LocalActorRef private[akka]( protected[akka] def restart(reason: Throwable, maxNrOfRetries: Int, withinTimeRange: Int): Unit = { if (maxNrOfRetriesCount == 0) restartsWithinTimeRangeTimestamp = System.currentTimeMillis // first time around maxNrOfRetriesCount += 1 - + val tooManyRestarts = maxNrOfRetriesCount > maxNrOfRetries val restartingHasExpired = (System.currentTimeMillis - restartsWithinTimeRangeTimestamp) > withinTimeRange if (tooManyRestarts || restartingHasExpired) { val notification = MaximumNumberOfRestartsWithinTimeRangeReached(this, maxNrOfRetries, withinTimeRange, reason) Actor.log.warning( - "Maximum number of restarts [%s] within time range [%s] reached." + - "\n\tWill *not* restart actor [%s] anymore." + - "\n\tLast exception causing restart was" + - "\n\t[%s].", + "Maximum number of restarts [%s] within time range [%s] reached." + + "\n\tWill *not* restart actor [%s] anymore." + + "\n\tLast exception causing restart was" + + "\n\t[%s].", maxNrOfRetries, withinTimeRange, this, reason) - _supervisor.foreach { sup => + _supervisor.foreach { sup => // can supervisor handle the notification? - if (sup.isDefinedAt(notification)) notifySupervisorWithMessage(notification) + if (sup.isDefinedAt(notification)) notifySupervisorWithMessage(notification) else Actor.log.warning( "No message handler defined for system message [MaximumNumberOfRestartsWithinTimeRangeReached]" + "\n\tCan't send the message to the supervisor [%s].", sup) @@ -1012,7 +1012,7 @@ sealed class LocalActorRef private[akka]( guard.withGuard { lifeCycle match { case Some(LifeCycle(Temporary, _, _)) => shutDownTemporaryActor(this) - case _ => + case _ => // either permanent or none where default is permanent Actor.log.info("Restarting actor [%s] configured as PERMANENT.", id) Actor.log.debug("Restarting linked actors for actor [%s].", id) @@ -1062,7 +1062,7 @@ sealed class LocalActorRef private[akka]( failedActor.preRestart(reason) failedActor.postRestart(reason) } - + private def restartActor(failedActor: Actor, reason: Throwable) = { failedActor.preRestart(reason) nullOutActorRefReferencesFor(failedActor) @@ -1073,7 +1073,7 @@ sealed class LocalActorRef private[akka]( Actor.log.debug("Invoking 'postRestart' for new actor instance [%s].", id) freshActor.postRestart(reason) } - + private def spawnButDoNotStart[T <: Actor: Manifest]: ActorRef = guard.withGuard { val actorRef = Actor.actorOf(manifest[T].erasure.asInstanceOf[Class[T]].newInstance) if (!dispatcher.isInstanceOf[ThreadBasedDispatcher]) actorRef.dispatcher = dispatcher @@ -1113,8 +1113,8 @@ sealed class LocalActorRef private[akka]( clearTransactionSet createNewTransactionSet } else oldTxSet - Actor.log.ifTrace("Joining transaction set [" + currentTxSet + - "];\n\tactor " + toString + + Actor.log.ifTrace("Joining transaction set [" + currentTxSet + + "];\n\tactor " + toString + "\n\twith message [" + message + "]") val mtx = ThreadLocalTransaction.getThreadLocalTransaction if ((mtx eq null) || mtx.getStatus.isDead) currentTxSet.incParties @@ -1130,7 +1130,7 @@ sealed class LocalActorRef private[akka]( else { topLevelTransaction = true // FIXME create a new internal atomic block that can wait for X seconds if top level tx if (isTransactor) { - Actor.log.ifTrace("Creating a new transaction set (top-level transaction)\n\tfor actor " + toString + + Actor.log.ifTrace("Creating a new transaction set (top-level transaction)\n\tfor actor " + toString + "\n\twith message " + messageHandle) Some(createNewTransactionSet) } else None @@ -1152,7 +1152,7 @@ sealed class LocalActorRef private[akka]( } catch { case e: DeadTransactionException => handleExceptionInDispatch( - new TransactionSetAbortedException("Transaction set has been aborted by another participant"), + new TransactionSetAbortedException("Transaction set has been aborted by another participant"), message, topLevelTransaction) case e: InterruptedException => {} // received message while actor is shutting down, ignore case e => handleExceptionInDispatch(e, message, topLevelTransaction) @@ -1199,14 +1199,14 @@ sealed class LocalActorRef private[akka]( private def notifySupervisorWithMessage(notification: LifeCycleMessage) = { // FIXME to fix supervisor restart of remote actor for oneway calls, inject a supervisor proxy that can send notification back to client - _supervisor.foreach { sup => + _supervisor.foreach { sup => if (sup.isShutdown) { // if supervisor is shut down, game over for all linked actors // shutdownLinkedActors // stop } else sup ! notification // else notify supervisor } } - + private def nullOutActorRefReferencesFor(actor: Actor) = { actorSelfFields._1.set(actor, null) actorSelfFields._2.set(actor, null) diff --git a/akka-core/src/main/scala/actor/ActorRegistry.scala b/akka-core/src/main/scala/actor/ActorRegistry.scala index 57b27f08b0..cebc2ec287 100644 --- a/akka-core/src/main/scala/actor/ActorRegistry.scala +++ b/akka-core/src/main/scala/actor/ActorRegistry.scala @@ -29,11 +29,11 @@ case class ActorUnregistered(actor: ActorRef) extends ActorRegistryEvent * @author Jonas Bonér */ object ActorRegistry extends ListenerManagement { - + private val refComparator = new java.util.Comparator[ActorRef]{ def compare(a: ActorRef,b: ActorRef) = a.uuid.compareTo(b.uuid) } - + private val actorsByUUID = new ConcurrentHashMap[String, ActorRef] private val actorsById = new ConcurrentHashMap[String, JSet[ActorRef]] private val actorsByClassName = new ConcurrentHashMap[String, JSet[ActorRef]] diff --git a/akka-core/src/main/scala/actor/SerializationProtocol.scala b/akka-core/src/main/scala/actor/SerializationProtocol.scala index 3897d3abda..b1cbb53bdc 100644 --- a/akka-core/src/main/scala/actor/SerializationProtocol.scala +++ b/akka-core/src/main/scala/actor/SerializationProtocol.scala @@ -226,7 +226,7 @@ object RemoteActorSerialization { .build } - def createRemoteRequestProtocolBuilder(actorRef: ActorRef, message: Any, isOneWay: Boolean, senderOption: Option[ActorRef]): + def createRemoteRequestProtocolBuilder(actorRef: ActorRef, message: Any, isOneWay: Boolean, senderOption: Option[ActorRef]): RemoteRequestProtocol.Builder = { import actorRef._ diff --git a/akka-core/src/main/scala/actor/Supervisor.scala b/akka-core/src/main/scala/actor/Supervisor.scala index ede7d380db..9b56bddf38 100644 --- a/akka-core/src/main/scala/actor/Supervisor.scala +++ b/akka-core/src/main/scala/actor/Supervisor.scala @@ -180,7 +180,7 @@ final class SupervisorActor private[akka] ( handler: FaultHandlingStrategy, trapExceptions: List[Class[_ <: Throwable]]) extends Actor { import self._ - + trapExit = trapExceptions faultHandler = Some(handler) diff --git a/akka-core/src/main/scala/actor/TypedActor.scala b/akka-core/src/main/scala/actor/TypedActor.scala index f624daeb33..7526d48b05 100644 --- a/akka-core/src/main/scala/actor/TypedActor.scala +++ b/akka-core/src/main/scala/actor/TypedActor.scala @@ -22,7 +22,7 @@ import java.net.InetSocketAddress import java.lang.reflect.{InvocationTargetException, Method, Field} import scala.reflect.BeanProperty - + /** * FIXME: document TypedActor * @@ -33,12 +33,12 @@ import scala.reflect.BeanProperty * Pong pong = (Pong) getContext().getSender(); * pong.hit(count++); * } - * + * * @Override * public void init() { * ... // optional initialization on start * } - * + * * @Override * public void shutdown() { * ... // optional cleanup on stop @@ -46,7 +46,7 @@ import scala.reflect.BeanProperty * * ... // more life-cycle callbacks if needed * } - * + * * // create the ping actor * Ping ping = TypedActor.newInstance(Ping.class, PingImpl.class); * @@ -56,7 +56,7 @@ import scala.reflect.BeanProperty * // stop the actor * TypedActor.stop(ping); * - * + * * Here is an example of usage (in Scala): *
  * class PingImpl extends TypedActor with Ping {
@@ -68,14 +68,14 @@ import scala.reflect.BeanProperty
  *   override def init = {
  *     ... // optional initialization on start
  *   }
- * 
+ *
  *   override def shutdown = {
  *     ... // optional cleanup on stop
  *   }
  *
  *   ... // more life-cycle callbacks if needed
  * }
- * 
+ *
  * // create the ping actor
  * val ping = TypedActor.newInstance(classOf[Ping], classOf[PingImpl])
  *
@@ -85,7 +85,7 @@ import scala.reflect.BeanProperty
  * // stop the actor
  * TypedActor.stop(ping)
  * 
- * + * * @author Jonas Bonér */ abstract class TypedActor extends Logging { @@ -97,7 +97,7 @@ abstract class TypedActor extends Logging { * This class does not contain static information but is updated by the runtime system * at runtime. *

- * You can get a hold of the context using either the 'getContext()' or 'context' + * You can get a hold of the context using either the 'getContext()' or 'context' * methods from the 'TypedActor' base class. *

* @@ -110,7 +110,7 @@ abstract class TypedActor extends Logging { * } * } * - * + * * Here is an example of usage (in Scala): *

    * class PingImpl extends TypedActor with Ping {
@@ -127,7 +127,7 @@ abstract class TypedActor extends Logging {
    * The uuid for the Typed Actor.
    */
   @BeanProperty @volatile var uuid = UUID.newUuid.toString
-  
+
   /**
    * Identifier for actor, does not have to be a unique one. Default is the 'uuid'.
    * 

@@ -189,14 +189,14 @@ abstract class TypedActor extends Logging { * * @author Jonas Bonér */ -@transactionrequired +@transactionrequired abstract class TypedTransactor extends TypedActor /** * Configuration factory for TypedActors. * * FIXDOC: document TypedActorConfiguration - * + * * @author Jonas Bonér */ final class TypedActorConfiguration { @@ -246,7 +246,7 @@ final class TypedActorConfiguration { * This class does not contain static information but is updated by the runtime system * at runtime. *

- * You can get a hold of the context using either the 'getContext()' or 'context' + * You can get a hold of the context using either the 'getContext()' or 'context' * methods from the 'TypedActor' base class. *

* Here is an example of usage (from Java): @@ -258,7 +258,7 @@ final class TypedActorConfiguration { * } * } *

- * + * * Here is an example of usage (in Scala): *
  * class PingImpl extends TypedActor with Ping {
@@ -320,19 +320,19 @@ object TypedActor extends Logging {
   private[actor] val AW_PROXY_PREFIX = "$$ProxiedByAW".intern
 
   def newInstance[T](intfClass: Class[T], targetClass: Class[_], timeout: Long): T = {
-    newInstance(intfClass, newTypedActor(targetClass), actorOf(new Dispatcher(false)), None, timeout)    
+    newInstance(intfClass, newTypedActor(targetClass), actorOf(new Dispatcher(false)), None, timeout)
   }
 
   def newInstance[T](intfClass: Class[T], targetClass: Class[_]): T = {
-    newInstance(intfClass, newTypedActor(targetClass), actorOf(new Dispatcher(false)), None, Actor.TIMEOUT)    
+    newInstance(intfClass, newTypedActor(targetClass), actorOf(new Dispatcher(false)), None, Actor.TIMEOUT)
   }
 
   def newRemoteInstance[T](intfClass: Class[T], targetClass: Class[_], timeout: Long, hostname: String, port: Int): T = {
-    newInstance(intfClass, newTypedActor(targetClass), actorOf(new Dispatcher(false)), Some(new InetSocketAddress(hostname, port)), timeout)    
+    newInstance(intfClass, newTypedActor(targetClass), actorOf(new Dispatcher(false)), Some(new InetSocketAddress(hostname, port)), timeout)
   }
 
   def newRemoteInstance[T](intfClass: Class[T], targetClass: Class[_], hostname: String, port: Int): T = {
-    newInstance(intfClass, newTypedActor(targetClass), actorOf(new Dispatcher(false)), Some(new InetSocketAddress(hostname, port)), Actor.TIMEOUT)    
+    newInstance(intfClass, newTypedActor(targetClass), actorOf(new Dispatcher(false)), Some(new InetSocketAddress(hostname, port)), Actor.TIMEOUT)
   }
 
   def newInstance[T](intfClass: Class[T], targetClass: Class[_], config: TypedActorConfiguration): T = {
@@ -356,7 +356,7 @@ object TypedActor extends Logging {
   // NOTE: currently not used - but keep it around
   private[akka] def newInstance[T <: TypedActor](
       targetClass: Class[T], actorRef: ActorRef, remoteAddress: Option[InetSocketAddress], timeout: Long): T = {
-    val proxy = { 
+    val proxy = {
       val instance = Proxy.newInstance(targetClass, true, false)
       if (instance.isInstanceOf[TypedActor]) instance.asInstanceOf[TypedActor]
       else throw new IllegalActorStateException("Actor [" + targetClass.getName + "] is not a sub class of 'TypedActor'")
@@ -378,7 +378,7 @@ object TypedActor extends Logging {
   /**
    * Get the underlying dispatcher actor for the given Typed Actor.
    */
-  def actorFor(proxy: AnyRef): Option[ActorRef] = 
+  def actorFor(proxy: AnyRef): Option[ActorRef] =
     ActorRegistry
       .actorsFor(classOf[Dispatcher])
       .find(a => a.actor.asInstanceOf[Dispatcher].proxy == proxy)
@@ -403,7 +403,7 @@ object TypedActor extends Logging {
    * @param handler fault handling strategy
    * @param trapExceptions array of exceptions that should be handled by the supervisor
    */
-  def link(supervisor: AnyRef, supervised: AnyRef, 
+  def link(supervisor: AnyRef, supervised: AnyRef,
            handler: FaultHandlingStrategy, trapExceptions: Array[Class[_ <: Throwable]]) = {
     val supervisorActor = actorFor(supervisor).getOrElse(
       throw new IllegalActorStateException("Can't link when the supervisor is not an Typed Actor"))
@@ -463,8 +463,8 @@ object TypedActor extends Logging {
         val parent = clazz.getSuperclass
         if (parent != null) injectTypedActorContext0(activeObject, parent)
         else {
-          log.ifTrace("Can't set 'TypedActorContext' for TypedActor [" + 
-                      activeObject.getClass.getName + 
+          log.ifTrace("Can't set 'TypedActorContext' for TypedActor [" +
+                      activeObject.getClass.getName +
                       "] since no field of this type could be found.")
           None
         }
@@ -475,7 +475,7 @@ object TypedActor extends Logging {
 
   private[akka] def newTypedActor(targetClass: Class[_]): TypedActor = {
     val instance = targetClass.newInstance
-    val typedActor = 
+    val typedActor =
       if (instance.isInstanceOf[TypedActor]) instance.asInstanceOf[TypedActor]
       else throw new IllegalArgumentException("Actor [" + targetClass.getName + "] is not a sub class of 'TypedActor'")
     typedActor.init
@@ -546,14 +546,14 @@ private[akka] sealed case class AspectInit(
   val actorRef: ActorRef,
   val remoteAddress: Option[InetSocketAddress],
   val timeout: Long) {
-  def this(interfaceClass: Class[_], targetInstance: TypedActor, actorRef: ActorRef, timeout: Long) = 
+  def this(interfaceClass: Class[_], targetInstance: TypedActor, actorRef: ActorRef, timeout: Long) =
     this(interfaceClass, targetInstance, actorRef, None, timeout)
 }
 
 /**
  * AspectWerkz Aspect that is turning POJO into TypedActor.
  * 

- * Is deployed on a 'perInstance' basis with the pointcut 'execution(* *.*(..))', + * Is deployed on a 'perInstance' basis with the pointcut 'execution(* *.*(..))', * e.g. all methods on the instance. * * @author Jonas Bonér @@ -620,7 +620,7 @@ private[akka] sealed class TypedActorAspect { .setInterface(interfaceClass.getName) .setMethod(rtti.getMethod.getName) .build - + val actorInfo = ActorInfoProtocol.newBuilder .setUuid(uuid) .setTarget(targetInstance.getClass.getName) @@ -736,7 +736,7 @@ private[akka] class Dispatcher(transactionalRequired: Boolean) extends Actor { private[actor] def initialize( targetClass: Class[_], targetInstance: TypedActor, proxy: AnyRef, ctx: Option[TypedActorContext]) = { if (transactionalRequired || isTransactional(targetClass)) self.makeTransactionRequired - + self.id = targetClass.getName this.targetClass = targetClass this.proxy = proxy @@ -804,11 +804,11 @@ private[akka] class Dispatcher(transactionalRequired: Boolean) extends Actor { targetInstance.initTransactionalState } - def isTransactional(clazz: Class[_]): Boolean = + def isTransactional(clazz: Class[_]): Boolean = if (clazz == null) false else if (clazz.isAnnotationPresent(Annotations.transactionrequired)) true else isTransactional(clazz.getSuperclass) - + private def serializeArguments(joinPoint: JoinPoint) = { val args = joinPoint.getRtti.asInstanceOf[MethodRtti].getParameterValues var unserializable = false diff --git a/akka-core/src/main/scala/actor/UntypedActor.scala b/akka-core/src/main/scala/actor/UntypedActor.scala index 81924886d9..61e310d732 100644 --- a/akka-core/src/main/scala/actor/UntypedActor.scala +++ b/akka-core/src/main/scala/actor/UntypedActor.scala @@ -5,7 +5,7 @@ package se.scalablesolutions.akka.actor /** - * FIXME: document + * FIXME: document * * @author Jonas Bonér */ @@ -13,7 +13,7 @@ abstract class UntypedActor extends Actor { protected[akka] var context: Option[ActorContext] = None protected def receive = { - case msg => + case msg => if (context.isEmpty) { val ctx = new ActorContext(self) context = Some(ctx) @@ -25,9 +25,9 @@ abstract class UntypedActor extends Actor { } /** - * FIXME: document + * FIXME: document * * @author Jonas Bonér */ class ActorContext(val self: ActorRef) { -} \ No newline at end of file +} diff --git a/akka-core/src/main/scala/config/TypedActorConfigurator.scala b/akka-core/src/main/scala/config/TypedActorConfigurator.scala index 797d52cd70..d639d21f5f 100644 --- a/akka-core/src/main/scala/config/TypedActorConfigurator.scala +++ b/akka-core/src/main/scala/config/TypedActorConfigurator.scala @@ -32,7 +32,7 @@ class TypedActorConfigurator { * @param clazz the class for the typed actor * @return a list with all the typed actors for the class */ - def getInstances[T](clazz: Class[T]): JList[T] = + def getInstances[T](clazz: Class[T]): JList[T] = INSTANCE.getInstance(clazz).foldLeft(new ArrayList[T]){ (l, i) => l add i ; l } /** diff --git a/akka-core/src/main/scala/config/TypedActorGuiceConfigurator.scala b/akka-core/src/main/scala/config/TypedActorGuiceConfigurator.scala index 29efc14082..fe9289f1f8 100644 --- a/akka-core/src/main/scala/config/TypedActorGuiceConfigurator.scala +++ b/akka-core/src/main/scala/config/TypedActorGuiceConfigurator.scala @@ -81,7 +81,7 @@ private[akka] class TypedActorGuiceConfigurator extends TypedActorConfiguratorBa } private def newSubclassingProxy(component: Component): DependencyBinding = { - val targetClass = + val targetClass = if (component.target.isInstanceOf[Class[_ <: TypedActor]]) component.target.asInstanceOf[Class[_ <: TypedActor]] else throw new IllegalArgumentException("TypedActor [" + component.target.getName + "] must be a subclass of TypedActor") val actorRef = Actor.actorOf(new Dispatcher(component.transactionRequired)) @@ -103,7 +103,7 @@ private[akka] class TypedActorGuiceConfigurator extends TypedActorConfiguratorBa val targetClass = component.intf.get val instance = component.target.newInstance.asInstanceOf[AnyRef] // TODO: perhaps need to put in registry - val targetInstance = + val targetInstance = if (instance.isInstanceOf[TypedActor]) instance.asInstanceOf[TypedActor] else throw new IllegalArgumentException("TypedActor [" + component.target.getName + "] must be a subclass of TypedActor") diff --git a/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenDispatcher.scala b/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenDispatcher.scala index 42d1ae1620..836dc0ea86 100644 --- a/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenDispatcher.scala +++ b/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenDispatcher.scala @@ -153,7 +153,7 @@ class ExecutorBasedEventDrivenDispatcher(_name: String, throughput: Int = Dispat def ensureNotActive(): Unit = if (active) throw new IllegalActorStateException( "Can't build a new thread pool for a dispatcher that is already up and running") - + override def toString = "ExecutorBasedEventDrivenDispatcher[" + name + "]" // FIXME: should we have an unbounded queue and not bounded as default ???? diff --git a/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcher.scala b/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcher.scala index 6f4ec934eb..b9ff5d92f4 100644 --- a/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcher.scala +++ b/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenWorkStealingDispatcher.scala @@ -52,7 +52,7 @@ class ExecutorBasedEventDrivenWorkStealingDispatcher(_name: String) extends Mess private def getMailbox(receiver: ActorRef) = receiver.mailbox.asInstanceOf[ConcurrentLinkedDeque[MessageInvocation]] override def mailboxSize(actorRef: ActorRef) = getMailbox(actorRef).size - + def dispatch(invocation: MessageInvocation) = if (active) { getMailbox(invocation.receiver).add(invocation) executor.execute(new Runnable() { @@ -175,7 +175,7 @@ class ExecutorBasedEventDrivenWorkStealingDispatcher(_name: String) extends Mess "Can't build a new thread pool for a dispatcher that is already up and running") override def toString = "ExecutorBasedEventDrivenWorkStealingDispatcher[" + name + "]" - + private[akka] def init = withNewThreadPoolWithLinkedBlockingQueueWithUnboundedCapacity.buildThreadPool override def register(actorRef: ActorRef) = { diff --git a/akka-core/src/main/scala/dispatch/HawtDispatcher.scala b/akka-core/src/main/scala/dispatch/HawtDispatcher.scala index 3e14f0a5aa..45e4468b3d 100644 --- a/akka-core/src/main/scala/dispatch/HawtDispatcher.scala +++ b/akka-core/src/main/scala/dispatch/HawtDispatcher.scala @@ -69,7 +69,7 @@ object HawtDispatcher { */ def queue(actorRef: ActorRef) = { mailbox(actorRef).queue - } + } /** @@ -173,7 +173,7 @@ object HawtDispatcher { class HawtDispatcher(val aggregate:Boolean=true, val parent:DispatchQueue=globalQueue) extends MessageDispatcher { import HawtDispatcher._ private val active = new AtomicBoolean(false) - + def start = { if( active.compareAndSet(false, true) ) { retainNonDaemon diff --git a/akka-core/src/main/scala/dispatch/ReactorBasedSingleThreadEventDrivenDispatcher.scala b/akka-core/src/main/scala/dispatch/ReactorBasedSingleThreadEventDrivenDispatcher.scala index e6896ef706..d0850aa830 100644 --- a/akka-core/src/main/scala/dispatch/ReactorBasedSingleThreadEventDrivenDispatcher.scala +++ b/akka-core/src/main/scala/dispatch/ReactorBasedSingleThreadEventDrivenDispatcher.scala @@ -14,7 +14,7 @@ import java.util.{LinkedList, List} class ReactorBasedSingleThreadEventDrivenDispatcher(_name: String) extends AbstractReactorBasedEventDrivenDispatcher("akka:event-driven:reactor:single-thread:dispatcher:" + _name) { - + def start = if (!active) { log.debug("Starting up %s", toString) active = true diff --git a/akka-core/src/main/scala/remote/RemoteServer.scala b/akka-core/src/main/scala/remote/RemoteServer.scala index e93fc4db48..55a74feab0 100644 --- a/akka-core/src/main/scala/remote/RemoteServer.scala +++ b/akka-core/src/main/scala/remote/RemoteServer.scala @@ -432,9 +432,9 @@ class RemoteServerHandler( /** * Creates a new instance of the actor with name, uuid and timeout specified as arguments. - * + * * If actor already created then just return it from the registry. - * + * * Does not start the actor. */ private def createActor(actorInfo: ActorInfoProtocol): ActorRef = { @@ -474,11 +474,11 @@ class RemoteServerHandler( try { log.info("Creating a new remote typed actor:\n\t[%s :: %s]", interfaceClassname, targetClassname) - val (interfaceClass, targetClass) = - if (applicationLoader.isDefined) (applicationLoader.get.loadClass(interfaceClassname), + val (interfaceClass, targetClass) = + if (applicationLoader.isDefined) (applicationLoader.get.loadClass(interfaceClassname), applicationLoader.get.loadClass(targetClassname)) else (Class.forName(interfaceClassname), Class.forName(targetClassname)) - + val newInstance = TypedActor.newInstance( interfaceClass, targetClass.asInstanceOf[Class[_ <: TypedActor]], actorInfo.getTimeout).asInstanceOf[AnyRef] activeObjects.put(uuid, newInstance) @@ -488,7 +488,7 @@ class RemoteServerHandler( } } else activeObjectOrNull } - + private def createErrorReplyMessage(e: Throwable, request: RemoteRequestProtocol, isActor: Boolean): RemoteReplyProtocol = { val actorInfo = request.getActorInfo log.error(e, "Could not invoke remote typed actor [%s :: %s]", actorInfo.getTypedActorInfo.getMethod, actorInfo.getTarget) diff --git a/akka-core/src/main/scala/stm/JTA.scala b/akka-core/src/main/scala/stm/JTA.scala index 24b5a49086..1c0af88d73 100644 --- a/akka-core/src/main/scala/stm/JTA.scala +++ b/akka-core/src/main/scala/stm/JTA.scala @@ -4,8 +4,8 @@ package se.scalablesolutions.akka.stm -import javax.transaction.{TransactionManager, UserTransaction, - Transaction => JtaTransaction, SystemException, +import javax.transaction.{TransactionManager, UserTransaction, + Transaction => JtaTransaction, SystemException, Status, Synchronization, TransactionSynchronizationRegistry} import javax.naming.{InitialContext, Context, NamingException} diff --git a/akka-core/src/main/scala/stm/TransactionFactory.scala b/akka-core/src/main/scala/stm/TransactionFactory.scala index 329928c011..691fec675b 100644 --- a/akka-core/src/main/scala/stm/TransactionFactory.scala +++ b/akka-core/src/main/scala/stm/TransactionFactory.scala @@ -153,7 +153,7 @@ object TransactionFactory { * @see TransactionConfig for configuration options. */ class TransactionFactory( - val config: TransactionConfig = DefaultTransactionConfig, + val config: TransactionConfig = DefaultTransactionConfig, defaultName: String = TransactionConfig.FAMILY_NAME) { self => // use the config family name if it's been set, otherwise defaultName - used by actors to set class name as default diff --git a/akka-core/src/main/scala/stm/TransactionManagement.scala b/akka-core/src/main/scala/stm/TransactionManagement.scala index 25e58f3fb6..65f8d7624c 100644 --- a/akka-core/src/main/scala/stm/TransactionManagement.scala +++ b/akka-core/src/main/scala/stm/TransactionManagement.scala @@ -160,7 +160,7 @@ class GlobalStm extends TransactionManagement with Logging { txSet.tryJoinCommit( mtx, TransactionConfig.DefaultTimeout.length, - TransactionConfig.DefaultTimeout.unit) + TransactionConfig.DefaultTimeout.unit) // Need to catch IllegalStateException until we have fix in Multiverse, since it throws it by mistake } catch { case e: IllegalStateException => {} } result @@ -170,19 +170,19 @@ class GlobalStm extends TransactionManagement with Logging { } trait StmUtil { - + /** * Schedule a deferred task on the thread local transaction (use within an atomic). * This is executed when the transaction commits. */ - def deferred[T](body: => T): Unit = + def deferred[T](body: => T): Unit = MultiverseStmUtils.scheduleDeferredTask(new Runnable { def run = body }) /** * Schedule a compensating task on the thread local transaction (use within an atomic). * This is executed when the transaction aborts. */ - def compensating[T](body: => T): Unit = + def compensating[T](body: => T): Unit = MultiverseStmUtils.scheduleCompensatingTask(new Runnable { def run = body }) /** @@ -193,7 +193,7 @@ trait StmUtil { /** * Use either-orElse to combine two blocking transactions. - * Usage: + * Usage: *

    * either {
    *   ...
diff --git a/akka-core/src/test/scala/actor/NestedTransactionalTypedActorSpec.scala b/akka-core/src/test/scala/actor/NestedTransactionalTypedActorSpec.scala
index e0c59800bc..7338e8df41 100644
--- a/akka-core/src/test/scala/actor/NestedTransactionalTypedActorSpec.scala
+++ b/akka-core/src/test/scala/actor/NestedTransactionalTypedActorSpec.scala
@@ -99,4 +99,4 @@ class NestedTransactionalTypedActorSpec extends
       nested.getRefState should equal("init")
     }
   }
-}
\ No newline at end of file
+}
diff --git a/akka-core/src/test/scala/actor/ReceiveTimeoutSpec.scala b/akka-core/src/test/scala/actor/ReceiveTimeoutSpec.scala
index 248cbcbcab..ff43467efc 100644
--- a/akka-core/src/test/scala/actor/ReceiveTimeoutSpec.scala
+++ b/akka-core/src/test/scala/actor/ReceiveTimeoutSpec.scala
@@ -74,4 +74,4 @@ class ReceiveTimeoutSpec extends JUnitSuite {
 
     assert(timeoutLatch.tryAwait(1, TimeUnit.SECONDS) == false)
   }
-}
\ No newline at end of file
+}
diff --git a/akka-core/src/test/scala/actor/RestartNestedTransactionalTypedActorSpec.scala b/akka-core/src/test/scala/actor/RestartNestedTransactionalTypedActorSpec.scala
index d853230371..e70370c261 100644
--- a/akka-core/src/test/scala/actor/RestartNestedTransactionalTypedActorSpec.scala
+++ b/akka-core/src/test/scala/actor/RestartNestedTransactionalTypedActorSpec.scala
@@ -58,19 +58,19 @@ class RestartNestedTransactionalTypedActorSpec extends
       val stateful = conf.getInstance(classOf[TransactionalTypedActor])
       stateful.init
       stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state
-      
+
       val nested = conf.getInstance(classOf[NestedTransactionalTypedActor])
       nested.init
       nested.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init") // set init state
-      
+
       val failer = conf.getInstance(classOf[TypedActorFailer])
       try {
         stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer)
-        
+
         fail("should have thrown an exception")
       } catch { case e => {} }
       stateful.getMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure") should equal("init")
-      
+
       nested.getMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure") should equal("init")
     }
 
@@ -78,19 +78,19 @@ class RestartNestedTransactionalTypedActorSpec extends
       val stateful = conf.getInstance(classOf[TransactionalTypedActor])
       stateful.init
       stateful.setVectorState("init") // set init state
-      
+
       val nested = conf.getInstance(classOf[NestedTransactionalTypedActor])
       nested.init
       nested.setVectorState("init") // set init state
-      
+
       val failer = conf.getInstance(classOf[TypedActorFailer])
       try {
         stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer)
-        
+
         fail("should have thrown an exception")
       } catch { case e => {} }
       stateful.getVectorState should equal("init")
-      
+
       nested.getVectorState should equal("init")
     }
 
@@ -100,19 +100,19 @@ class RestartNestedTransactionalTypedActorSpec extends
       val nested = conf.getInstance(classOf[NestedTransactionalTypedActor])
       nested.init
       stateful.setRefState("init") // set init state
-      
+
       nested.setRefState("init") // set init state
-      
+
       val failer = conf.getInstance(classOf[TypedActorFailer])
       try {
         stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", nested, failer)
-        
+
         fail("should have thrown an exception")
       } catch { case e => {} }
       stateful.getRefState should equal("init")
-      
+
       nested.getRefState should equal("init")
     }
     */
   }
-}
\ No newline at end of file
+}
diff --git a/akka-core/src/test/scala/actor/RestartTransactionalTypedActorSpec.scala b/akka-core/src/test/scala/actor/RestartTransactionalTypedActorSpec.scala
index a4f9c61f59..5da6f9594f 100644
--- a/akka-core/src/test/scala/actor/RestartTransactionalTypedActorSpec.scala
+++ b/akka-core/src/test/scala/actor/RestartTransactionalTypedActorSpec.scala
@@ -46,7 +46,7 @@ class RestartTransactionalTypedActorSpec extends
     conf.stop
     ActorRegistry.shutdownAll
   }
-  
+
   describe("Restart supervised transactional Active Object ") {
 /*
     it("map should rollback state for stateful server in case of failure") {
diff --git a/akka-core/src/test/scala/actor/SchedulerSpec.scala b/akka-core/src/test/scala/actor/SchedulerSpec.scala
index 450a265788..1cedb27354 100644
--- a/akka-core/src/test/scala/actor/SchedulerSpec.scala
+++ b/akka-core/src/test/scala/actor/SchedulerSpec.scala
@@ -83,4 +83,4 @@ class SchedulerSpec extends JUnitSuite {
     // should be enough time for the ping countdown to recover and reach 6 pings
     assert(pingLatch.await(4, TimeUnit.SECONDS))
   }
-}
\ No newline at end of file
+}
diff --git a/akka-core/src/test/scala/actor/SupervisorHierarchySpec.scala b/akka-core/src/test/scala/actor/SupervisorHierarchySpec.scala
index 138313bafc..ffc9dbd860 100644
--- a/akka-core/src/test/scala/actor/SupervisorHierarchySpec.scala
+++ b/akka-core/src/test/scala/actor/SupervisorHierarchySpec.scala
@@ -14,7 +14,7 @@ import java.util.concurrent.{TimeUnit, CountDownLatch}
 
 object SupervisorHierarchySpec {
   class FireWorkerException(msg: String) extends Exception(msg)
-  
+
   class CountDownActor(countDown: CountDownLatch) extends Actor {
     protected def receive = { case _ => () }
     override def postRestart(reason: Throwable) = countDown.countDown
@@ -57,7 +57,7 @@ class SupervisorHierarchySpec extends JUnitSuite {
 
     assert(countDown.await(2, TimeUnit.SECONDS))
   }
-  
+
   @Test
   def supervisorShouldReceiveNotificationMessageWhenMaximumNumberOfRestartsWithinTimeRangeIsReached = {
     val countDown = new CountDownLatch(2)
@@ -65,7 +65,7 @@ class SupervisorHierarchySpec extends JUnitSuite {
     val boss = actorOf(new Actor{
       self.trapExit = List(classOf[Throwable])
       self.faultHandler = Some(OneForOneStrategy(1, 5000))
-      protected def receive = { 
+      protected def receive = {
         case MaximumNumberOfRestartsWithinTimeRangeReached(_, _, _, _) =>
           countDown.countDown
       }
@@ -75,7 +75,7 @@ class SupervisorHierarchySpec extends JUnitSuite {
     crasher ! Exit(crasher, new FireWorkerException("Fire the worker!"))
     crasher ! Exit(crasher, new FireWorkerException("Fire the worker!"))
 
-    assert(countDown.await(2, TimeUnit.SECONDS))      
+    assert(countDown.await(2, TimeUnit.SECONDS))
   }
 }
 
diff --git a/akka-core/src/test/scala/actor/TransactionalTypedActorSpec.scala b/akka-core/src/test/scala/actor/TransactionalTypedActorSpec.scala
index e8ac4c3fd7..c07c53935e 100644
--- a/akka-core/src/test/scala/actor/TransactionalTypedActorSpec.scala
+++ b/akka-core/src/test/scala/actor/TransactionalTypedActorSpec.scala
@@ -24,7 +24,7 @@ class TransactionalTypedActorSpec extends
   override def afterAll {
 //    ActorRegistry.shutdownAll
   }
-  
+
   describe("Declaratively supervised transactional in-memory Active Object ") {
     it("map should not rollback state for stateful server in case of success") {
       val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor], classOf[TransactionalTypedActorImpl])
diff --git a/akka-core/src/test/scala/actor/TypedActorContextSpec.scala b/akka-core/src/test/scala/actor/TypedActorContextSpec.scala
index 5c3fb629ad..11719650d6 100644
--- a/akka-core/src/test/scala/actor/TypedActorContextSpec.scala
+++ b/akka-core/src/test/scala/actor/TypedActorContextSpec.scala
@@ -24,7 +24,7 @@ class TypedActorContextSpec extends
       val pojo = TypedActor.newInstance(classOf[SimpleJavaPojo], classOf[SimpleJavaPojoImpl])
       val pojoCaller = TypedActor.newInstance(classOf[SimpleJavaPojoCaller], classOf[SimpleJavaPojoCallerImpl])
       pojoCaller.setPojo(pojo)
-      try { 
+      try {
         pojoCaller.getSenderFromSimpleJavaPojo should equal (pojoCaller)
       } catch {
         case e => fail("no sender available")
@@ -35,7 +35,7 @@ class TypedActorContextSpec extends
       val pojo = TypedActor.newInstance(classOf[SimpleJavaPojo], classOf[SimpleJavaPojoImpl])
       val pojoCaller = TypedActor.newInstance(classOf[SimpleJavaPojoCaller], classOf[SimpleJavaPojoCallerImpl])
       pojoCaller.setPojo(pojo)
-      try { 
+      try {
         pojoCaller.getSenderFutureFromSimpleJavaPojo.getClass.getName should equal (classOf[DefaultCompletableFuture[_]].getName)
       } catch {
         case e => fail("no sender future available", e)
diff --git a/akka-core/src/test/scala/actor/TypedActorLifecycleSpec.scala b/akka-core/src/test/scala/actor/TypedActorLifecycleSpec.scala
index 02a5712410..2db8820f9c 100644
--- a/akka-core/src/test/scala/actor/TypedActorLifecycleSpec.scala
+++ b/akka-core/src/test/scala/actor/TypedActorLifecycleSpec.scala
@@ -166,4 +166,4 @@ class TypedActorLifecycleSpec extends Spec with ShouldMatchers with BeforeAndAft
         }
     */
   }
-}
\ No newline at end of file
+}
diff --git a/akka-core/src/test/scala/routing/RoutingSpec.scala b/akka-core/src/test/scala/routing/RoutingSpec.scala
index b709714de9..747363efe6 100644
--- a/akka-core/src/test/scala/routing/RoutingSpec.scala
+++ b/akka-core/src/test/scala/routing/RoutingSpec.scala
@@ -172,4 +172,4 @@ class RoutingSpec extends junit.framework.TestCase with Suite with MustMatchers
 
     for(a <- List(t1,t2,d1,d2)) a.stop
   }
-}
\ No newline at end of file
+}
diff --git a/akka-core/src/test/scala/serialization/SerializableTypeClassActorSpec.scala b/akka-core/src/test/scala/serialization/SerializableTypeClassActorSpec.scala
index 7777fa6580..a9bcc35790 100644
--- a/akka-core/src/test/scala/serialization/SerializableTypeClassActorSpec.scala
+++ b/akka-core/src/test/scala/serialization/SerializableTypeClassActorSpec.scala
@@ -174,7 +174,7 @@ class MyStatelessActorWithMessagesInMailbox extends Actor {
 @serializable class MyJavaSerializableActor extends Actor {
   var count = 0
   self.receiveTimeout = Some(1000)
-  
+
   def receive = {
     case "hello" =>
       count = count + 1
diff --git a/akka-core/src/test/scala/stm/RefSpec.scala b/akka-core/src/test/scala/stm/RefSpec.scala
index 33ce43ab10..6e972152e5 100644
--- a/akka-core/src/test/scala/stm/RefSpec.scala
+++ b/akka-core/src/test/scala/stm/RefSpec.scala
@@ -153,4 +153,4 @@ class RefSpec extends Spec with ShouldMatchers {
       optGreater2 should be(None)
     }
   }
-}
\ No newline at end of file
+}
diff --git a/akka-core/src/test/scala/tickets/Proof001Spec.scala b/akka-core/src/test/scala/tickets/Proof001Spec.scala
index 29e4ca3137..5e179ec16d 100644
--- a/akka-core/src/test/scala/tickets/Proof001Spec.scala
+++ b/akka-core/src/test/scala/tickets/Proof001Spec.scala
@@ -7,4 +7,4 @@ import org.junit.Test
 class Proof001Spec extends JUnitSuite {
 
   @Test def thisFixesSomeSpecifiedBug = ()
-}
\ No newline at end of file
+}
diff --git a/akka-samples/akka-sample-camel/src/main/scala/Actors.scala b/akka-samples/akka-sample-camel/src/main/scala/Actors.scala
index f3b50d9c6e..64bdb19dfd 100644
--- a/akka-samples/akka-sample-camel/src/main/scala/Actors.scala
+++ b/akka-samples/akka-sample-camel/src/main/scala/Actors.scala
@@ -115,7 +115,7 @@ class PublisherBridge(uri: String, publisher: ActorRef) extends Actor with Consu
 
 class HttpConsumer(producer: ActorRef) extends Actor with Consumer {
   def endpointUri = "jetty:http://0.0.0.0:8875/"
-  
+
   protected def receive = {
     case msg => producer forward msg
   }
diff --git a/akka-samples/akka-sample-camel/src/test/scala/HttpConcurrencyTest.scala b/akka-samples/akka-sample-camel/src/test/scala/HttpConcurrencyTest.scala
index 71c5d02ce4..b98876a01d 100644
--- a/akka-samples/akka-sample-camel/src/test/scala/HttpConcurrencyTest.scala
+++ b/akka-samples/akka-sample-camel/src/test/scala/HttpConcurrencyTest.scala
@@ -98,4 +98,4 @@ object HttpConcurrencyTest {
       case msg => self.reply(msg)
     }
   }
-}
\ No newline at end of file
+}
diff --git a/akka-samples/akka-sample-lift/src/main/scala/akka/SimpleService.scala b/akka-samples/akka-sample-lift/src/main/scala/akka/SimpleService.scala
index 4d20b60448..b361fbb16b 100644
--- a/akka-samples/akka-sample-lift/src/main/scala/akka/SimpleService.scala
+++ b/akka-samples/akka-sample-lift/src/main/scala/akka/SimpleService.scala
@@ -91,4 +91,4 @@ object SimpleRestService extends RestHelper {
       //Return either the resulting NodeSeq or a default one
       (result getOrElse 

Error in counter

).asInstanceOf[Node] } - } \ No newline at end of file + } diff --git a/akka-samples/akka-sample-osgi/src/main/scala/osgiExample.scala b/akka-samples/akka-sample-osgi/src/main/scala/osgiExample.scala index 3c233fdf1f..18323d04d3 100644 --- a/akka-samples/akka-sample-osgi/src/main/scala/osgiExample.scala +++ b/akka-samples/akka-sample-osgi/src/main/scala/osgiExample.scala @@ -29,5 +29,5 @@ class EchoActor extends Actor { override def receive = { case x => self reply x - } + } } diff --git a/akka-spring/src/main/scala/StringReflect.scala b/akka-spring/src/main/scala/StringReflect.scala index ae32350e2d..9e8cab8172 100644 --- a/akka-spring/src/main/scala/StringReflect.scala +++ b/akka-spring/src/main/scala/StringReflect.scala @@ -1,11 +1,11 @@ /** * Copyright (C) 2009-2010 Scalable Solutions AB */ - + package se.scalablesolutions.akka.spring object StringReflect { - + /** * Implicit conversion from String to StringReflect. */ @@ -22,4 +22,4 @@ class StringReflect(val self: String) { val clazz = Class.forName(self) clazz.asInstanceOf[Class[T]] } -} \ No newline at end of file +} diff --git a/akka-spring/src/main/scala/TypedActorFactoryBean.scala b/akka-spring/src/main/scala/TypedActorFactoryBean.scala index 7ba4cf5061..af792ab1fe 100644 --- a/akka-spring/src/main/scala/TypedActorFactoryBean.scala +++ b/akka-spring/src/main/scala/TypedActorFactoryBean.scala @@ -27,7 +27,7 @@ import se.scalablesolutions.akka.util.{Logging, Duration} /** * Exception to use when something goes wrong during bean creation. - * + * * @author Johan Rask */ class AkkaBeansException(message: String, cause:Throwable) extends BeansException(message, cause) { @@ -158,7 +158,7 @@ class TypedActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging wit if (transactional) config.makeTransactionRequired config } - + def newInstanceFor[T <: AnyRef](clazz: Class[T]): T = { var ref = clazz.newInstance().asInstanceOf[T] postConstruct(setProperties(ref)) @@ -170,15 +170,15 @@ class TypedActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging wit private[akka] def hasInterface = (interface != null) && (!interface.isEmpty) - private[akka] def hasRestartCallbacks = - ((pre != null) && !pre.isEmpty) || + private[akka] def hasRestartCallbacks = + ((pre != null) && !pre.isEmpty) || ((post != null) && !post.isEmpty) private[akka] def hasShutdownCallback = ((shutdown != null) && !shutdown.isEmpty) - private[akka] def hasDispatcher = - (dispatcher != null) && - (dispatcher.dispatcherType != null) && + private[akka] def hasDispatcher = + (dispatcher != null) && + (dispatcher.dispatcherType != null) && (!dispatcher.dispatcherType.isEmpty) private[akka] def dispatcherInstance: MessageDispatcher = { diff --git a/akka-spring/src/test/scala/TypedActorFactoryBeanTest.scala b/akka-spring/src/test/scala/TypedActorFactoryBeanTest.scala index 9fb500240b..1526517da7 100644 --- a/akka-spring/src/test/scala/TypedActorFactoryBeanTest.scala +++ b/akka-spring/src/test/scala/TypedActorFactoryBeanTest.scala @@ -82,7 +82,7 @@ class TypedActorFactoryBeanTest extends Spec with ShouldMatchers { /* // ------ NOTE: Can't work now when we only support POJO with interface ----- - + it("should create a proxy of type ResourceEditor") { val bean = new TypedActorFactoryBean() // we must have a java class here diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 03a91cbe6c..f2b1dd33bc 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -517,7 +517,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { "org.aopalliance.*;version=1.0.0", // Provided by other bundles - "!se.scalablesolutions.akka.*", + "!se.scalablesolutions.akka.*", "!net.liftweb.*", "!com.google.inject.*", "!javax.transaction.*", @@ -573,7 +573,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { val jms_1_1 = "org.apache.geronimo.specs" % "geronimo-jms_1.1_spec" % "1.1.1" % "compile" intransitive val joda = "joda-time" % "joda-time" % "1.6" intransitive - override def packageAction = + override def packageAction = task { val libs: Seq[Path] = managedClasspath(config("compile")).get.toSeq val prjs: Seq[Path] = info.dependencies.toSeq.asInstanceOf[Seq[DefaultProject]] map { _.jarPath } @@ -709,7 +709,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { !jar.toString.endsWith("scala-library-2.7.7.jar") ) } - + def akkaArtifacts = descendents(info.projectPath / "dist", "*" + buildScalaVersion + "-" + version + ".jar") // ------------------------------------------------------------ diff --git a/project/plugins/Plugins.scala b/project/plugins/Plugins.scala index b66ee5267e..ce3319b885 100644 --- a/project/plugins/Plugins.scala +++ b/project/plugins/Plugins.scala @@ -21,7 +21,7 @@ class Plugins(info: ProjectInfo) extends PluginDefinition(info) { lazy val aquteModuleConfig = ModuleConfiguration("biz.aQute", AquteRepo) lazy val codeFellowModuleConfig = ModuleConfiguration("de.tuxed", EmbeddedRepo) lazy val spdeModuleConfig = ModuleConfiguration("us.technically.spde", DatabinderRepo) - + // ------------------------------------------------------------------------------------------------------------------- // Dependencies // ------------------------------------------------------------------------------------------------------------------- From 10ffeb6a300f1203812a84a1c787858efdf226ef Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Thu, 29 Jul 2010 21:19:33 +0200 Subject: [PATCH 072/188] Fixing Comparable problem --- akka-core/src/main/scala/actor/ActorRef.scala | 6 +++++- akka-core/src/main/scala/actor/ActorRegistry.scala | 9 ++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/akka-core/src/main/scala/actor/ActorRef.scala b/akka-core/src/main/scala/actor/ActorRef.scala index e84c0cfa6f..96c47d08e5 100644 --- a/akka-core/src/main/scala/actor/ActorRef.scala +++ b/akka-core/src/main/scala/actor/ActorRef.scala @@ -64,7 +64,7 @@ import com.google.protobuf.ByteString * * @author Jonas Bonér */ -trait ActorRef extends TransactionManagement { +trait ActorRef extends TransactionManagement with java.lang.Comparable[ActorRef] { // Only mutable for RemoteServer in order to maintain identity across nodes @volatile protected[akka] var _uuid = UUID.newUuid.toString @@ -203,6 +203,10 @@ trait ActorRef extends TransactionManagement { protected[akka] def currentMessage_=(msg: Option[MessageInvocation]) = guard.withGuard { _currentMessage = msg } protected[akka] def currentMessage = guard.withGuard { _currentMessage } + + /** comparison only takes uuid into account + */ + def compareTo(other: ActorRef) = this.uuid.compareTo(other.uuid) /** * Returns the uuid for the actor. diff --git a/akka-core/src/main/scala/actor/ActorRegistry.scala b/akka-core/src/main/scala/actor/ActorRegistry.scala index cebc2ec287..aea37432b7 100644 --- a/akka-core/src/main/scala/actor/ActorRegistry.scala +++ b/akka-core/src/main/scala/actor/ActorRegistry.scala @@ -29,11 +29,6 @@ case class ActorUnregistered(actor: ActorRef) extends ActorRegistryEvent * @author Jonas Bonér */ object ActorRegistry extends ListenerManagement { - - private val refComparator = new java.util.Comparator[ActorRef]{ - def compare(a: ActorRef,b: ActorRef) = a.uuid.compareTo(b.uuid) - } - private val actorsByUUID = new ConcurrentHashMap[String, ActorRef] private val actorsById = new ConcurrentHashMap[String, JSet[ActorRef]] private val actorsByClassName = new ConcurrentHashMap[String, JSet[ActorRef]] @@ -122,7 +117,7 @@ object ActorRegistry extends ListenerManagement { if (id eq null) throw new IllegalActorStateException("Actor.id is null " + actor) if (actorsById.containsKey(id)) actorsById.get(id).add(actor) else { - val set = new ConcurrentSkipListSet[ActorRef](refComparator) + val set = new ConcurrentSkipListSet[ActorRef] set.add(actor) actorsById.put(id, set) } @@ -131,7 +126,7 @@ object ActorRegistry extends ListenerManagement { val className = actor.actorClassName if (actorsByClassName.containsKey(className)) actorsByClassName.get(className).add(actor) else { - val set = new ConcurrentSkipListSet[ActorRef](refComparator) + val set = new ConcurrentSkipListSet[ActorRef] set.add(actor) actorsByClassName.put(className, set) } From 8c82e2724df137acaf6b2714ed49172d9b865eb4 Mon Sep 17 00:00:00 2001 From: Jonas Boner Date: Fri, 30 Jul 2010 00:18:43 +0200 Subject: [PATCH 073/188] Added UntypedActor and UntypedActorRef (+ tests) to work with untyped MDB-style actors in Java. --- .gitignore | 3 +- akka-core/src/main/scala/actor/Actor.scala | 13 +- akka-core/src/main/scala/actor/ActorRef.scala | 18 +- .../src/main/scala/actor/UntypedActor.scala | 562 +++++++++++++++++- .../akka/actor/ReplyUntypedActor.java | 28 + .../akka/actor/SampleUntypedActor.java | 53 ++ .../akka/actor/SenderUntypedActor.java | 44 ++ .../akka/actor/TestUntypedActor.java | 9 - .../akka/actor/UntypedActorTestState.java | 10 + ...typedActorFireForgetRequestReplySpec.scala | 86 +++ 10 files changed, 786 insertions(+), 40 deletions(-) create mode 100644 akka-core/src/test/java/se/scalablesolutions/akka/actor/ReplyUntypedActor.java create mode 100644 akka-core/src/test/java/se/scalablesolutions/akka/actor/SampleUntypedActor.java create mode 100644 akka-core/src/test/java/se/scalablesolutions/akka/actor/SenderUntypedActor.java delete mode 100644 akka-core/src/test/java/se/scalablesolutions/akka/actor/TestUntypedActor.java create mode 100644 akka-core/src/test/java/se/scalablesolutions/akka/actor/UntypedActorTestState.java create mode 100644 akka-core/src/test/scala/actor/untyped-actor/UntypedActorFireForgetRequestReplySpec.scala diff --git a/.gitignore b/.gitignore index 51b42bf7be..91a3be7969 100755 --- a/.gitignore +++ b/.gitignore @@ -39,4 +39,5 @@ run-codefellow .classpath .idea .scala_dependencies -multiverse.log \ No newline at end of file +multiverse.log +.eprj \ No newline at end of file diff --git a/akka-core/src/main/scala/actor/Actor.scala b/akka-core/src/main/scala/actor/Actor.scala index 1de3997c12..562a10a7d5 100644 --- a/akka-core/src/main/scala/actor/Actor.scala +++ b/akka-core/src/main/scala/actor/Actor.scala @@ -14,6 +14,7 @@ import se.scalablesolutions.akka.util.{Logging, Duration} import com.google.protobuf.Message import java.util.concurrent.TimeUnit +import java.net.InetSocketAddress /** * Implements the Transactor abstraction. E.g. a transactional actor. @@ -33,8 +34,9 @@ trait Transactor extends Actor { * * @author Jonas Bonér */ -abstract class RemoteActor(hostname: String, port: Int) extends Actor { - self.makeRemote(hostname, port) +abstract class RemoteActor(address: InetSocketAddress) extends Actor { + def this(hostname: String, port: Int) = this(new InetSocketAddress(hostname, port)) + self.makeRemote(address) } /** @@ -56,6 +58,7 @@ class ActorStartException private[akka](message: String) extends RuntimeExceptio class IllegalActorStateException private[akka](message: String) extends RuntimeException(message) class ActorKilledException private[akka](message: String) extends RuntimeException(message) class ActorInitializationException private[akka](message: String) extends RuntimeException(message) +class ActorTimeoutException private[akka](message: String) extends RuntimeException(message) /** * Actor factory module with factory methods for creating various kinds of Actors. @@ -73,9 +76,9 @@ object Actor extends Logging { type Receive = PartialFunction[Any, Unit] private[actor] val actorRefInCreation = new scala.util.DynamicVariable[Option[ActorRef]](None) - + /** - * Creates a Actor.actorOf out of the Actor with type T. + * Creates an ActorRef out of the Actor with type T. *
    *   import Actor._
    *   val actor = actorOf[MyActor]
@@ -91,7 +94,7 @@ object Actor extends Logging {
   def actorOf[T <: Actor : Manifest]: ActorRef = new LocalActorRef(manifest[T].erasure.asInstanceOf[Class[_ <: Actor]])
 
   /**
-   * Creates a Actor.actorOf out of the Actor. Allows you to pass in a factory function
+   * Creates an ActorRef out of the Actor. Allows you to pass in a factory function
    * that creates the Actor. Please note that this function can be invoked multiple
    * times if for example the Actor is supervised and needs to be restarted.
    * 

diff --git a/akka-core/src/main/scala/actor/ActorRef.scala b/akka-core/src/main/scala/actor/ActorRef.scala index ca55d6c1fa..3cc9878129 100644 --- a/akka-core/src/main/scala/actor/ActorRef.scala +++ b/akka-core/src/main/scala/actor/ActorRef.scala @@ -457,57 +457,41 @@ trait ActorRef extends TransactionManagement { * If the 'trapExit' member field has been set to at contain at least one exception class then it will * 'trap' these exceptions and automatically restart the linked actors according to the restart strategy * defined by the 'faultHandler'. - *

- * To be invoked from within the actor itself. */ def link(actorRef: ActorRef): Unit /** * Unlink the actor. - *

- * To be invoked from within the actor itself. */ def unlink(actorRef: ActorRef): Unit /** * Atomically start and link an actor. - *

- * To be invoked from within the actor itself. */ def startLink(actorRef: ActorRef): Unit /** * Atomically start, link and make an actor remote. - *

- * To be invoked from within the actor itself. */ def startLinkRemote(actorRef: ActorRef, hostname: String, port: Int): Unit /** * Atomically create (from actor class) and start an actor. - *

- * To be invoked from within the actor itself. */ def spawn[T <: Actor : Manifest]: ActorRef /** * Atomically create (from actor class), start and make an actor remote. - *

- * To be invoked from within the actor itself. */ def spawnRemote[T <: Actor: Manifest](hostname: String, port: Int): ActorRef /** * Atomically create (from actor class), start and link an actor. - *

- * To be invoked from within the actor itself. */ def spawnLink[T <: Actor: Manifest]: ActorRef /** * Atomically create (from actor class), start, link and make an actor remote. - *

- * To be invoked from within the actor itself. */ def spawnLinkRemote[T <: Actor : Manifest](hostname: String, port: Int): ActorRef @@ -587,7 +571,7 @@ trait ActorRef extends TransactionManagement { * * @author Jonas Bonér */ -sealed class LocalActorRef private[akka]( +class LocalActorRef private[akka]( private[this] var actorFactory: Either[Option[Class[_ <: Actor]], Option[() => Actor]] = Left(None)) extends ActorRef { diff --git a/akka-core/src/main/scala/actor/UntypedActor.scala b/akka-core/src/main/scala/actor/UntypedActor.scala index 7e45dee40d..3026369202 100644 --- a/akka-core/src/main/scala/actor/UntypedActor.scala +++ b/akka-core/src/main/scala/actor/UntypedActor.scala @@ -4,31 +4,577 @@ package se.scalablesolutions.akka.actor +import se.scalablesolutions.akka.dispatch._ +import se.scalablesolutions.akka.stm.global._ +import se.scalablesolutions.akka.config.{AllForOneStrategy, OneForOneStrategy, FaultHandlingStrategy} +import se.scalablesolutions.akka.config.ScalaConfig._ + +import java.net.InetSocketAddress + /** - * FIXME: document + * Subclass this abstract class to create a MDB-style untyped actor. + *

+ * This class is meant to be used from Java. + *

+ * Here is an example on how to create and use an UntypedActor: + *

+ *  public class SampleUntypedActor extends UntypedActor {
+ *    public void onReceive(Object message, UntypedActorRef context) throws Exception {
+ *      if (message instanceof String) {
+ *        String msg = (String)message;
+ *
+ *	      if (msg.equals("UseReply")) {
+ *	  	    // Reply to original sender of message using the 'replyUnsafe' method
+ *	  	    context.replyUnsafe(msg + ":" + context.getUuid());
+ *
+ *	      } else if (msg.equals("UseSender") && context.getSender().isDefined()) {	
+ *	  	    // Reply to original sender of message using the sender reference
+ *	  	    // also passing along my own refererence (the context)
+ *	  	    context.getSender().get().sendOneWay(msg, context); 
+ *
+ *        } else if (msg.equals("UseSenderFuture") && context.getSenderFuture().isDefined()) {	
+ *	  	    // Reply to original sender of message using the sender future reference
+ *	  	    context.getSenderFuture().get().completeWithResult(msg);
+ *
+ *        } else if (msg.equals("SendToSelf")) {
+ *	  	    // Send message to the actor itself recursively
+ *	  	    context.sendOneWay(msg)
+ *
+ *        } else if (msg.equals("ForwardMessage")) {
+ *          // Retreive an actor from the ActorRegistry by ID and get an ActorRef back
+ *          ActorRef actorRef = ActorRegistry.actorsFor("some-actor-id").head();
+ *          // Wrap the ActorRef in an UntypedActorRef and forward the message to this actor
+ *          UntypedActorRef.wrap(actorRef).forward(msg, context);
+ *
+ *        } else throw new IllegalArgumentException("Unknown message: " + message);
+ *      } else throw new IllegalArgumentException("Unknown message: " + message);
+ *    }
+ *   
+ *    public static void main(String[] args) {
+ *      UntypedActorRef actor = UntypedActor.actorOf(SampleUntypedActor.class);
+ *      actor.start();
+ *      actor.sendOneWay("SendToSelf");
+ *      actor.stop();
+ *    }
+ *  }
+ * 
* * @author Jonas Bonér */ abstract class UntypedActor extends Actor { - protected[akka] var context: Option[ActorContext] = None + protected[akka] var context: Option[UntypedActorRef] = None - protected def receive = { + final protected def receive = { case msg => if (context.isEmpty) { - val ctx = new ActorContext(self) + val ctx = new UntypedActorRef(self) context = Some(ctx) onReceive(msg, ctx) } else onReceive(msg, context.get) } - def onReceive(message: Any, context: ActorContext): Unit + @throws(classOf[Exception]) + def onReceive(message: Any, context: UntypedActorRef): Unit } /** - * FIXME: document + * Implements the Transactor abstraction. E.g. a transactional UntypedActor. * * @author Jonas Bonér */ -class ActorContext(self: ActorRef) { +abstract class UntypedTransactor extends UntypedActor { + self.makeTransactionRequired +} + +/** + * Extend this abstract class to create a remote UntypedActor. + * + * @author Jonas Bonér + */ +abstract class RemoteUntypedActor(address: InetSocketAddress) extends UntypedActor { + def this(hostname: String, port: Int) = this(new InetSocketAddress(hostname, port)) + self.makeRemote(address) +} + +/** + * Factory object for creating and managing 'UntypedActor's. Meant to be used from Java. + *

+ * Example on how to create an actor: + *

+ *   ActorRef actor = UntypedActor.actorOf(MyUntypedActor.class);
+ *   actor.start();
+ *   actor.sendOneWay(message, context)
+ *   actor.stop();
+ * 
+ * You can create and start the actor in one statement like this: + *
+ *   ActorRef actor = UntypedActor.actorOf(MyUntypedActor.class).start();
+ * 
+ * + * @author Jonas Bonér + */ +object UntypedActor { -} \ No newline at end of file + /** + * Creates an ActorRef out of the Actor. Allows you to pass in the class for the Actor. + *

+ * Example in Java: + *

+   *   ActorRef actor = UntypedActor.actorOf(MyUntypedActor.class);
+   *   actor.start();
+   *   actor.sendOneWay(message, context)
+   *   actor.stop();
+   * 
+ * You can create and start the actor in one statement like this: + *
+   *   ActorRef actor = UntypedActor.actorOf(MyUntypedActor.class).start();
+   * 
+ */ + def actorOf(clazz: Class[_]): UntypedActorRef = { + if (!clazz.isInstanceOf[Class[_ <: UntypedActor]]) throw new IllegalArgumentException( + "Class [" + clazz.getName + "] passed into the 'actorOf' factory method needs to be assignable from 'UntypedActor'") + UntypedActorRef.wrap(new LocalActorRef(() => clazz.newInstance.asInstanceOf[Actor])) + } + + /** + * NOTE: Use this convenience method with care, do NOT make it possible to get a reference to the + * UntypedActor instance directly, but only through its 'UntypedActorRef' wrapper reference. + *

+ * Creates an ActorRef out of the Actor. Allows you to pass in the instance for the Actor. Only + * use this method when you need to pass in constructor arguments into the 'UntypedActor'. + *

+ * Example in Java: + *

+   *   ActorRef actor = UntypedActor.actorOf(new MyUntypedActor("service:name", 5));
+   *   actor.start();
+   *   actor.sendOneWay(message, context)
+   *   actor.stop();
+   * 
+ * You can create and start the actor in one statement like this: + *
+   *   ActorRef actor = UntypedActor.actorOf(MyUntypedActor.class).start();
+   * 
+ */ + def actorOf(actorInstance: UntypedActor): UntypedActorRef = UntypedActorRef.wrap(new LocalActorRef(() => actorInstance)) +} + +/** + * Use this class if you need to wrap an 'ActorRef' in the more Java-friendly 'UntypedActorRef'. + * + * @author Jonas Bonér + */ +object UntypedActorRef { + def wrap(actorRef: ActorRef) = new UntypedActorRef(actorRef) +} + +/** + * A Java-friendly wrapper class around the 'ActorRef'. + * + * @author Jonas Bonér + */ +class UntypedActorRef(val actorRef: ActorRef) { + + /** + * Returns the uuid for the actor. + */ + def getUuid(): String = actorRef.uuid + + /** + * Identifier for actor, does not have to be a unique one. Default is the 'uuid'. + *

+ * This field is used for logging, AspectRegistry.actorsFor(id), identifier for remote + * actor in RemoteServer etc.But also as the identifier for persistence, which means + * that you can use a custom name to be able to retrieve the "correct" persisted state + * upon restart, remote restart etc. + */ + def setId(id: String) = actorRef.id = id + def getId(): String = actorRef.id + + /** + * Defines the default timeout for '!!' and '!!!' invocations, + * e.g. the timeout for the future returned by the call to '!!' and '!!!'. + */ + def setTimeout(timeout: Long) = actorRef.timeout = timeout + def getTimeout(): Long = actorRef.timeout + + /** + * Defines the default timeout for an initial receive invocation. + * When specified, the receive function should be able to handle a 'ReceiveTimeout' message. + */ + def setReceiveTimeout(timeout: Long) = actorRef.receiveTimeout = Some(timeout) + def getReceiveTimeout(): Option[Long] = actorRef.receiveTimeout + + /** + * Set 'trapExit' to the list of exception classes that the actor should be able to trap + * from the actor it is supervising. When the supervising actor throws these exceptions + * then they will trigger a restart. + *

+ * + * Trap all exceptions: + *

+   * context.setTrapExit(new Class[]{Throwable.class});
+   * 
+ * + * Trap specific exceptions only: + *
+   * context.setTrapExit(new Class[]{MyApplicationException.class, MyApplicationError.class});
+   * 
+ */ + def setTrapExit(exceptions: Array[Class[_ <: Throwable]]) = actorRef.trapExit = exceptions.toList + def getTrapExit(): Array[Class[_ <: Throwable]] = actorRef.trapExit.toArray + + /** + * If 'trapExit' is set for the actor to act as supervisor, then a 'faultHandler' must be defined. + *

+ * Can be one of: + *

+   *  context.setFaultHandler(new AllForOneStrategy(maxNrOfRetries, withinTimeRange));
+   * 
+ * Or: + *
+   *  context.setFaultHandler(new OneForOneStrategy(maxNrOfRetries, withinTimeRange));
+   * 
+ */ + def setFaultHandler(handler: FaultHandlingStrategy) = actorRef.faultHandler = Some(handler) + def getFaultHandler(): Option[FaultHandlingStrategy] = actorRef.faultHandler + + /** + * Defines the life-cycle for a supervised actor. + */ + def setLifeCycle(lifeCycle: LifeCycle) = actorRef.lifeCycle = Some(lifeCycle) + def getLifeCycle(): Option[LifeCycle] = actorRef.lifeCycle + + /** + * The default dispatcher is the Dispatchers.globalExecutorBasedEventDrivenDispatcher();. + * This means that all actors will share the same event-driven executor based dispatcher. + *

+ * You can override it so it fits the specific use-case that the actor is used for. + * See the se.scalablesolutions.akka.dispatch.Dispatchers class for the different + * dispatchers available. + *

+ * The default is also that all actors that are created and spawned from within this actor + * is sharing the same dispatcher as its creator. + */ + def setDispatcher(dispatcher: MessageDispatcher) = actorRef.dispatcher = dispatcher + def getDispatcher(): MessageDispatcher = actorRef.dispatcher + + /** + * The reference sender Actor of the last received message. + * Is defined if the message was sent from another Actor, else None. + */ + def getSender(): Option[UntypedActorRef] = actorRef.sender match { + case Some(s) => Some(UntypedActorRef.wrap(s)) + case None => None + } + + /** + * The reference sender future of the last received message. + * Is defined if the message was sent with sent with 'sendRequestReply' or 'sendRequestReplyFuture', else None. + */ + def getSenderFuture(): Option[CompletableFuture[Any]] = actorRef.senderFuture + + /** + * Starts up the actor and its message queue. + */ + def start(): UntypedActorRef = UntypedActorRef.wrap(actorRef.start) + + /** + * Shuts down the actor its dispatcher and message queue. + * Alias for 'stop'. + */ + def exit() = stop() + + /** + * Shuts down the actor its dispatcher and message queue. + */ + def stop(): Unit = actorRef.stop() + + /** + * Sends a one-way asynchronous message. E.g. fire-and-forget semantics. + *

+ *

+   *   actor.sendOneWay(message);
+   * 
+ *

+ */ + def sendOneWay(message: AnyRef) = actorRef.!(message)(None) + + /** + * Sends a one-way asynchronous message. E.g. fire-and-forget semantics. + *

+ * Allows you to pass along the sender of the messag. + *

+ *

+   *   actor.sendOneWay(message, context);
+   * 
+ *

+ */ + def sendOneWay(message: AnyRef, sender: UntypedActorRef) = + if (sender eq null) actorRef.!(message)(None) + else actorRef.!(message)(Some(sender.actorRef)) + + /** + * Sends a message asynchronously and waits on a future for a reply message under the hood. The timeout is taken from + * the default timeout in the Actor. + *

+ * It waits on the reply either until it receives it or until the timeout expires + * (which will throw an ActorTimeoutException). E.g. send-and-receive-eventually semantics. + *

+ * NOTE: + * Use this method with care. In most cases it is better to use 'sendOneWay' together with 'context.getSender()' to + * implement request/response message exchanges. + *

+ * If you are sending messages using sendRequestReply then you have to use context.reply(..) + * to send a reply message to the original sender. If not then the sender will block until the timeout expires. + */ + def sendRequestReply(message: AnyRef): AnyRef = + actorRef.!!(message)(None).getOrElse(throw new ActorTimeoutException( + "Message [" + message + + "]\n\tsent to [" + actorRef.actorClassName + + "]\n\twith timeout [" + actorRef.timeout + + "]\n\ttimed out.")) + .asInstanceOf[AnyRef] + + /** + * Sends a message asynchronously and waits on a future for a reply message under the hood. The timeout is taken from + * the default timeout in the Actor. + *

+ * It waits on the reply either until it receives it or until the timeout expires + * (which will throw an ActorTimeoutException). E.g. send-and-receive-eventually semantics. + *

+ * NOTE: + * Use this method with care. In most cases it is better to use 'sendOneWay' together with 'context.getSender()' to + * implement request/response message exchanges. + *

+ * If you are sending messages using sendRequestReply then you have to use context.reply(..) + * to send a reply message to the original sender. If not then the sender will block until the timeout expires. + */ + def sendRequestReply(message: AnyRef, sender: UntypedActorRef): AnyRef = { + val result = if (sender eq null) actorRef.!!(message)(None) + else actorRef.!!(message)(Some(sender.actorRef)) + result.getOrElse(throw new ActorTimeoutException( + "Message [" + message + + "]\n\tsent to [" + actorRef.actorClassName + + "]\n\tfrom [" + sender.actorRef.actorClassName + + "]\n\twith timeout [" + actorRef.timeout + + "]\n\ttimed out.")) + .asInstanceOf[AnyRef] + } + + /** + * Sends a message asynchronously and waits on a future for a reply message under the hood. + *

+ * It waits on the reply either until it receives it or until the timeout expires + * (which will throw an ActorTimeoutException). E.g. send-and-receive-eventually semantics. + *

+ * NOTE: + * Use this method with care. In most cases it is better to use 'sendOneWay' together with 'context.getSender()' to + * implement request/response message exchanges. + *

+ * If you are sending messages using sendRequestReply then you have to use context.reply(..) + * to send a reply message to the original sender. If not then the sender will block until the timeout expires. + */ + def sendRequestReply(message: AnyRef, timeout: Long): AnyRef = + actorRef.!!(message, timeout)(None).getOrElse(throw new ActorTimeoutException( + "Message [" + message + + "]\n\tsent to [" + actorRef.actorClassName + + "]\n\twith timeout [" + timeout + + "]\n\ttimed out.")) + .asInstanceOf[AnyRef] + + /** + * Sends a message asynchronously and waits on a future for a reply message under the hood. + *

+ * It waits on the reply either until it receives it or until the timeout expires + * (which will throw an ActorTimeoutException). E.g. send-and-receive-eventually semantics. + *

+ * NOTE: + * Use this method with care. In most cases it is better to use 'sendOneWay' together with 'context.getSender()' to + * implement request/response message exchanges. + *

+ * If you are sending messages using sendRequestReply then you have to use context.reply(..) + * to send a reply message to the original sender. If not then the sender will block until the timeout expires. + */ + def sendRequestReply(message: AnyRef, timeout: Long, sender: UntypedActorRef): AnyRef = { + val result = if (sender eq null) actorRef.!!(message, timeout)(None) + else actorRef.!!(message)(Some(sender.actorRef)) + result.getOrElse(throw new ActorTimeoutException( + "Message [" + message + + "]\n\tsent to [" + actorRef.actorClassName + + "]\n\tfrom [" + sender.actorRef.actorClassName + + "]\n\twith timeout [" + timeout + + "]\n\ttimed out.")) + .asInstanceOf[AnyRef] + } + + /** + * Sends a message asynchronously returns a future holding the eventual reply message. The timeout is taken from + * the default timeout in the Actor. + *

+ * NOTE: + * Use this method with care. In most cases it is better to use 'sendOneWay' together with the 'context.getSender()' to + * implement request/response message exchanges. + *

+ * If you are sending messages using sendRequestReplyFuture then you have to use context.reply(..) + * to send a reply message to the original sender. If not then the sender will block until the timeout expires. + */ + def sendRequestReplyFuture(message: AnyRef): Future[_] = actorRef.!!!(message)(None) + + /** + * Sends a message asynchronously returns a future holding the eventual reply message. The timeout is taken from + * the default timeout in the Actor. + *

+ * NOTE: + * Use this method with care. In most cases it is better to use 'sendOneWay' together with the 'context.getSender()' to + * implement request/response message exchanges. + *

+ * If you are sending messages using sendRequestReplyFuture then you have to use context.reply(..) + * to send a reply message to the original sender. If not then the sender will block until the timeout expires. + */ + def sendRequestReplyFuture(message: AnyRef, sender: UntypedActorRef): Future[_] = + if (sender eq null) actorRef.!!!(message)(None) + else actorRef.!!!(message)(Some(sender.actorRef)) + + /** + * Sends a message asynchronously returns a future holding the eventual reply message. + *

+ * NOTE: + * Use this method with care. In most cases it is better to use 'sendOneWay' together with the 'context.getSender()' to + * implement request/response message exchanges. + *

+ * If you are sending messages using sendRequestReplyFuture then you have to use context.reply(..) + * to send a reply message to the original sender. If not then the sender will block until the timeout expires. + */ + def sendRequestReplyFuture(message: AnyRef, timeout: Long): Future[_] = actorRef.!!!(message, timeout)(None) + + /** + * Sends a message asynchronously returns a future holding the eventual reply message. + *

+ * NOTE: + * Use this method with care. In most cases it is better to use 'sendOneWay' together with the 'context.getSender()' to + * implement request/response message exchanges. + *

+ * If you are sending messages using sendRequestReplyFuture then you have to use context.reply(..) + * to send a reply message to the original sender. If not then the sender will block until the timeout expires. + */ + def sendRequestReplyFuture(message: AnyRef, timeout: Long, sender: UntypedActorRef): Future[_] = + if (sender eq null) actorRef.!!!(message, timeout)(None) + else actorRef.!!!(message)(Some(sender.actorRef)) + + /** + * Forwards the message and passes the original sender actor as the sender. + *

+ * Works with 'sendOneWay', 'sendRequestReply' and 'sendRequestReplyFuture'. + */ + def forward(message: AnyRef, sender: UntypedActorRef): Unit = + if (sender eq null) throw new IllegalArgumentException("The 'sender' argument to 'forward' can't be null") + else actorRef.forward(message)(Some(sender.actorRef)) + + /** + * Use context.replyUnsafe(..) to reply with a message to the original sender of the message currently + * being processed. + *

+ * Throws an IllegalStateException if unable to determine what to reply to. + */ + def replyUnsafe(message: AnyRef): Unit = actorRef.reply(message) + + /** + * Use context.replySafe(..) to reply with a message to the original sender of the message currently + * being processed. + *

+ * Returns true if reply was sent, and false if unable to determine what to reply to. + */ + def replySafe(message: AnyRef): Boolean = actorRef.reply_?(message) + + /** + * Returns the class for the Actor instance that is managed by the ActorRef. + */ + def getActorClass(): Class[_ <: Actor] = actorRef.actorClass + + /** + * Returns the class name for the Actor instance that is managed by the ActorRef. + */ + def getActorClassName(): String = actorRef.actorClassName + + /** + * Invoking 'makeRemote' means that an actor will be moved to and invoked on a remote host. + */ + def makeRemote(hostname: String, port: Int): Unit = actorRef.makeRemote(hostname, port) + + /** + * Invoking 'makeRemote' means that an actor will be moved to and invoked on a remote host. + */ + def makeRemote(address: InetSocketAddress): Unit = actorRef.makeRemote(address) + + /** + * Invoking 'makeTransactionRequired' means that the actor will **start** a new transaction if non exists. + * However, it will always participate in an existing transaction. + */ + def makeTransactionRequired(): Unit = actorRef.makeTransactionRequired + + /** + * Sets the transaction configuration for this actor. Needs to be invoked before the actor is started. + */ + def setTransactionConfig(config: TransactionConfig): Unit = actorRef.transactionConfig = config + + /** + * Get the transaction configuration for this actor. + */ + def getTransactionConfig(): TransactionConfig = actorRef.transactionConfig + + /** + * Gets the remote address for the actor, if any, else None. + */ + def getRemoteAddress(): Option[InetSocketAddress] = actorRef.remoteAddress + + /** + * Returns the home address and port for this actor. + */ + def getHomeAddress(): InetSocketAddress = actorRef.homeAddress + + /** + * Set the home address and port for this actor. + */ + def setHomeAddress(hostnameAndPort: Tuple2[String, Int]): Unit = actorRef.homeAddress = hostnameAndPort + + /** + * Set the home address and port for this actor. + */ + def setHomeAddress(address: InetSocketAddress): Unit = actorRef.homeAddress = address + + /** + * Links an other actor to this actor. Links are unidirectional and means that a the linking actor will + * receive a notification if the linked actor has crashed. + *

+ * If the 'trapExit' member field has been set to at contain at least one exception class then it will + * 'trap' these exceptions and automatically restart the linked actors according to the restart strategy + * defined by the 'faultHandler'. + */ + def link(actor: UntypedActorRef): Unit = actorRef.link(actor.actorRef) + + /** + * Unlink the actor. + */ + def unlink(actor: UntypedActorRef): Unit = actorRef.unlink(actor.actorRef) + + /** + * Atomically start and link an actor. + */ + def startLink(actor: UntypedActorRef): Unit = actorRef.startLink(actor.actorRef) + + /** + * Atomically start, link and make an actor remote. + */ + def startLinkRemote(actor: UntypedActorRef, hostname: String, port: Int): Unit = + actorRef.startLinkRemote(actor.actorRef, hostname, port) + + /** + * Returns the mailbox size. + */ + def getMailboxSize(): Int = actorRef.mailboxSize + + /** + * Returns the current supervisor if there is one, null if not. + */ + def getSupervisor(): UntypedActorRef = UntypedActorRef.wrap(actorRef.supervisor.getOrElse(null)) +} diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/ReplyUntypedActor.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/ReplyUntypedActor.java new file mode 100644 index 0000000000..c50e1e8b3d --- /dev/null +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/ReplyUntypedActor.java @@ -0,0 +1,28 @@ +package se.scalablesolutions.akka.actor; + +import se.scalablesolutions.akka.actor.*; + +public class ReplyUntypedActor extends UntypedActor { + public void onReceive(Object message, UntypedActorRef context) throws Exception { + if (message instanceof String) { + String str = (String)message; + + if (str.equals("ReplyToSendOneWayUsingReply")) { + context.replyUnsafe("Reply"); + } else if (str.equals("ReplyToSendOneWayUsingSender")) { + context.getSender().get().sendOneWay("Reply"); + + } else if (str.equals("ReplyToSendRequestReplyUsingReply")) { + context.replyUnsafe("Reply"); + } else if (str.equals("ReplyToSendRequestReplyUsingFuture")) { + context.getSenderFuture().get().completeWithResult("Reply"); + + } else if (str.equals("ReplyToSendRequestReplyFutureUsingReply")) { + context.replyUnsafe("Reply"); + } else if (str.equals("ReplyToSendRequestReplyFutureUsingFuture")) { + context.getSenderFuture().get().completeWithResult("Reply"); + + } else throw new IllegalArgumentException("Unknown message: " + str); + } else throw new IllegalArgumentException("Unknown message: " + message); + } +} diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SampleUntypedActor.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SampleUntypedActor.java new file mode 100644 index 0000000000..41f125dd98 --- /dev/null +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SampleUntypedActor.java @@ -0,0 +1,53 @@ +/** + * Copyright (C) 2009-2010 Scalable Solutions AB + */ +package se.scalablesolutions.akka.actor; + +import se.scalablesolutions.akka.actor.*; + +/** + * Here is an example on how to create and use an UntypedActor. + * + * @author Jonas Bonér + */ +public class SampleUntypedActor extends UntypedActor { + + public void onReceive(Object message, UntypedActorRef context) throws Exception { + if (message instanceof String) { + String msg = (String)message; + System.out.println("Received message: " + msg); + + if (msg.equals("UseReply")) { + // Reply to original sender of message using the 'replyUnsafe' method + context.replyUnsafe(msg + ":" + context.getUuid()); + + } else if (msg.equals("UseSender") && context.getSender().isDefined()) { + // Reply to original sender of message using the sender reference + // also passing along my own refererence (the context) + context.getSender().get().sendOneWay(msg, context); + + } else if (msg.equals("UseSenderFuture") && context.getSenderFuture().isDefined()) { + // Reply to original sender of message using the sender future reference + context.getSenderFuture().get().completeWithResult(msg); + + } else if (msg.equals("SendToSelf")) { + // Send fire-forget message to the actor itself recursively + context.sendOneWay(msg); + + } else if (msg.equals("ForwardMessage")) { + // Retreive an actor from the ActorRegistry by ID and get an ActorRef back + ActorRef actorRef = ActorRegistry.actorsFor("some-actor-id").head(); + // Wrap the ActorRef in an UntypedActorRef and forward the message to this actor + UntypedActorRef.wrap(actorRef).forward(msg, context); + + } else throw new IllegalArgumentException("Unknown message: " + message); + } else throw new IllegalArgumentException("Unknown message: " + message); + } + + public static void main(String[] args) { + UntypedActorRef actor = UntypedActor.actorOf(SampleUntypedActor.class); + actor.start(); + actor.sendOneWay("SendToSelf"); + actor.stop(); + } +} diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SenderUntypedActor.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SenderUntypedActor.java new file mode 100644 index 0000000000..84adc5da7a --- /dev/null +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SenderUntypedActor.java @@ -0,0 +1,44 @@ +package se.scalablesolutions.akka.actor; + +import se.scalablesolutions.akka.actor.*; +import se.scalablesolutions.akka.dispatch.CompletableFuture; + +public class SenderUntypedActor extends UntypedActor { + private UntypedActorRef replyActor = null; + + public void onReceive(Object message, UntypedActorRef context) throws Exception { + if (message instanceof UntypedActorRef) replyActor = (UntypedActorRef)message; + else if (message instanceof String) { + if (replyActor == null) throw new IllegalStateException("Need to receive a ReplyUntypedActor before any other message."); + String str = (String)message; + + if (str.equals("ReplyToSendOneWayUsingReply")) { + replyActor.sendOneWay("ReplyToSendOneWayUsingReply", context); + } else if (str.equals("ReplyToSendOneWayUsingSender")) { + replyActor.sendOneWay("ReplyToSendOneWayUsingSender", context); + + } else if (str.equals("ReplyToSendRequestReplyUsingReply")) { + UntypedActorTestState.log = (String)replyActor.sendRequestReply("ReplyToSendRequestReplyUsingReply", context); + UntypedActorTestState.finished.await(); + } else if (str.equals("ReplyToSendRequestReplyUsingFuture")) { + UntypedActorTestState.log = (String)replyActor.sendRequestReply("ReplyToSendRequestReplyUsingFuture", context); + UntypedActorTestState.finished.await(); + + } else if (str.equals("ReplyToSendRequestReplyFutureUsingReply")) { + CompletableFuture future = (CompletableFuture)replyActor.sendRequestReplyFuture("ReplyToSendRequestReplyFutureUsingReply", context); + future.await(); + UntypedActorTestState.log = (String)future.result().get(); + UntypedActorTestState.finished.await(); + } else if (str.equals("ReplyToSendRequestReplyFutureUsingFuture")) { + CompletableFuture future = (CompletableFuture)replyActor.sendRequestReplyFuture("ReplyToSendRequestReplyFutureUsingFuture", context); + future.await(); + UntypedActorTestState.log = (String)future.result().get(); + UntypedActorTestState.finished.await(); + + } else if (str.equals("Reply")) { + UntypedActorTestState.log = "Reply"; + UntypedActorTestState.finished.await(); + } + } + } +} diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/TestUntypedActor.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/TestUntypedActor.java deleted file mode 100644 index 7a1d2982e9..0000000000 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/TestUntypedActor.java +++ /dev/null @@ -1,9 +0,0 @@ -package se.scalablesolutions.akka.actor; - -import se.scalablesolutions.akka.actor.*; - -public class TestUntypedActor extends UntypedActor { - public void onReceive(Object message, ActorContext context) { - System.out.println("TestUntypedActor got " + message); - } -} \ No newline at end of file diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/UntypedActorTestState.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/UntypedActorTestState.java new file mode 100644 index 0000000000..b94c5870fd --- /dev/null +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/UntypedActorTestState.java @@ -0,0 +1,10 @@ +package se.scalablesolutions.akka.actor; + +import se.scalablesolutions.akka.actor.*; + +import java.util.concurrent.CyclicBarrier; + +public class UntypedActorTestState { + public static String log = "NIL"; + public static CyclicBarrier finished = null; +} diff --git a/akka-core/src/test/scala/actor/untyped-actor/UntypedActorFireForgetRequestReplySpec.scala b/akka-core/src/test/scala/actor/untyped-actor/UntypedActorFireForgetRequestReplySpec.scala new file mode 100644 index 0000000000..89a05eca9c --- /dev/null +++ b/akka-core/src/test/scala/actor/untyped-actor/UntypedActorFireForgetRequestReplySpec.scala @@ -0,0 +1,86 @@ +package se.scalablesolutions.akka.actor + +import java.util.concurrent.{TimeUnit, CyclicBarrier, TimeoutException} + +import org.scalatest.WordSpec +import org.scalatest.matchers.MustMatchers + +import se.scalablesolutions.akka.dispatch.Dispatchers +import Actor._ + +class UntypedActorFireForgetRequestReplySpec extends WordSpec with MustMatchers { + + "An UntypedActor" should { + "reply to message sent with 'sendOneWay' using 'reply'" in { + UntypedActorTestState.finished = new CyclicBarrier(2); + UntypedActorTestState.log = "NIL"; + val replyActor = UntypedActor.actorOf(classOf[ReplyUntypedActor]).start + val senderActor = UntypedActor.actorOf(classOf[SenderUntypedActor]).start + senderActor.sendOneWay(replyActor) + senderActor.sendOneWay("ReplyToSendOneWayUsingReply") + try { UntypedActorTestState.finished.await(1L, TimeUnit.SECONDS) } + catch { case e: TimeoutException => fail("Never got the message") } + UntypedActorTestState.log must be ("Reply") + } + + "reply to message sent with 'sendOneWay' using 'sender' reference" in { + UntypedActorTestState.finished = new CyclicBarrier(2); + UntypedActorTestState.log = "NIL"; + val replyActor = UntypedActor.actorOf(classOf[ReplyUntypedActor]).start + val senderActor = UntypedActor.actorOf(classOf[SenderUntypedActor]).start + senderActor.sendOneWay(replyActor) + senderActor.sendOneWay("ReplyToSendOneWayUsingSender") + try { UntypedActorTestState.finished.await(1L, TimeUnit.SECONDS) } + catch { case e: TimeoutException => fail("Never got the message") } + UntypedActorTestState.log must be ("Reply") + } + + "reply to message sent with 'sendRequestReply' using 'reply'" in { + UntypedActorTestState.finished = new CyclicBarrier(2); + UntypedActorTestState.log = "NIL"; + val replyActor = UntypedActor.actorOf(classOf[ReplyUntypedActor]).start + val senderActor = UntypedActor.actorOf(classOf[SenderUntypedActor]).start + senderActor.sendOneWay(replyActor) + senderActor.sendOneWay("ReplyToSendRequestReplyUsingReply") + try { UntypedActorTestState.finished.await(1L, TimeUnit.SECONDS) } + catch { case e: TimeoutException => fail("Never got the message") } + UntypedActorTestState.log must be ("Reply") + } + + "reply to message sent with 'sendRequestReply' using 'sender future' reference" in { + UntypedActorTestState.finished = new CyclicBarrier(2); + UntypedActorTestState.log = "NIL"; + val replyActor = UntypedActor.actorOf(classOf[ReplyUntypedActor]).start + val senderActor = UntypedActor.actorOf(classOf[SenderUntypedActor]).start + senderActor.sendOneWay(replyActor) + senderActor.sendOneWay("ReplyToSendRequestReplyUsingFuture") + try { UntypedActorTestState.finished.await(1L, TimeUnit.SECONDS) } + catch { case e: TimeoutException => fail("Never got the message") } + UntypedActorTestState.log must be ("Reply") + } + + "reply to message sent with 'sendRequestReplyFuture' using 'reply'" in { + UntypedActorTestState.finished = new CyclicBarrier(2); + UntypedActorTestState.log = "NIL"; + val replyActor = UntypedActor.actorOf(classOf[ReplyUntypedActor]).start + val senderActor = UntypedActor.actorOf(classOf[SenderUntypedActor]).start + senderActor.sendOneWay(replyActor) + senderActor.sendOneWay("ReplyToSendRequestReplyFutureUsingReply") + try { UntypedActorTestState.finished.await(1L, TimeUnit.SECONDS) } + catch { case e: TimeoutException => fail("Never got the message") } + UntypedActorTestState.log must be ("Reply") + } + + "reply to message sent with 'sendRequestReplyFuture' using 'sender future' reference" in { + UntypedActorTestState.finished = new CyclicBarrier(2); + UntypedActorTestState.log = "NIL"; + val replyActor = UntypedActor.actorOf(classOf[ReplyUntypedActor]).start + val senderActor = UntypedActor.actorOf(classOf[SenderUntypedActor]).start + senderActor.sendOneWay(replyActor) + senderActor.sendOneWay("ReplyToSendRequestReplyFutureUsingFuture") + try { UntypedActorTestState.finished.await(1L, TimeUnit.SECONDS) } + catch { case e: TimeoutException => fail("Never got the message") } + UntypedActorTestState.log must be ("Reply") + } + } +} From a4d246ea4f2aa5dfede344ff139d1715e3f74228 Mon Sep 17 00:00:00 2001 From: Jonas Boner Date: Fri, 30 Jul 2010 00:45:33 +0200 Subject: [PATCH 074/188] dos2unix --- .../src/main/scala/actor/UntypedActor.scala | 18 +++++++++--------- .../akka/actor/SampleUntypedActor.java | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/akka-core/src/main/scala/actor/UntypedActor.scala b/akka-core/src/main/scala/actor/UntypedActor.scala index 3026369202..3d5f0b8e59 100644 --- a/akka-core/src/main/scala/actor/UntypedActor.scala +++ b/akka-core/src/main/scala/actor/UntypedActor.scala @@ -19,32 +19,32 @@ import java.net.InetSocketAddress * Here is an example on how to create and use an UntypedActor: *

  *  public class SampleUntypedActor extends UntypedActor {
- *    public void onReceive(Object message, UntypedActorRef context) throws Exception {
+ *    public void onReceive(Object message, UntypedActorRef self) throws Exception {
  *      if (message instanceof String) {
  *        String msg = (String)message;
  *
  *	      if (msg.equals("UseReply")) {
  *	  	    // Reply to original sender of message using the 'replyUnsafe' method
- *	  	    context.replyUnsafe(msg + ":" + context.getUuid());
+ *	  	    self.replyUnsafe(msg + ":" + self.getUuid());
  *
- *	      } else if (msg.equals("UseSender") && context.getSender().isDefined()) {	
+ *	      } else if (msg.equals("UseSender") && self.getSender().isDefined()) {	
  *	  	    // Reply to original sender of message using the sender reference
- *	  	    // also passing along my own refererence (the context)
- *	  	    context.getSender().get().sendOneWay(msg, context); 
+ *	  	    // also passing along my own refererence (the self)
+ *	  	    self.getSender().get().sendOneWay(msg, self); 
  *
- *        } else if (msg.equals("UseSenderFuture") && context.getSenderFuture().isDefined()) {	
+ *        } else if (msg.equals("UseSenderFuture") && self.getSenderFuture().isDefined()) {	
  *	  	    // Reply to original sender of message using the sender future reference
- *	  	    context.getSenderFuture().get().completeWithResult(msg);
+ *	  	    self.getSenderFuture().get().completeWithResult(msg);
  *
  *        } else if (msg.equals("SendToSelf")) {
  *	  	    // Send message to the actor itself recursively
- *	  	    context.sendOneWay(msg)
+ *	  	    self.sendOneWay(msg)
  *
  *        } else if (msg.equals("ForwardMessage")) {
  *          // Retreive an actor from the ActorRegistry by ID and get an ActorRef back
  *          ActorRef actorRef = ActorRegistry.actorsFor("some-actor-id").head();
  *          // Wrap the ActorRef in an UntypedActorRef and forward the message to this actor
- *          UntypedActorRef.wrap(actorRef).forward(msg, context);
+ *          UntypedActorRef.wrap(actorRef).forward(msg, self);
  *
  *        } else throw new IllegalArgumentException("Unknown message: " + message);
  *      } else throw new IllegalArgumentException("Unknown message: " + message);
diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SampleUntypedActor.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SampleUntypedActor.java
index 41f125dd98..79350222ca 100644
--- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SampleUntypedActor.java
+++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SampleUntypedActor.java
@@ -12,33 +12,33 @@ import se.scalablesolutions.akka.actor.*;
  */
 public class SampleUntypedActor extends UntypedActor {
 
-  public void onReceive(Object message, UntypedActorRef context) throws Exception {
+  public void onReceive(Object message, UntypedActorRef self) throws Exception {
   	if (message instanceof String) {
       String msg = (String)message;
 	    System.out.println("Received message: " + msg);
 
   	  if (msg.equals("UseReply")) {
   	  	// Reply to original sender of message using the 'replyUnsafe' method
-  	  	context.replyUnsafe(msg + ":" + context.getUuid());
+  	  	self.replyUnsafe(msg + ":" + self.getUuid());
 	  
-  	  } else if (msg.equals("UseSender") && context.getSender().isDefined()) {	
+  	  } else if (msg.equals("UseSender") && self.getSender().isDefined()) {	
   	  	// Reply to original sender of message using the sender reference
-  	  	// also passing along my own refererence (the context)
-  	  	context.getSender().get().sendOneWay(msg, context); 
+  	  	// also passing along my own refererence (the self)
+  	  	self.getSender().get().sendOneWay(msg, self); 
 
-  	  } else if (msg.equals("UseSenderFuture") && context.getSenderFuture().isDefined()) {	
+  	  } else if (msg.equals("UseSenderFuture") && self.getSenderFuture().isDefined()) {	
   	  	// Reply to original sender of message using the sender future reference
-  	  	context.getSenderFuture().get().completeWithResult(msg);
+  	  	self.getSenderFuture().get().completeWithResult(msg);
 
   	  } else if (msg.equals("SendToSelf")) {
   	  	// Send fire-forget message to the actor itself recursively
-  	  	context.sendOneWay(msg);
+  	  	self.sendOneWay(msg);
 
   	  } else if (msg.equals("ForwardMessage")) {
   	  	// Retreive an actor from the ActorRegistry by ID and get an ActorRef back
   	  	ActorRef actorRef = ActorRegistry.actorsFor("some-actor-id").head();
   	  	// Wrap the ActorRef in an UntypedActorRef and forward the message to this actor
-  	    UntypedActorRef.wrap(actorRef).forward(msg, context);
+  	    UntypedActorRef.wrap(actorRef).forward(msg, self);
   	      
       } else throw new IllegalArgumentException("Unknown message: " + message);
     } else throw new IllegalArgumentException("Unknown message: " + message);

From ea5ce25474070038ef625771344de814f49cf894 Mon Sep 17 00:00:00 2001
From: Jonas Boner 
Date: Fri, 30 Jul 2010 00:46:35 +0200
Subject: [PATCH 075/188] removed trailing whitespace

---
 .../src/main/scala/actor/UntypedActor.scala   | 62 +++++++++----------
 .../akka/actor/ReplyUntypedActor.java         | 18 +++---
 .../akka/actor/SampleUntypedActor.java        | 44 ++++++-------
 .../akka/actor/SenderUntypedActor.java        |  6 +-
 4 files changed, 65 insertions(+), 65 deletions(-)

diff --git a/akka-core/src/main/scala/actor/UntypedActor.scala b/akka-core/src/main/scala/actor/UntypedActor.scala
index 3d5f0b8e59..8ea36531e8 100644
--- a/akka-core/src/main/scala/actor/UntypedActor.scala
+++ b/akka-core/src/main/scala/actor/UntypedActor.scala
@@ -23,22 +23,22 @@ import java.net.InetSocketAddress
  *      if (message instanceof String) {
  *        String msg = (String)message;
  *
- *	      if (msg.equals("UseReply")) {
- *	  	    // Reply to original sender of message using the 'replyUnsafe' method
- *	  	    self.replyUnsafe(msg + ":" + self.getUuid());
+ *            if (msg.equals("UseReply")) {
+ *                  // Reply to original sender of message using the 'replyUnsafe' method
+ *                  self.replyUnsafe(msg + ":" + self.getUuid());
  *
- *	      } else if (msg.equals("UseSender") && self.getSender().isDefined()) {	
- *	  	    // Reply to original sender of message using the sender reference
- *	  	    // also passing along my own refererence (the self)
- *	  	    self.getSender().get().sendOneWay(msg, self); 
+ *            } else if (msg.equals("UseSender") && self.getSender().isDefined()) {     
+ *                  // Reply to original sender of message using the sender reference
+ *                  // also passing along my own refererence (the self)
+ *                  self.getSender().get().sendOneWay(msg, self); 
  *
- *        } else if (msg.equals("UseSenderFuture") && self.getSenderFuture().isDefined()) {	
- *	  	    // Reply to original sender of message using the sender future reference
- *	  	    self.getSenderFuture().get().completeWithResult(msg);
+ *        } else if (msg.equals("UseSenderFuture") && self.getSenderFuture().isDefined()) {     
+ *                  // Reply to original sender of message using the sender future reference
+ *                  self.getSenderFuture().get().completeWithResult(msg);
  *
  *        } else if (msg.equals("SendToSelf")) {
- *	  	    // Send message to the actor itself recursively
- *	  	    self.sendOneWay(msg)
+ *                  // Send message to the actor itself recursively
+ *                  self.sendOneWay(msg)
  *
  *        } else if (msg.equals("ForwardMessage")) {
  *          // Retreive an actor from the ActorRegistry by ID and get an ActorRef back
@@ -263,8 +263,8 @@ class UntypedActorRef(val actorRef: ActorRef) {
    * Is defined if the message was sent from another Actor, else None.
    */
   def getSender(): Option[UntypedActorRef] = actorRef.sender match {
-  	case Some(s) => Some(UntypedActorRef.wrap(s))
-  	case None    => None
+        case Some(s) => Some(UntypedActorRef.wrap(s))
+        case None    => None
   }
 
   /**
@@ -310,8 +310,8 @@ class UntypedActorRef(val actorRef: ActorRef) {
    * 

*/ def sendOneWay(message: AnyRef, sender: UntypedActorRef) = - if (sender eq null) actorRef.!(message)(None) - else actorRef.!(message)(Some(sender.actorRef)) + if (sender eq null) actorRef.!(message)(None) + else actorRef.!(message)(Some(sender.actorRef)) /** * Sends a message asynchronously and waits on a future for a reply message under the hood. The timeout is taken from @@ -328,7 +328,7 @@ class UntypedActorRef(val actorRef: ActorRef) { * to send a reply message to the original sender. If not then the sender will block until the timeout expires. */ def sendRequestReply(message: AnyRef): AnyRef = - actorRef.!!(message)(None).getOrElse(throw new ActorTimeoutException( + actorRef.!!(message)(None).getOrElse(throw new ActorTimeoutException( "Message [" + message + "]\n\tsent to [" + actorRef.actorClassName + "]\n\twith timeout [" + actorRef.timeout + @@ -350,9 +350,9 @@ class UntypedActorRef(val actorRef: ActorRef) { * to send a reply message to the original sender. If not then the sender will block until the timeout expires. */ def sendRequestReply(message: AnyRef, sender: UntypedActorRef): AnyRef = { - val result = if (sender eq null) actorRef.!!(message)(None) - else actorRef.!!(message)(Some(sender.actorRef)) - result.getOrElse(throw new ActorTimeoutException( + val result = if (sender eq null) actorRef.!!(message)(None) + else actorRef.!!(message)(Some(sender.actorRef)) + result.getOrElse(throw new ActorTimeoutException( "Message [" + message + "]\n\tsent to [" + actorRef.actorClassName + "]\n\tfrom [" + sender.actorRef.actorClassName + @@ -375,7 +375,7 @@ class UntypedActorRef(val actorRef: ActorRef) { * to send a reply message to the original sender. If not then the sender will block until the timeout expires. */ def sendRequestReply(message: AnyRef, timeout: Long): AnyRef = - actorRef.!!(message, timeout)(None).getOrElse(throw new ActorTimeoutException( + actorRef.!!(message, timeout)(None).getOrElse(throw new ActorTimeoutException( "Message [" + message + "]\n\tsent to [" + actorRef.actorClassName + "]\n\twith timeout [" + timeout + @@ -396,9 +396,9 @@ class UntypedActorRef(val actorRef: ActorRef) { * to send a reply message to the original sender. If not then the sender will block until the timeout expires. */ def sendRequestReply(message: AnyRef, timeout: Long, sender: UntypedActorRef): AnyRef = { - val result = if (sender eq null) actorRef.!!(message, timeout)(None) - else actorRef.!!(message)(Some(sender.actorRef)) - result.getOrElse(throw new ActorTimeoutException( + val result = if (sender eq null) actorRef.!!(message, timeout)(None) + else actorRef.!!(message)(Some(sender.actorRef)) + result.getOrElse(throw new ActorTimeoutException( "Message [" + message + "]\n\tsent to [" + actorRef.actorClassName + "]\n\tfrom [" + sender.actorRef.actorClassName + @@ -432,8 +432,8 @@ class UntypedActorRef(val actorRef: ActorRef) { * to send a reply message to the original sender. If not then the sender will block until the timeout expires. */ def sendRequestReplyFuture(message: AnyRef, sender: UntypedActorRef): Future[_] = - if (sender eq null) actorRef.!!!(message)(None) - else actorRef.!!!(message)(Some(sender.actorRef)) + if (sender eq null) actorRef.!!!(message)(None) + else actorRef.!!!(message)(Some(sender.actorRef)) /** * Sends a message asynchronously returns a future holding the eventual reply message. @@ -458,8 +458,8 @@ class UntypedActorRef(val actorRef: ActorRef) { * to send a reply message to the original sender. If not then the sender will block until the timeout expires. */ def sendRequestReplyFuture(message: AnyRef, timeout: Long, sender: UntypedActorRef): Future[_] = - if (sender eq null) actorRef.!!!(message, timeout)(None) - else actorRef.!!!(message)(Some(sender.actorRef)) + if (sender eq null) actorRef.!!!(message, timeout)(None) + else actorRef.!!!(message)(Some(sender.actorRef)) /** * Forwards the message and passes the original sender actor as the sender. @@ -467,8 +467,8 @@ class UntypedActorRef(val actorRef: ActorRef) { * Works with 'sendOneWay', 'sendRequestReply' and 'sendRequestReplyFuture'. */ def forward(message: AnyRef, sender: UntypedActorRef): Unit = - if (sender eq null) throw new IllegalArgumentException("The 'sender' argument to 'forward' can't be null") - else actorRef.forward(message)(Some(sender.actorRef)) + if (sender eq null) throw new IllegalArgumentException("The 'sender' argument to 'forward' can't be null") + else actorRef.forward(message)(Some(sender.actorRef)) /** * Use context.replyUnsafe(..) to reply with a message to the original sender of the message currently @@ -566,7 +566,7 @@ class UntypedActorRef(val actorRef: ActorRef) { * Atomically start, link and make an actor remote. */ def startLinkRemote(actor: UntypedActorRef, hostname: String, port: Int): Unit = - actorRef.startLinkRemote(actor.actorRef, hostname, port) + actorRef.startLinkRemote(actor.actorRef, hostname, port) /** * Returns the mailbox size. diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/ReplyUntypedActor.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/ReplyUntypedActor.java index c50e1e8b3d..8510c3889b 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/ReplyUntypedActor.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/ReplyUntypedActor.java @@ -4,25 +4,25 @@ import se.scalablesolutions.akka.actor.*; public class ReplyUntypedActor extends UntypedActor { public void onReceive(Object message, UntypedActorRef context) throws Exception { - if (message instanceof String) { + if (message instanceof String) { String str = (String)message; - if (str.equals("ReplyToSendOneWayUsingReply")) { - context.replyUnsafe("Reply"); + if (str.equals("ReplyToSendOneWayUsingReply")) { + context.replyUnsafe("Reply"); } else if (str.equals("ReplyToSendOneWayUsingSender")) { - context.getSender().get().sendOneWay("Reply"); + context.getSender().get().sendOneWay("Reply"); } else if (str.equals("ReplyToSendRequestReplyUsingReply")) { - context.replyUnsafe("Reply"); + context.replyUnsafe("Reply"); } else if (str.equals("ReplyToSendRequestReplyUsingFuture")) { - context.getSenderFuture().get().completeWithResult("Reply"); + context.getSenderFuture().get().completeWithResult("Reply"); } else if (str.equals("ReplyToSendRequestReplyFutureUsingReply")) { - context.replyUnsafe("Reply"); + context.replyUnsafe("Reply"); } else if (str.equals("ReplyToSendRequestReplyFutureUsingFuture")) { - context.getSenderFuture().get().completeWithResult("Reply"); + context.getSenderFuture().get().completeWithResult("Reply"); } else throw new IllegalArgumentException("Unknown message: " + str); - } else throw new IllegalArgumentException("Unknown message: " + message); + } else throw new IllegalArgumentException("Unknown message: " + message); } } diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SampleUntypedActor.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SampleUntypedActor.java index 79350222ca..8040e1394f 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SampleUntypedActor.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SampleUntypedActor.java @@ -13,33 +13,33 @@ import se.scalablesolutions.akka.actor.*; public class SampleUntypedActor extends UntypedActor { public void onReceive(Object message, UntypedActorRef self) throws Exception { - if (message instanceof String) { + if (message instanceof String) { String msg = (String)message; - System.out.println("Received message: " + msg); + System.out.println("Received message: " + msg); - if (msg.equals("UseReply")) { - // Reply to original sender of message using the 'replyUnsafe' method - self.replyUnsafe(msg + ":" + self.getUuid()); - - } else if (msg.equals("UseSender") && self.getSender().isDefined()) { - // Reply to original sender of message using the sender reference - // also passing along my own refererence (the self) - self.getSender().get().sendOneWay(msg, self); + if (msg.equals("UseReply")) { + // Reply to original sender of message using the 'replyUnsafe' method + self.replyUnsafe(msg + ":" + self.getUuid()); + + } else if (msg.equals("UseSender") && self.getSender().isDefined()) { + // Reply to original sender of message using the sender reference + // also passing along my own refererence (the self) + self.getSender().get().sendOneWay(msg, self); - } else if (msg.equals("UseSenderFuture") && self.getSenderFuture().isDefined()) { - // Reply to original sender of message using the sender future reference - self.getSenderFuture().get().completeWithResult(msg); + } else if (msg.equals("UseSenderFuture") && self.getSenderFuture().isDefined()) { + // Reply to original sender of message using the sender future reference + self.getSenderFuture().get().completeWithResult(msg); - } else if (msg.equals("SendToSelf")) { - // Send fire-forget message to the actor itself recursively - self.sendOneWay(msg); + } else if (msg.equals("SendToSelf")) { + // Send fire-forget message to the actor itself recursively + self.sendOneWay(msg); - } else if (msg.equals("ForwardMessage")) { - // Retreive an actor from the ActorRegistry by ID and get an ActorRef back - ActorRef actorRef = ActorRegistry.actorsFor("some-actor-id").head(); - // Wrap the ActorRef in an UntypedActorRef and forward the message to this actor - UntypedActorRef.wrap(actorRef).forward(msg, self); - + } else if (msg.equals("ForwardMessage")) { + // Retreive an actor from the ActorRegistry by ID and get an ActorRef back + ActorRef actorRef = ActorRegistry.actorsFor("some-actor-id").head(); + // Wrap the ActorRef in an UntypedActorRef and forward the message to this actor + UntypedActorRef.wrap(actorRef).forward(msg, self); + } else throw new IllegalArgumentException("Unknown message: " + message); } else throw new IllegalArgumentException("Unknown message: " + message); } diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SenderUntypedActor.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SenderUntypedActor.java index 84adc5da7a..7234ff27a4 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SenderUntypedActor.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SenderUntypedActor.java @@ -13,9 +13,9 @@ public class SenderUntypedActor extends UntypedActor { String str = (String)message; if (str.equals("ReplyToSendOneWayUsingReply")) { - replyActor.sendOneWay("ReplyToSendOneWayUsingReply", context); + replyActor.sendOneWay("ReplyToSendOneWayUsingReply", context); } else if (str.equals("ReplyToSendOneWayUsingSender")) { - replyActor.sendOneWay("ReplyToSendOneWayUsingSender", context); + replyActor.sendOneWay("ReplyToSendOneWayUsingSender", context); } else if (str.equals("ReplyToSendRequestReplyUsingReply")) { UntypedActorTestState.log = (String)replyActor.sendRequestReply("ReplyToSendRequestReplyUsingReply", context); @@ -35,7 +35,7 @@ public class SenderUntypedActor extends UntypedActor { UntypedActorTestState.log = (String)future.result().get(); UntypedActorTestState.finished.await(); - } else if (str.equals("Reply")) { + } else if (str.equals("Reply")) { UntypedActorTestState.log = "Reply"; UntypedActorTestState.finished.await(); } From 01c3be9af4bfaa8bab79be706df7bcff4b32b241 Mon Sep 17 00:00:00 2001 From: Martin Krasser Date: Fri, 30 Jul 2010 13:17:44 +0200 Subject: [PATCH 076/188] Fixed failing (and temporarily disabled) tests in akka-spring after refactoring from ActiveObject to TypedActor. - Further: * Dropped support for @PostConstruct * Cleaned up typed actor implementations for testing --- .../akka/camel/PojoBase.java | 17 ++--- .../akka/camel/PojoImpl.java | 9 +-- .../akka/camel/PojoRemote.java | 4 +- .../akka/camel/PojoSingle.java | 4 +- .../scalablesolutions/akka/camel/PojoSub.java | 12 +-- .../java/sample/camel/ConsumerPojo2Impl.java | 18 ----- ...ConsumerPojo1.java => TypedConsumer1.java} | 2 +- ...Pojo1Impl.java => TypedConsumer1Impl.java} | 5 +- ...ConsumerPojo2.java => TypedConsumer2.java} | 2 +- .../java/sample/camel/TypedConsumer2Impl.java | 13 ++++ ...erPojo1.java => TypedRemoteConsumer1.java} | 2 +- ...mpl.java => TypedRemoteConsumer1Impl.java} | 4 +- ...erPojo2.java => TypedRemoteConsumer2.java} | 2 +- .../src/main/resources/context-standalone.xml | 2 +- .../src/main/scala/Boot.scala | 2 +- .../src/main/scala/ClientApplication.scala | 4 +- .../main/scala/StandaloneApplication.scala | 19 ++--- .../main/scala/TypedActorFactoryBean.scala | 45 +++-------- .../scalablesolutions/akka/spring/Pojo.java | 31 +++++--- .../akka/spring/PojoInf.java | 7 +- akka-spring/src/test/resources/appContext.xml | 19 ++--- .../scala/CamelServiceSpringFeatureTest.scala | 2 - .../scala/TypedActorFactoryBeanTest.scala | 74 +++++++++---------- 23 files changed, 120 insertions(+), 179 deletions(-) delete mode 100644 akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo2Impl.java rename akka-samples/akka-sample-camel/src/main/java/sample/camel/{ConsumerPojo1.java => TypedConsumer1.java} (91%) rename akka-samples/akka-sample-camel/src/main/java/sample/camel/{ConsumerPojo1Impl.java => TypedConsumer1Impl.java} (66%) rename akka-samples/akka-sample-camel/src/main/java/sample/camel/{ConsumerPojo2.java => TypedConsumer2.java} (87%) create mode 100644 akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedConsumer2Impl.java rename akka-samples/akka-sample-camel/src/main/java/sample/camel/{RemoteConsumerPojo1.java => TypedRemoteConsumer1.java} (89%) rename akka-samples/akka-sample-camel/src/main/java/sample/camel/{RemoteConsumerPojo1Impl.java => TypedRemoteConsumer1Impl.java} (59%) rename akka-samples/akka-sample-camel/src/main/java/sample/camel/{RemoteConsumerPojo2.java => TypedRemoteConsumer2.java} (91%) diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoBase.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoBase.java index 7a9b5c95cc..f0f0b8ee4d 100644 --- a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoBase.java +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoBase.java @@ -1,10 +1,6 @@ package se.scalablesolutions.akka.camel; -import org.apache.camel.Body; -import org.apache.camel.Header; - -import se.scalablesolutions.akka.actor.annotation.consume; -import se.scalablesolutions.akka.actor.*; +import se.scalablesolutions.akka.actor.TypedActor; /** * @author Martin Krasser @@ -15,21 +11,18 @@ public class PojoBase extends TypedActor implements PojoBaseIntf { return "m1base: " + b + " " + h; } - @consume("direct:m2base") - public String m2(@Body String b, @Header("test") String h) { + public String m2(String b, String h) { return "m2base: " + b + " " + h; } - @consume("direct:m3base") - public String m3(@Body String b, @Header("test") String h) { + public String m3(String b, String h) { return "m3base: " + b + " " + h; } - @consume("direct:m4base") - public String m4(@Body String b, @Header("test") String h) { + public String m4(String b, String h) { return "m4base: " + b + " " + h; } - public void m5(@Body String b, @Header("test") String h) { + public void m5(String b, String h) { } } diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoImpl.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoImpl.java index 8866acf573..f8ade8ac97 100644 --- a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoImpl.java +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoImpl.java @@ -1,10 +1,6 @@ package se.scalablesolutions.akka.camel; -import org.apache.camel.Body; -import org.apache.camel.Header; - -import se.scalablesolutions.akka.actor.annotation.consume; -import se.scalablesolutions.akka.actor.*; +import se.scalablesolutions.akka.actor.TypedActor; /** * @author Martin Krasser @@ -15,8 +11,7 @@ public class PojoImpl extends TypedActor implements PojoIntf { return "m1impl: " + b + " " + h; } - @consume("direct:m2impl") - public String m2(@Body String b, @Header("test") String h) { + public String m2(String b, String h) { return "m2impl: " + b + " " + h; } } diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemote.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemote.java index 61ea4d7a17..3ea8b05180 100644 --- a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemote.java +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemote.java @@ -1,14 +1,12 @@ package se.scalablesolutions.akka.camel; -import se.scalablesolutions.akka.actor.annotation.consume; -import se.scalablesolutions.akka.actor.*; +import se.scalablesolutions.akka.actor.TypedActor; /** * @author Martin Krasser */ public class PojoRemote extends TypedActor implements PojoRemoteIntf { - @consume("direct:remote-active-object") public String foo(String s) { return String.format("remote typed actor: %s", s); } diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSingle.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSingle.java index d4cbe1aabe..7d4f6be5da 100644 --- a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSingle.java +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSingle.java @@ -1,14 +1,12 @@ package se.scalablesolutions.akka.camel; -import se.scalablesolutions.akka.actor.annotation.consume; -import se.scalablesolutions.akka.actor.*; +import se.scalablesolutions.akka.actor.TypedActor; /** * @author Martin Krasser */ public class PojoSingle extends TypedActor implements PojoSingleIntf { - @consume("direct:foo") public void foo(String b) { } diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSub.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSub.java index 24caf37348..a7e592ef01 100644 --- a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSub.java +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoSub.java @@ -1,16 +1,11 @@ package se.scalablesolutions.akka.camel; -import org.apache.camel.Body; -import org.apache.camel.Header; - -import se.scalablesolutions.akka.actor.annotation.consume; -import se.scalablesolutions.akka.actor.*; +import se.scalablesolutions.akka.actor.TypedActor; public class PojoSub extends PojoBase implements PojoSubIntf { @Override - @consume("direct:m1sub") - public String m1(@Body String b, @Header("test") String h) { + public String m1(String b, String h) { return "m1sub: " + b + " " + h; } @@ -20,8 +15,7 @@ public class PojoSub extends PojoBase implements PojoSubIntf { } @Override - @consume("direct:m3sub") - public String m3(@Body String b, @Header("test") String h) { + public String m3(String b, String h) { return "m3sub: " + b + " " + h; } diff --git a/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo2Impl.java b/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo2Impl.java deleted file mode 100644 index eeca816d1b..0000000000 --- a/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo2Impl.java +++ /dev/null @@ -1,18 +0,0 @@ -package sample.camel; - -import org.apache.camel.Body; -import org.apache.camel.Header; - -import se.scalablesolutions.akka.actor.TypedActor; -import se.scalablesolutions.akka.actor.annotation.consume; - -/** - * @author Martin Krasser - */ -public class ConsumerPojo2Impl extends TypedActor implements ConsumerPojo2 { - - @consume("direct:default") - public String foo(String body) { - return String.format("default: %s", body); - } -} \ No newline at end of file diff --git a/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo1.java b/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedConsumer1.java similarity index 91% rename from akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo1.java rename to akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedConsumer1.java index d099816161..f05d96c953 100644 --- a/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo1.java +++ b/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedConsumer1.java @@ -8,7 +8,7 @@ import se.scalablesolutions.akka.actor.annotation.consume; /** * @author Martin Krasser */ -public interface ConsumerPojo1 { +public interface TypedConsumer1 { @consume("file:data/input/pojo") public void foo(String body); diff --git a/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo1Impl.java b/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedConsumer1Impl.java similarity index 66% rename from akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo1Impl.java rename to akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedConsumer1Impl.java index 8f3ca9625d..dc4014fb1f 100644 --- a/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo1Impl.java +++ b/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedConsumer1Impl.java @@ -3,21 +3,18 @@ package sample.camel; import org.apache.camel.Body; import org.apache.camel.Header; -import se.scalablesolutions.akka.actor.annotation.consume; import se.scalablesolutions.akka.actor.TypedActor; /** * @author Martin Krasser */ -public class ConsumerPojo1Impl extends TypedActor implements ConsumerPojo1 { +public class TypedConsumer1Impl extends TypedActor implements TypedConsumer1 { - @consume("file:data/input/pojo") public void foo(String body) { System.out.println("Received message:"); System.out.println(body); } - @consume("jetty:http://0.0.0.0:8877/camel/pojo") public String bar(@Body String body, @Header("name") String header) { return String.format("body=%s header=%s", body, header); } diff --git a/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo2.java b/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedConsumer2.java similarity index 87% rename from akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo2.java rename to akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedConsumer2.java index c0ef7a6798..1fed5ac4ce 100644 --- a/akka-samples/akka-sample-camel/src/main/java/sample/camel/ConsumerPojo2.java +++ b/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedConsumer2.java @@ -7,7 +7,7 @@ import se.scalablesolutions.akka.actor.annotation.consume; /** * @author Martin Krasser */ -public interface ConsumerPojo2 { +public interface TypedConsumer2 { @consume("direct:default") public String foo(String body); diff --git a/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedConsumer2Impl.java b/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedConsumer2Impl.java new file mode 100644 index 0000000000..8a5fe1e4c9 --- /dev/null +++ b/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedConsumer2Impl.java @@ -0,0 +1,13 @@ +package sample.camel; + +import se.scalablesolutions.akka.actor.TypedActor; + +/** + * @author Martin Krasser + */ +public class TypedConsumer2Impl extends TypedActor implements TypedConsumer2 { + + public String foo(String body) { + return String.format("default: %s", body); + } +} \ No newline at end of file diff --git a/akka-samples/akka-sample-camel/src/main/java/sample/camel/RemoteConsumerPojo1.java b/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedRemoteConsumer1.java similarity index 89% rename from akka-samples/akka-sample-camel/src/main/java/sample/camel/RemoteConsumerPojo1.java rename to akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedRemoteConsumer1.java index 929a82b65d..23fa7e2181 100644 --- a/akka-samples/akka-sample-camel/src/main/java/sample/camel/RemoteConsumerPojo1.java +++ b/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedRemoteConsumer1.java @@ -8,7 +8,7 @@ import se.scalablesolutions.akka.actor.annotation.consume; /** * @author Martin Krasser */ -public interface RemoteConsumerPojo1 { +public interface TypedRemoteConsumer1 { @consume("jetty:http://localhost:6644/camel/remote-active-object-1") public String foo(@Body String body, @Header("name") String header); diff --git a/akka-samples/akka-sample-camel/src/main/java/sample/camel/RemoteConsumerPojo1Impl.java b/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedRemoteConsumer1Impl.java similarity index 59% rename from akka-samples/akka-sample-camel/src/main/java/sample/camel/RemoteConsumerPojo1Impl.java rename to akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedRemoteConsumer1Impl.java index 858afcdbeb..1cc32b3e07 100644 --- a/akka-samples/akka-sample-camel/src/main/java/sample/camel/RemoteConsumerPojo1Impl.java +++ b/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedRemoteConsumer1Impl.java @@ -3,15 +3,13 @@ package sample.camel; import org.apache.camel.Body; import org.apache.camel.Header; -import se.scalablesolutions.akka.actor.annotation.consume; import se.scalablesolutions.akka.actor.TypedActor; /** * @author Martin Krasser */ -public class RemoteConsumerPojo1Impl extends TypedActor implements RemoteConsumerPojo1 { +public class TypedRemoteConsumer1Impl extends TypedActor implements TypedRemoteConsumer1 { - @consume("jetty:http://localhost:6644/camel/remote-active-object-1") public String foo(@Body String body, @Header("name") String header) { return String.format("remote1: body=%s header=%s", body, header); } diff --git a/akka-samples/akka-sample-camel/src/main/java/sample/camel/RemoteConsumerPojo2.java b/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedRemoteConsumer2.java similarity index 91% rename from akka-samples/akka-sample-camel/src/main/java/sample/camel/RemoteConsumerPojo2.java rename to akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedRemoteConsumer2.java index e982fe5025..ef824acce2 100644 --- a/akka-samples/akka-sample-camel/src/main/java/sample/camel/RemoteConsumerPojo2.java +++ b/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedRemoteConsumer2.java @@ -7,7 +7,7 @@ import se.scalablesolutions.akka.actor.annotation.consume; /** * @author Martin Krasser */ -public class RemoteConsumerPojo2 { +public class TypedRemoteConsumer2 { @consume("jetty:http://localhost:6644/camel/remote-active-object-2") public String foo(@Body String body, @Header("name") String header) { diff --git a/akka-samples/akka-sample-camel/src/main/resources/context-standalone.xml b/akka-samples/akka-sample-camel/src/main/resources/context-standalone.xml index 36645a936d..6dc8cfd564 100644 --- a/akka-samples/akka-sample-camel/src/main/resources/context-standalone.xml +++ b/akka-samples/akka-sample-camel/src/main/resources/context-standalone.xml @@ -20,6 +20,6 @@ http://camel.apache.org/schema/spring/camel-spring.xsd"> - + diff --git a/akka-samples/akka-sample-camel/src/main/scala/Boot.scala b/akka-samples/akka-sample-camel/src/main/scala/Boot.scala index 3b733fa988..98c7c34b7e 100644 --- a/akka-samples/akka-sample-camel/src/main/scala/Boot.scala +++ b/akka-samples/akka-sample-camel/src/main/scala/Boot.scala @@ -89,7 +89,7 @@ class Boot { // Active object example // ----------------------------------------------------------------------- - TypedActor.newInstance(classOf[ConsumerPojo1], classOf[ConsumerPojo1Impl]) + TypedActor.newInstance(classOf[TypedConsumer1], classOf[TypedConsumer1Impl]) } /** diff --git a/akka-samples/akka-sample-camel/src/main/scala/ClientApplication.scala b/akka-samples/akka-sample-camel/src/main/scala/ClientApplication.scala index 5be24f1c8f..95f9703f5b 100644 --- a/akka-samples/akka-sample-camel/src/main/scala/ClientApplication.scala +++ b/akka-samples/akka-sample-camel/src/main/scala/ClientApplication.scala @@ -18,8 +18,8 @@ object ClientApplication { val actor1 = actorOf[RemoteActor1] val actor2 = RemoteClient.actorFor("remote2", "localhost", 7777) - val actobj1 = TypedActor.newRemoteInstance(classOf[RemoteConsumerPojo1], classOf[RemoteConsumerPojo1Impl], "localhost", 7777) - //val actobj2 = TODO: create reference to server-managed typed actor (RemoteConsumerPojo2) + val actobj1 = TypedActor.newRemoteInstance(classOf[TypedRemoteConsumer1], classOf[TypedRemoteConsumer1Impl], "localhost", 7777) + //val actobj2 = TODO: create reference to server-managed typed actor (TypedRemoteConsumer2) actor1.start diff --git a/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala b/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala index 6584651f68..17a0c343d3 100644 --- a/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala +++ b/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala @@ -18,7 +18,7 @@ object StandaloneApplication { // 'externally' register typed actors val registry = new SimpleRegistry - registry.put("pojo1", TypedActor.newInstance(classOf[BeanIntf], classOf[BeanImpl])) + registry.put("sample", TypedActor.newInstance(classOf[BeanIntf], classOf[BeanImpl])) // customize CamelContext CamelContextManager.init(new DefaultCamelContext(registry)) @@ -28,17 +28,19 @@ object StandaloneApplication { val camelService = CamelService.newInstance.load // access 'externally' registered typed actors - assert("hello msg1" == context.createProducerTemplate.requestBody("direct:test1", "msg1")) - assert("hello msg2" == context.createProducerTemplate.requestBody("direct:test2", "msg2")) + assert("hello msg1" == context.createProducerTemplate.requestBody("direct:test", "msg1")) + + // set expectations on upcoming endpoint activation + val activation = camelService.expectEndpointActivationCount(1) // 'internally' register typed actor (requires CamelService) - TypedActor.newInstance(classOf[ConsumerPojo2], classOf[ConsumerPojo2Impl]) + TypedActor.newInstance(classOf[TypedConsumer2], classOf[TypedConsumer2Impl]) // internal registration is done in background. Wait a bit ... - Thread.sleep(1000) + activation.await // access 'internally' (automatically) registered active-objects - // (see @consume annotation value at ConsumerPojo2.foo method) + // (see @consume annotation value at TypedConsumer2.foo method) assert("default: msg3" == context.createProducerTemplate.requestBody("direct:default", "msg3")) // shutdown CamelService @@ -51,9 +53,8 @@ object StandaloneApplication { class StandaloneApplicationRoute extends RouteBuilder { def configure = { - // routes to typed actors (in SimpleRegistry) - from("direct:test1").to("active-object:pojo1?method=foo") - from("direct:test2").to("active-object:pojo2?method=foo") + // route to typed actors (in SimpleRegistry) + from("direct:test").to("active-object:sample?method=foo") } } diff --git a/akka-spring/src/main/scala/TypedActorFactoryBean.scala b/akka-spring/src/main/scala/TypedActorFactoryBean.scala index af792ab1fe..11267586db 100644 --- a/akka-spring/src/main/scala/TypedActorFactoryBean.scala +++ b/akka-spring/src/main/scala/TypedActorFactoryBean.scala @@ -20,7 +20,7 @@ import org.springframework.context.{ApplicationContext,ApplicationContextAware} import org.springframework.util.ReflectionUtils import org.springframework.util.StringUtils -import se.scalablesolutions.akka.actor.{TypedActorConfiguration, TypedActor} +import se.scalablesolutions.akka.actor.{AspectInitRegistry, TypedActorConfiguration, TypedActor} import se.scalablesolutions.akka.config.ScalaConfig.{ShutdownCallback, RestartCallbacks} import se.scalablesolutions.akka.dispatch.MessageDispatcher import se.scalablesolutions.akka.util.{Logging, Duration} @@ -75,7 +75,7 @@ class TypedActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging wit target.toClass } catch { // required by contract to return null - case e: ClassNotFoundException => null + case e: IllegalArgumentException => null } /* @@ -86,30 +86,15 @@ class TypedActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging wit if (isRemote) argumentList += "r" if (hasInterface) argumentList += "i" if (hasDispatcher) argumentList += "d" - postConstruct(setProperties(create(argumentList))) + val ref = create(argumentList) + setProperties(AspectInitRegistry.initFor(ref).targetInstance) + ref } /** * Stop the typed actor if it is a singleton. */ - override def destroyInstance(instance: AnyRef) = TypedActor.stop(instance.asInstanceOf[TypedActor]) - - /** - * Invokes any method annotated with @PostConstruct - * When interfaces are specified, this method is invoked both on the - * target instance and on the typed actor, so a developer is free do decide - * where the annotation should be. If no interface is specified it is only invoked - * on the typed actor - */ - private def postConstruct(ref: AnyRef): AnyRef = { - // Invoke postConstruct method if any - for { - method <- ref.getClass.getMethods - if method.isAnnotationPresent(classOf[PostConstruct]) - } method.invoke(ref) - ref - } - + override def destroyInstance(instance: AnyRef) = TypedActor.stop(instance) private def setProperties(ref: AnyRef): AnyRef = { if (hasSetDependecies) return ref @@ -139,12 +124,11 @@ class TypedActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging wit if (target == null || target == "") throw new AkkaBeansException( "The 'target' part of the 'akka:actor' element in the Spring config file can't be null or empty string") argList match { - case "ri" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), createConfig.makeRemote(host, port)) - case "i" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), createConfig) - case "id" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), createConfig.dispatcher(dispatcherInstance)) - case "rid" => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), - createConfig.makeRemote(host, port).dispatcher(dispatcherInstance)) - case _ => TypedActor.newInstance(interface.toClass, newInstanceFor(target.toClass), createConfig) + case "ri" => TypedActor.newInstance(interface.toClass, target.toClass, createConfig.makeRemote(host, port)) + case "i" => TypedActor.newInstance(interface.toClass, target.toClass, createConfig) + case "id" => TypedActor.newInstance(interface.toClass, target.toClass, createConfig.dispatcher(dispatcherInstance)) + case "rid" => TypedActor.newInstance(interface.toClass, target.toClass, createConfig.makeRemote(host, port).dispatcher(dispatcherInstance)) + case _ => TypedActor.newInstance(interface.toClass, target.toClass, createConfig) // case "rd" => TypedActor.newInstance(target.toClass, createConfig.makeRemote(host, port).dispatcher(dispatcherInstance)) // case "r" => TypedActor.newInstance(target.toClass, createConfig.makeRemote(host, port)) // case "d" => TypedActor.newInstance(target.toClass, createConfig.dispatcher(dispatcherInstance)) @@ -159,13 +143,6 @@ class TypedActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging wit config } - def newInstanceFor[T <: AnyRef](clazz: Class[T]): T = { - var ref = clazz.newInstance().asInstanceOf[T] - postConstruct(setProperties(ref)) - hasSetDependecies = true - ref - } - private[akka] def isRemote = (host != null) && (!host.isEmpty) private[akka] def hasInterface = (interface != null) && (!interface.isEmpty) diff --git a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/Pojo.java b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/Pojo.java index 72fb8cb895..f588fc777a 100644 --- a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/Pojo.java +++ b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/Pojo.java @@ -10,10 +10,11 @@ import se.scalablesolutions.akka.actor.*; public class Pojo extends TypedActor implements PojoInf, ApplicationContextAware { - private String string; + private String stringFromVal; + private String stringFromRef; private boolean gotApplicationContext = false; - private boolean postConstructInvoked = false; + private boolean initInvoked = false; public boolean gotApplicationContext() { return gotApplicationContext; @@ -23,20 +24,28 @@ public class Pojo extends TypedActor implements PojoInf, ApplicationContextAware gotApplicationContext = true; } - public void setString(String s) { - string = s; + public String getStringFromVal() { + return stringFromVal; } - public String getString() { - return string; + public void setStringFromVal(String s) { + stringFromVal = s; } - @PostConstruct - public void create() { - postConstructInvoked = true; + public String getStringFromRef() { + return stringFromRef; } - public boolean isPostConstructInvoked() { - return postConstructInvoked; + public void setStringFromRef(String s) { + stringFromRef = s; + } + + @Override + public void init() { + initInvoked = true; + } + + public boolean isInitInvoked() { + return initInvoked; } } diff --git a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/PojoInf.java b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/PojoInf.java index 0189d5ec4a..9ebf80e89b 100644 --- a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/PojoInf.java +++ b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/PojoInf.java @@ -5,10 +5,9 @@ import javax.annotation.PostConstruct; public interface PojoInf { - public String getString(); + public String getStringFromVal(); + public String getStringFromRef(); public boolean gotApplicationContext(); - public boolean isPostConstructInvoked(); + public boolean isInitInvoked(); - @PostConstruct - public void create(); } diff --git a/akka-spring/src/test/resources/appContext.xml b/akka-spring/src/test/resources/appContext.xml index ba2c243558..9e83d2d927 100644 --- a/akka-spring/src/test/resources/appContext.xml +++ b/akka-spring/src/test/resources/appContext.xml @@ -21,23 +21,16 @@ timeout="1000" scope="prototype"/> - - - - - - + + - + + + diff --git a/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala b/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala index ff246891c9..66f9a93646 100644 --- a/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala +++ b/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala @@ -17,7 +17,6 @@ class CamelServiceSpringFeatureTest extends FeatureSpec with BeforeAndAfterEach ActorRegistry.shutdownAll } -/* feature("start CamelService from Spring application context") { import CamelContextManager._ scenario("with a custom CamelContext and access a registered typed actor") { @@ -40,5 +39,4 @@ class CamelServiceSpringFeatureTest extends FeatureSpec with BeforeAndAfterEach appctx.close } } -*/ } diff --git a/akka-spring/src/test/scala/TypedActorFactoryBeanTest.scala b/akka-spring/src/test/scala/TypedActorFactoryBeanTest.scala index 1526517da7..50a284e624 100644 --- a/akka-spring/src/test/scala/TypedActorFactoryBeanTest.scala +++ b/akka-spring/src/test/scala/TypedActorFactoryBeanTest.scala @@ -3,19 +3,22 @@ */ package se.scalablesolutions.akka.spring -import org.scalatest.Spec -import org.scalatest.matchers.ShouldMatchers -import org.scalatest.junit.JUnitRunner +import se.scalablesolutions.akka.actor.ActorRegistry; + import org.junit.runner.RunWith -import org.springframework.core.io.ResourceEditor -import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext +import org.scalatest.junit.JUnitRunner +import org.scalatest.{BeforeAndAfterAll, Spec} +import org.scalatest.matchers.ShouldMatchers /** * Test for TypedActorFactoryBean * @author michaelkober */ @RunWith(classOf[JUnitRunner]) -class TypedActorFactoryBeanTest extends Spec with ShouldMatchers { +class TypedActorFactoryBeanTest extends Spec with ShouldMatchers with BeforeAndAfterAll { + + override protected def afterAll = ActorRegistry.shutdownAll describe("A TypedActorFactoryBean") { val bean = new TypedActorFactoryBean @@ -48,22 +51,37 @@ class TypedActorFactoryBeanTest extends Spec with ShouldMatchers { assert(bean.getObjectType == classOf[String]) } -/* + it("should create a proxy of type PojoInf") { + val bean = new TypedActorFactoryBean() + bean.setInterface("se.scalablesolutions.akka.spring.PojoInf") + bean.setTarget("se.scalablesolutions.akka.spring.Pojo") + bean.timeout = 1000 + val entries = new PropertyEntries() + val entry = new PropertyEntry() + entry.name = "stringFromVal" + entry.value = "tests rock" + entries.add(entry) + bean.setProperty(entries) + assert(classOf[PojoInf].isAssignableFrom(bean.getObjectType)) + + // Check that we have injected the depencency correctly + val target = bean.createInstance.asInstanceOf[PojoInf] + assert(target.getStringFromVal === entry.value) + } + it("should create an application context and verify dependency injection") { var ctx = new ClassPathXmlApplicationContext("appContext.xml"); - val target:ResourceEditor = ctx.getBean("bean").asInstanceOf[ResourceEditor] - assert(target.getSource === "someString") - - val pojoInf = ctx.getBean("pojoInf").asInstanceOf[PojoInf]; - Thread.sleep(200) - assert(pojoInf.isPostConstructInvoked) - assert(pojoInf.getString == "akka rocks") - assert(pojoInf.gotApplicationContext) + val ta = ctx.getBean("typedActor").asInstanceOf[PojoInf]; + assert(ta.isInitInvoked) + assert(ta.getStringFromVal == "akka rocks") + assert(ta.getStringFromRef == "spring rocks") + assert(ta.gotApplicationContext) + ctx.close } it("should stop the created typed actor when scope is singleton and the context is closed") { var ctx = new ClassPathXmlApplicationContext("appContext.xml"); - val target = ctx.getBean("bean-singleton").asInstanceOf[SampleBean] + val target = ctx.getBean("bean-singleton").asInstanceOf[SampleBeanIntf] assert(!target.down) ctx.close assert(target.down) @@ -71,32 +89,10 @@ class TypedActorFactoryBeanTest extends Spec with ShouldMatchers { it("should not stop the created typed actor when scope is prototype and the context is closed") { var ctx = new ClassPathXmlApplicationContext("appContext.xml"); - val target = ctx.getBean("bean-prototype").asInstanceOf[SampleBean] + val target = ctx.getBean("bean-prototype").asInstanceOf[SampleBeanIntf] assert(!target.down) ctx.close assert(!target.down) } - */ } } - -/* - // ------ NOTE: Can't work now when we only support POJO with interface ----- - - it("should create a proxy of type ResourceEditor") { - val bean = new TypedActorFactoryBean() - // we must have a java class here - bean.setTarget("org.springframework.core.io.ResourceEditor") - val entries = new PropertyEntries() - val entry = new PropertyEntry() - entry.name = "source" - entry.value = "sourceBeanIsAString" - entries.add(entry) - bean.setProperty(entries) - assert(bean.getObjectType == classOf[ResourceEditor]) - - // Check that we have injected the depencency correctly - val target:ResourceEditor = bean.createInstance.asInstanceOf[ResourceEditor] - assert(target.getSource === entry.value) - } -*/ From ac77ce525be750c2d5383e68401312072bd2bde5 Mon Sep 17 00:00:00 2001 From: Jonas Boner Date: Fri, 30 Jul 2010 18:23:53 +0200 Subject: [PATCH 077/188] Restructured test folder structure --- .../ActorFireForgetRequestReplySpec.scala | 0 .../test/scala/actor/{ => actor}/AgentSpec.scala | 0 .../src/test/scala/actor/{ => actor}/Bench.scala | 0 .../actor/{ => actor}/ForwardActorSpec.scala | 0 .../actor/{ => actor}/ReceiveTimeoutSpec.scala | 0 .../scala/actor/{ => actor}/TransactorSpec.scala | 0 .../{ => supervisor}/RestartStrategySpec.scala | 0 .../SupervisorHierarchySpec.scala | 0 .../actor/{ => supervisor}/SupervisorSpec.scala | 0 .../NestedTransactionalTypedActorSpec.scala | 0 ...estartNestedTransactionalTypedActorSpec.scala | 0 .../RestartTransactionalTypedActorSpec.scala | 0 .../TransactionalTypedActorSpec.scala | 0 .../TypedActorContextSpec.scala | 0 .../TypedActorGuiceConfiguratorSpec.scala | 0 .../TypedActorLifecycleSpec.scala | 0 .../TypedActorUtilFunctionsSpec.scala | 0 .../scala/{actor => dispatch}/FutureSpec.scala | 0 .../{actor => misc}/ActorRegistrySpec.scala | 0 .../scala/{actor => misc}/SchedulerSpec.scala | 0 .../RemoteTransactionalTypedActorSpec.scala | 0 .../src/test/scala/ticket/Ticket001Spec.scala | 16 ++++++++++++++++ .../src/test/scala/tickets/Proof001Spec.scala | 10 ---------- 23 files changed, 16 insertions(+), 10 deletions(-) rename akka-core/src/test/scala/actor/{ => actor}/ActorFireForgetRequestReplySpec.scala (100%) rename akka-core/src/test/scala/actor/{ => actor}/AgentSpec.scala (100%) rename akka-core/src/test/scala/actor/{ => actor}/Bench.scala (100%) rename akka-core/src/test/scala/actor/{ => actor}/ForwardActorSpec.scala (100%) rename akka-core/src/test/scala/actor/{ => actor}/ReceiveTimeoutSpec.scala (100%) rename akka-core/src/test/scala/actor/{ => actor}/TransactorSpec.scala (100%) rename akka-core/src/test/scala/actor/{ => supervisor}/RestartStrategySpec.scala (100%) rename akka-core/src/test/scala/actor/{ => supervisor}/SupervisorHierarchySpec.scala (100%) rename akka-core/src/test/scala/actor/{ => supervisor}/SupervisorSpec.scala (100%) rename akka-core/src/test/scala/actor/{ => typed-actor}/NestedTransactionalTypedActorSpec.scala (100%) rename akka-core/src/test/scala/actor/{ => typed-actor}/RestartNestedTransactionalTypedActorSpec.scala (100%) rename akka-core/src/test/scala/actor/{ => typed-actor}/RestartTransactionalTypedActorSpec.scala (100%) rename akka-core/src/test/scala/actor/{ => typed-actor}/TransactionalTypedActorSpec.scala (100%) rename akka-core/src/test/scala/actor/{ => typed-actor}/TypedActorContextSpec.scala (100%) rename akka-core/src/test/scala/actor/{ => typed-actor}/TypedActorGuiceConfiguratorSpec.scala (100%) rename akka-core/src/test/scala/actor/{ => typed-actor}/TypedActorLifecycleSpec.scala (100%) rename akka-core/src/test/scala/actor/{ => typed-actor}/TypedActorUtilFunctionsSpec.scala (100%) rename akka-core/src/test/scala/{actor => dispatch}/FutureSpec.scala (100%) rename akka-core/src/test/scala/{actor => misc}/ActorRegistrySpec.scala (100%) rename akka-core/src/test/scala/{actor => misc}/SchedulerSpec.scala (100%) rename akka-core/src/test/scala/{actor => remote}/RemoteTransactionalTypedActorSpec.scala (100%) create mode 100644 akka-core/src/test/scala/ticket/Ticket001Spec.scala delete mode 100644 akka-core/src/test/scala/tickets/Proof001Spec.scala diff --git a/akka-core/src/test/scala/actor/ActorFireForgetRequestReplySpec.scala b/akka-core/src/test/scala/actor/actor/ActorFireForgetRequestReplySpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/ActorFireForgetRequestReplySpec.scala rename to akka-core/src/test/scala/actor/actor/ActorFireForgetRequestReplySpec.scala diff --git a/akka-core/src/test/scala/actor/AgentSpec.scala b/akka-core/src/test/scala/actor/actor/AgentSpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/AgentSpec.scala rename to akka-core/src/test/scala/actor/actor/AgentSpec.scala diff --git a/akka-core/src/test/scala/actor/Bench.scala b/akka-core/src/test/scala/actor/actor/Bench.scala similarity index 100% rename from akka-core/src/test/scala/actor/Bench.scala rename to akka-core/src/test/scala/actor/actor/Bench.scala diff --git a/akka-core/src/test/scala/actor/ForwardActorSpec.scala b/akka-core/src/test/scala/actor/actor/ForwardActorSpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/ForwardActorSpec.scala rename to akka-core/src/test/scala/actor/actor/ForwardActorSpec.scala diff --git a/akka-core/src/test/scala/actor/ReceiveTimeoutSpec.scala b/akka-core/src/test/scala/actor/actor/ReceiveTimeoutSpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/ReceiveTimeoutSpec.scala rename to akka-core/src/test/scala/actor/actor/ReceiveTimeoutSpec.scala diff --git a/akka-core/src/test/scala/actor/TransactorSpec.scala b/akka-core/src/test/scala/actor/actor/TransactorSpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/TransactorSpec.scala rename to akka-core/src/test/scala/actor/actor/TransactorSpec.scala diff --git a/akka-core/src/test/scala/actor/RestartStrategySpec.scala b/akka-core/src/test/scala/actor/supervisor/RestartStrategySpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/RestartStrategySpec.scala rename to akka-core/src/test/scala/actor/supervisor/RestartStrategySpec.scala diff --git a/akka-core/src/test/scala/actor/SupervisorHierarchySpec.scala b/akka-core/src/test/scala/actor/supervisor/SupervisorHierarchySpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/SupervisorHierarchySpec.scala rename to akka-core/src/test/scala/actor/supervisor/SupervisorHierarchySpec.scala diff --git a/akka-core/src/test/scala/actor/SupervisorSpec.scala b/akka-core/src/test/scala/actor/supervisor/SupervisorSpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/SupervisorSpec.scala rename to akka-core/src/test/scala/actor/supervisor/SupervisorSpec.scala diff --git a/akka-core/src/test/scala/actor/NestedTransactionalTypedActorSpec.scala b/akka-core/src/test/scala/actor/typed-actor/NestedTransactionalTypedActorSpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/NestedTransactionalTypedActorSpec.scala rename to akka-core/src/test/scala/actor/typed-actor/NestedTransactionalTypedActorSpec.scala diff --git a/akka-core/src/test/scala/actor/RestartNestedTransactionalTypedActorSpec.scala b/akka-core/src/test/scala/actor/typed-actor/RestartNestedTransactionalTypedActorSpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/RestartNestedTransactionalTypedActorSpec.scala rename to akka-core/src/test/scala/actor/typed-actor/RestartNestedTransactionalTypedActorSpec.scala diff --git a/akka-core/src/test/scala/actor/RestartTransactionalTypedActorSpec.scala b/akka-core/src/test/scala/actor/typed-actor/RestartTransactionalTypedActorSpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/RestartTransactionalTypedActorSpec.scala rename to akka-core/src/test/scala/actor/typed-actor/RestartTransactionalTypedActorSpec.scala diff --git a/akka-core/src/test/scala/actor/TransactionalTypedActorSpec.scala b/akka-core/src/test/scala/actor/typed-actor/TransactionalTypedActorSpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/TransactionalTypedActorSpec.scala rename to akka-core/src/test/scala/actor/typed-actor/TransactionalTypedActorSpec.scala diff --git a/akka-core/src/test/scala/actor/TypedActorContextSpec.scala b/akka-core/src/test/scala/actor/typed-actor/TypedActorContextSpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/TypedActorContextSpec.scala rename to akka-core/src/test/scala/actor/typed-actor/TypedActorContextSpec.scala diff --git a/akka-core/src/test/scala/actor/TypedActorGuiceConfiguratorSpec.scala b/akka-core/src/test/scala/actor/typed-actor/TypedActorGuiceConfiguratorSpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/TypedActorGuiceConfiguratorSpec.scala rename to akka-core/src/test/scala/actor/typed-actor/TypedActorGuiceConfiguratorSpec.scala diff --git a/akka-core/src/test/scala/actor/TypedActorLifecycleSpec.scala b/akka-core/src/test/scala/actor/typed-actor/TypedActorLifecycleSpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/TypedActorLifecycleSpec.scala rename to akka-core/src/test/scala/actor/typed-actor/TypedActorLifecycleSpec.scala diff --git a/akka-core/src/test/scala/actor/TypedActorUtilFunctionsSpec.scala b/akka-core/src/test/scala/actor/typed-actor/TypedActorUtilFunctionsSpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/TypedActorUtilFunctionsSpec.scala rename to akka-core/src/test/scala/actor/typed-actor/TypedActorUtilFunctionsSpec.scala diff --git a/akka-core/src/test/scala/actor/FutureSpec.scala b/akka-core/src/test/scala/dispatch/FutureSpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/FutureSpec.scala rename to akka-core/src/test/scala/dispatch/FutureSpec.scala diff --git a/akka-core/src/test/scala/actor/ActorRegistrySpec.scala b/akka-core/src/test/scala/misc/ActorRegistrySpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/ActorRegistrySpec.scala rename to akka-core/src/test/scala/misc/ActorRegistrySpec.scala diff --git a/akka-core/src/test/scala/actor/SchedulerSpec.scala b/akka-core/src/test/scala/misc/SchedulerSpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/SchedulerSpec.scala rename to akka-core/src/test/scala/misc/SchedulerSpec.scala diff --git a/akka-core/src/test/scala/actor/RemoteTransactionalTypedActorSpec.scala b/akka-core/src/test/scala/remote/RemoteTransactionalTypedActorSpec.scala similarity index 100% rename from akka-core/src/test/scala/actor/RemoteTransactionalTypedActorSpec.scala rename to akka-core/src/test/scala/remote/RemoteTransactionalTypedActorSpec.scala diff --git a/akka-core/src/test/scala/ticket/Ticket001Spec.scala b/akka-core/src/test/scala/ticket/Ticket001Spec.scala new file mode 100644 index 0000000000..41efcbe578 --- /dev/null +++ b/akka-core/src/test/scala/ticket/Ticket001Spec.scala @@ -0,0 +1,16 @@ +package se.scalablesolutions.akka.actor.ticket + +import org.scalatest.junit.JUnitSuite +import org.junit.Test + +import org.scalatest.WordSpec +import org.scalatest.matchers.MustMatchers + +class Ticket001Spec extends WordSpec with MustMatchers { + + "An XXX" should { + "do YYY" in { + 1 must be (1) + } + } +} diff --git a/akka-core/src/test/scala/tickets/Proof001Spec.scala b/akka-core/src/test/scala/tickets/Proof001Spec.scala deleted file mode 100644 index 5e179ec16d..0000000000 --- a/akka-core/src/test/scala/tickets/Proof001Spec.scala +++ /dev/null @@ -1,10 +0,0 @@ -package se.scalablesolutions.akka.actor.tickets - -import org.scalatest.junit.JUnitSuite -import org.junit.Test - -// Sample ticket spec -class Proof001Spec extends JUnitSuite { - - @Test def thisFixesSomeSpecifiedBug = () -} From ba68c1eb5850e922a8669d2a0eb0a51c542c67b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bon=C3=A9r?= Date: Fri, 30 Jul 2010 09:24:47 -0700 Subject: [PATCH 078/188] Removed imports not used --- akka-core/src/test/scala/ticket/Ticket001Spec.scala | 3 --- 1 file changed, 3 deletions(-) diff --git a/akka-core/src/test/scala/ticket/Ticket001Spec.scala b/akka-core/src/test/scala/ticket/Ticket001Spec.scala index 41efcbe578..b94796d9a3 100644 --- a/akka-core/src/test/scala/ticket/Ticket001Spec.scala +++ b/akka-core/src/test/scala/ticket/Ticket001Spec.scala @@ -1,8 +1,5 @@ package se.scalablesolutions.akka.actor.ticket -import org.scalatest.junit.JUnitSuite -import org.junit.Test - import org.scalatest.WordSpec import org.scalatest.matchers.MustMatchers From d4ce436308e5b8b82b0afa6c2ed208cb4ca93336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bon=C3=A9r?= Date: Sat, 31 Jul 2010 00:41:43 +0200 Subject: [PATCH 079/188] Changed the Spring schema and the Camel endpoint names to the new typed-actor name --- .../component/{active-object => typed-actor} | 0 .../main/scala/CamelContextLifecycle.scala | 10 ++-- .../src/main/scala/ConsumerPublisher.scala | 36 +++++++-------- .../scala/component/TypedActorComponent.scala | 16 +++---- .../akka/camel/PojoRemoteIntf.java | 2 +- .../src/test/scala/PublishRequestorTest.scala | 4 +- .../src/test/scala/RemoteConsumerTest.scala | 2 +- .../TypedActorComponentFeatureTest.scala | 8 ++-- .../src/main/scala/actor/TypedActor.scala | 12 ++--- .../config/TypedActorGuiceConfigurator.scala | 14 +++--- .../scala/dispatch/ThreadPoolBuilder.scala | 7 +-- .../src/main/scala/remote/RemoteServer.scala | 30 ++++++------ ...artNestedTransactionalTypedActorSpec.scala | 2 +- .../RestartTransactionalTypedActorSpec.scala | 2 +- .../TransactionalTypedActorSpec.scala | 2 +- .../sample/camel/TypedRemoteConsumer1.java | 2 +- .../sample/camel/TypedRemoteConsumer2.java | 2 +- .../src/main/resources/context-standalone.xml | 2 +- .../main/scala/StandaloneApplication.scala | 8 ++-- .../akka/spring/foo/dispatcher-config.xml | 22 ++++----- .../akka/spring/foo/supervisor-config.xml | 46 +++++++++---------- .../akka/spring/foo/test-config.xml | 42 ++++++++--------- .../spring/DispatcherConfigurationTest.java | 2 +- .../spring/TypedActorConfigurationTest.java | 16 +++---- .../akka/spring/akka-0.10.xsd | 18 ++++---- .../src/main/scala/AkkaNamespaceHandler.scala | 2 +- .../scala/AkkaSpringConfigurationTags.scala | 8 ++-- .../src/main/scala/DispatcherParser.scala | 4 +- .../SupervisionBeanDefinitionParser.scala | 10 ++-- .../TypedActorBeanDefinitionParser.scala | 4 +- .../main/scala/TypedActorFactoryBean.scala | 28 +++++------ .../src/main/scala/TypedActorParser.scala | 4 +- .../src/main/scala/TypedActorProperties.scala | 2 +- .../akka/spring/SampleRoute.java | 2 +- akka-spring/src/test/resources/appContext.xml | 18 ++++---- .../appContextCamelServiceCustom.xml | 4 +- .../src/test/resources/failing-appContext.xml | 6 +-- .../scala/CamelServiceSpringFeatureTest.scala | 2 +- .../SupervisionBeanDefinitionParserTest.scala | 34 +++++++------- .../scala/SupervisionFactoryBeanTest.scala | 6 +-- .../TypedActorBeanDefinitionParserTest.scala | 16 +++---- .../scala/TypedActorFactoryBeanTest.scala | 8 ++-- 42 files changed, 233 insertions(+), 232 deletions(-) rename akka-camel/src/main/resources/META-INF/services/org/apache/camel/component/{active-object => typed-actor} (100%) diff --git a/akka-camel/src/main/resources/META-INF/services/org/apache/camel/component/active-object b/akka-camel/src/main/resources/META-INF/services/org/apache/camel/component/typed-actor similarity index 100% rename from akka-camel/src/main/resources/META-INF/services/org/apache/camel/component/active-object rename to akka-camel/src/main/resources/META-INF/services/org/apache/camel/component/typed-actor diff --git a/akka-camel/src/main/scala/CamelContextLifecycle.scala b/akka-camel/src/main/scala/CamelContextLifecycle.scala index d1683a9464..05c18396b8 100644 --- a/akka-camel/src/main/scala/CamelContextLifecycle.scala +++ b/akka-camel/src/main/scala/CamelContextLifecycle.scala @@ -31,13 +31,13 @@ trait CamelContextLifecycle extends Logging { /** * Camel component for accessing typed actors. */ - private[camel] var activeObjectComponent: TypedActorComponent = _ + private[camel] var typedActorComponent: TypedActorComponent = _ /** * Registry in which typed actors are TEMPORARILY registered during * creation of Camel routes to typed actors. */ - private[camel] var activeObjectRegistry: Map[String, AnyRef] = _ + private[camel] var typedActorRegistry: Map[String, AnyRef] = _ /** * Returns the managed CamelContext. @@ -97,11 +97,11 @@ trait CamelContextLifecycle extends Logging { * context under a name defined by TypedActorComponent.InternalSchema. */ def init(context: CamelContext) { - this.activeObjectComponent = new TypedActorComponent - this.activeObjectRegistry = activeObjectComponent.activeObjectRegistry + this.typedActorComponent = new TypedActorComponent + this.typedActorRegistry = typedActorComponent.typedActorRegistry this.context = context this.context.setStreamCaching(true) - this.context.addComponent(TypedActorComponent.InternalSchema, activeObjectComponent) + this.context.addComponent(TypedActorComponent.InternalSchema, typedActorComponent) this.template = context.createProducerTemplate _initialized = true log.info("Camel context initialized") diff --git a/akka-camel/src/main/scala/ConsumerPublisher.scala b/akka-camel/src/main/scala/ConsumerPublisher.scala index 6ca863a561..8c01b2079d 100644 --- a/akka-camel/src/main/scala/ConsumerPublisher.scala +++ b/akka-camel/src/main/scala/ConsumerPublisher.scala @@ -43,9 +43,9 @@ private[camel] object ConsumerPublisher extends Logging { val targetMethod = event.method.getName val objectId = "%s_%s" format (event.init.actorRef.uuid, targetMethod) - CamelContextManager.activeObjectRegistry.put(objectId, event.activeObject) + CamelContextManager.typedActorRegistry.put(objectId, event.typedActor) CamelContextManager.context.addRoutes(new ConsumerMethodRoute(event.uri, objectId, targetMethod)) - log.info("published method %s of %s at endpoint %s" format (targetMethod, event.activeObject, event.uri)) + log.info("published method %s of %s at endpoint %s" format (targetMethod, event.typedActor, event.uri)) } /** @@ -55,9 +55,9 @@ private[camel] object ConsumerPublisher extends Logging { val targetMethod = event.method.getName val objectId = "%s_%s" format (event.init.actorRef.uuid, targetMethod) - CamelContextManager.activeObjectRegistry.remove(objectId) + CamelContextManager.typedActorRegistry.remove(objectId) CamelContextManager.context.stopRoute(objectId) - log.info("unpublished method %s of %s from endpoint %s" format (targetMethod, event.activeObject, event.uri)) + log.info("unpublished method %s of %s from endpoint %s" format (targetMethod, event.typedActor, event.uri)) } } @@ -248,28 +248,28 @@ private[camel] case class ConsumerUnregistered(actorRef: ActorRef, uri: String, * @consume annotated POJO method a separate instance of this class is * created. * - * @param activeObject typed actor (proxy). + * @param typedActor typed actor (proxy). * @param init * @param uri endpoint URI of the typed actor method * @param method method to be published. * * @author Martin Krasser */ -private[camel] case class ConsumerMethodRegistered(activeObject: AnyRef, init: AspectInit, uri: String, method: Method) extends ConsumerEvent +private[camel] case class ConsumerMethodRegistered(typedActor: AnyRef, init: AspectInit, uri: String, method: Method) extends ConsumerEvent /** * Event indicating that an typed actor has been stopped. For each * @consume annotated POJO method a separate instance of this class is * created. * - * @param activeObject typed actor (proxy). + * @param typedActor typed actor (proxy). * @param init * @param uri endpoint URI of the typed actor method * @param method method to be un-published. * * @author Martin Krasser */ -private[camel] case class ConsumerMethodUnregistered(activeObject: AnyRef, init: AspectInit, uri: String, method: Method) extends ConsumerEvent +private[camel] case class ConsumerMethodUnregistered(typedActor: AnyRef, init: AspectInit, uri: String, method: Method) extends ConsumerEvent /** * @author Martin Krasser @@ -306,17 +306,17 @@ private[camel] object ConsumerUnregistered { */ private[camel] object ConsumerMethod { /** - * Applies a function f to each consumer method of activeObject and + * Applies a function f to each consumer method of typedActor and * returns the function results as a list. A consumer method is one that is annotated with - * @consume. If activeObject is a proxy for a remote typed actor + * @consume. If typedActor is a proxy for a remote typed actor * f is never called and Nil is returned. */ - def forConsumer[T](activeObject: AnyRef, init: AspectInit)(f: Method => T): List[T] = { + def forConsumer[T](typedActor: AnyRef, init: AspectInit)(f: Method => T): List[T] = { // TODO: support consumer annotation inheritance // - visit overridden methods in superclasses // - visit implemented method declarations in interfaces if (init.remoteAddress.isDefined) Nil // let remote node publish typed actor methods on endpoints - else for (m <- activeObject.getClass.getMethods.toList; if (m.isAnnotationPresent(classOf[consume]))) + else for (m <- typedActor.getClass.getMethods.toList; if (m.isAnnotationPresent(classOf[consume]))) yield f(m) } } @@ -330,9 +330,9 @@ private[camel] object ConsumerMethodRegistered { * list if the typed actor is a proxy for an remote typed actor or the typed actor doesn't * have any @consume annotated methods. */ - def forConsumer(activeObject: AnyRef, init: AspectInit): List[ConsumerMethodRegistered] = { - ConsumerMethod.forConsumer(activeObject, init) { - m => ConsumerMethodRegistered(activeObject, init, m.getAnnotation(classOf[consume]).value, m) + def forConsumer(typedActor: AnyRef, init: AspectInit): List[ConsumerMethodRegistered] = { + ConsumerMethod.forConsumer(typedActor, init) { + m => ConsumerMethodRegistered(typedActor, init, m.getAnnotation(classOf[consume]).value, m) } } } @@ -346,9 +346,9 @@ private[camel] object ConsumerMethodUnregistered { * list if the typed actor is a proxy for an remote typed actor or the typed actor doesn't * have any @consume annotated methods. */ - def forConsumer(activeObject: AnyRef, init: AspectInit): List[ConsumerMethodUnregistered] = { - ConsumerMethod.forConsumer(activeObject, init) { - m => ConsumerMethodUnregistered(activeObject, init, m.getAnnotation(classOf[consume]).value, m) + def forConsumer(typedActor: AnyRef, init: AspectInit): List[ConsumerMethodUnregistered] = { + ConsumerMethod.forConsumer(typedActor, init) { + m => ConsumerMethodUnregistered(typedActor, init, m.getAnnotation(classOf[consume]).value, m) } } } diff --git a/akka-camel/src/main/scala/component/TypedActorComponent.scala b/akka-camel/src/main/scala/component/TypedActorComponent.scala index aff6326beb..2a48cf9fc4 100644 --- a/akka-camel/src/main/scala/component/TypedActorComponent.scala +++ b/akka-camel/src/main/scala/component/TypedActorComponent.scala @@ -16,12 +16,12 @@ object TypedActorComponent { /** * Default schema name for typed actor endpoint URIs. */ - val InternalSchema = "active-object-internal" + val InternalSchema = "typed-actor-internal" } /** * Camel component for exchanging messages with typed actors. This component - * tries to obtain the typed actor from the activeObjectRegistry + * tries to obtain the typed actor from the typedActorRegistry * first. If it's not there it tries to obtain it from the CamelContext's registry. * * @see org.apache.camel.component.bean.BeanComponent @@ -29,11 +29,11 @@ object TypedActorComponent { * @author Martin Krasser */ class TypedActorComponent extends BeanComponent { - val activeObjectRegistry = new ConcurrentHashMap[String, AnyRef] + val typedActorRegistry = new ConcurrentHashMap[String, AnyRef] /** * Creates a {@link org.apache.camel.component.bean.BeanEndpoint} with a custom - * bean holder that uses activeObjectRegistry for getting access to + * bean holder that uses typedActorRegistry for getting access to * typed actors (beans). * * @see se.scalablesolutions.akka.camel.component.TypedActorHolder @@ -47,7 +47,7 @@ class TypedActorComponent extends BeanComponent { } private def createBeanHolder(beanName: String) = - new TypedActorHolder(activeObjectRegistry, getCamelContext, beanName).createCacheHolder + new TypedActorHolder(typedActorRegistry, getCamelContext, beanName).createCacheHolder } /** @@ -56,7 +56,7 @@ class TypedActorComponent extends BeanComponent { * * @author Martin Krasser */ -class TypedActorHolder(activeObjectRegistry: Map[String, AnyRef], context: CamelContext, name: String) +class TypedActorHolder(typedActorRegistry: Map[String, AnyRef], context: CamelContext, name: String) extends RegistryBean(context, name) { /** @@ -66,10 +66,10 @@ class TypedActorHolder(activeObjectRegistry: Map[String, AnyRef], context: Camel new TypedActorInfo(getContext, getBean.getClass, getParameterMappingStrategy) /** - * Obtains an typed actor from activeObjectRegistry. + * Obtains an typed actor from typedActorRegistry. */ override def getBean: AnyRef = { - val bean = activeObjectRegistry.get(getName) + val bean = typedActorRegistry.get(getName) if (bean eq null) super.getBean else bean } } diff --git a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemoteIntf.java b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemoteIntf.java index 639a440598..45f09e1757 100644 --- a/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemoteIntf.java +++ b/akka-camel/src/test/java/se/scalablesolutions/akka/camel/PojoRemoteIntf.java @@ -7,6 +7,6 @@ import se.scalablesolutions.akka.actor.annotation.consume; */ public interface PojoRemoteIntf { - @consume("direct:remote-active-object") + @consume("direct:remote-typed-actor") public String foo(String s); } diff --git a/akka-camel/src/test/scala/PublishRequestorTest.scala b/akka-camel/src/test/scala/PublishRequestorTest.scala index 984f856875..2913a5981c 100644 --- a/akka-camel/src/test/scala/PublishRequestorTest.scala +++ b/akka-camel/src/test/scala/PublishRequestorTest.scala @@ -40,7 +40,7 @@ class PublishRequestorTest extends JUnitSuite { val event = (publisher !! GetRetainedMessage).get.asInstanceOf[ConsumerMethodRegistered] assert(event.init === init) assert(event.uri === "direct:foo") - assert(event.activeObject === obj) + assert(event.typedActor === obj) assert(event.method.getName === "foo") } @@ -53,7 +53,7 @@ class PublishRequestorTest extends JUnitSuite { val event = (publisher !! GetRetainedMessage).get.asInstanceOf[ConsumerMethodUnregistered] assert(event.init === init) assert(event.uri === "direct:foo") - assert(event.activeObject === obj) + assert(event.typedActor === obj) assert(event.method.getName === "foo") } diff --git a/akka-camel/src/test/scala/RemoteConsumerTest.scala b/akka-camel/src/test/scala/RemoteConsumerTest.scala index 3f0770127f..4ac0033854 100644 --- a/akka-camel/src/test/scala/RemoteConsumerTest.scala +++ b/akka-camel/src/test/scala/RemoteConsumerTest.scala @@ -66,7 +66,7 @@ class RemoteConsumerTest extends FeatureSpec with BeforeAndAfterAll with GivenWh assert(latch.await(5000, TimeUnit.MILLISECONDS)) then("the published method is accessible via its endpoint URI") - val response = CamelContextManager.template.requestBody("direct:remote-active-object", "test") + val response = CamelContextManager.template.requestBody("direct:remote-typed-actor", "test") assert(response === "remote typed actor: test") } } diff --git a/akka-camel/src/test/scala/component/TypedActorComponentFeatureTest.scala b/akka-camel/src/test/scala/component/TypedActorComponentFeatureTest.scala index 4a2c4e8e28..12ec9f32ab 100644 --- a/akka-camel/src/test/scala/component/TypedActorComponentFeatureTest.scala +++ b/akka-camel/src/test/scala/component/TypedActorComponentFeatureTest.scala @@ -28,8 +28,8 @@ class TypedActorComponentFeatureTest extends FeatureSpec with BeforeAndAfterAll CamelContextManager.context.addRoutes(new CustomRouteBuilder) CamelContextManager.start - CamelContextManager.activeObjectRegistry.put("base", activePojoBase) - CamelContextManager.activeObjectRegistry.put("intf", activePojoIntf) + CamelContextManager.typedActorRegistry.put("base", activePojoBase) + CamelContextManager.typedActorRegistry.put("intf", activePojoIntf) } override protected def afterAll = { @@ -90,7 +90,7 @@ class TypedActorComponentFeatureTest extends FeatureSpec with BeforeAndAfterAll scenario("in-out exchange with internally registered typed actor not possible") { intercept[ResolveEndpointFailedException] { - template.requestBodyAndHeader("active-object:intf?method=m2", "x", "test", "y") + template.requestBodyAndHeader("typed-actor:intf?method=m2", "x", "test", "y") } } } @@ -99,7 +99,7 @@ class TypedActorComponentFeatureTest extends FeatureSpec with BeforeAndAfterAll object TypedActorComponentFeatureTest { class CustomRouteBuilder extends RouteBuilder { def configure = { - from("direct:test").to("active-object:pojo?method=foo") + from("direct:test").to("typed-actor:pojo?method=foo") } } } diff --git a/akka-core/src/main/scala/actor/TypedActor.scala b/akka-core/src/main/scala/actor/TypedActor.scala index 7526d48b05..460012a84f 100644 --- a/akka-core/src/main/scala/actor/TypedActor.scala +++ b/akka-core/src/main/scala/actor/TypedActor.scala @@ -451,26 +451,26 @@ object TypedActor extends Logging { this } - private def injectTypedActorContext(activeObject: AnyRef): Option[TypedActorContext] = { - def injectTypedActorContext0(activeObject: AnyRef, clazz: Class[_]): Option[TypedActorContext] = { + private def injectTypedActorContext(typedActor: AnyRef): Option[TypedActorContext] = { + def injectTypedActorContext0(typedActor: AnyRef, clazz: Class[_]): Option[TypedActorContext] = { val contextField = clazz.getDeclaredFields.toList.find(_.getType == classOf[TypedActorContext]) if (contextField.isDefined) { contextField.get.setAccessible(true) val context = new TypedActorContext - contextField.get.set(activeObject, context) + contextField.get.set(typedActor, context) Some(context) } else { val parent = clazz.getSuperclass - if (parent != null) injectTypedActorContext0(activeObject, parent) + if (parent != null) injectTypedActorContext0(typedActor, parent) else { log.ifTrace("Can't set 'TypedActorContext' for TypedActor [" + - activeObject.getClass.getName + + typedActor.getClass.getName + "] since no field of this type could be found.") None } } } - injectTypedActorContext0(activeObject, activeObject.getClass) + injectTypedActorContext0(typedActor, typedActor.getClass) } private[akka] def newTypedActor(targetClass: Class[_]): TypedActor = { diff --git a/akka-core/src/main/scala/config/TypedActorGuiceConfigurator.scala b/akka-core/src/main/scala/config/TypedActorGuiceConfigurator.scala index fe9289f1f8..8b23921792 100644 --- a/akka-core/src/main/scala/config/TypedActorGuiceConfigurator.scala +++ b/akka-core/src/main/scala/config/TypedActorGuiceConfigurator.scala @@ -30,7 +30,7 @@ private[akka] class TypedActorGuiceConfigurator extends TypedActorConfiguratorBa private var supervised: List[Supervise] = Nil private var bindings: List[DependencyBinding] = Nil private var configRegistry = new HashMap[Class[_], Component] // TODO is configRegistry needed? - private var activeObjectRegistry = new HashMap[Class[_], Tuple3[AnyRef, AnyRef, Component]] + private var typedActorRegistry = new HashMap[Class[_], Tuple3[AnyRef, AnyRef, Component]] private var modules = new java.util.ArrayList[Module] private var methodToUriRegistry = new HashMap[Method, String] @@ -45,7 +45,7 @@ private[akka] class TypedActorGuiceConfigurator extends TypedActorConfiguratorBa if (injector eq null) throw new IllegalActorStateException( "inject() and/or supervise() must be called before invoking getInstance(clazz)") val (proxy, targetInstance, component) = - activeObjectRegistry.getOrElse(clazz, throw new IllegalActorStateException( + typedActorRegistry.getOrElse(clazz, throw new IllegalActorStateException( "Class [" + clazz.getName + "] has not been put under supervision" + "\n(by passing in the config to the 'configure' and then invoking 'supervise') method")) injector.injectMembers(targetInstance) @@ -53,7 +53,7 @@ private[akka] class TypedActorGuiceConfigurator extends TypedActorConfiguratorBa } def isDefined(clazz: Class[_]): Boolean = synchronized { - activeObjectRegistry.get(clazz).isDefined + typedActorRegistry.get(clazz).isDefined } override def getExternalDependency[T](clazz: Class[T]): T = synchronized { @@ -93,7 +93,7 @@ private[akka] class TypedActorGuiceConfigurator extends TypedActorConfiguratorBa val proxy = TypedActor.newInstance(targetClass, actorRef, remoteAddress, component.timeout).asInstanceOf[AnyRef] remoteAddress.foreach(address => RemoteServer.registerTypedActor(address, targetClass.getName, proxy)) supervised ::= Supervise(actorRef, component.lifeCycle) - activeObjectRegistry.put(targetClass, (proxy, proxy, component)) + typedActorRegistry.put(targetClass, (proxy, proxy, component)) new DependencyBinding(targetClass, proxy) } @@ -122,7 +122,7 @@ private[akka] class TypedActorGuiceConfigurator extends TypedActorConfiguratorBa remoteAddress.foreach(address => RemoteServer.registerTypedActor(address, targetClass.getName, proxy)) supervised ::= Supervise(actorRef, component.lifeCycle) - activeObjectRegistry.put(targetClass, (proxy, targetInstance, component)) + typedActorRegistry.put(targetClass, (proxy, targetInstance, component)) new DependencyBinding(targetClass, proxy) } @@ -141,7 +141,7 @@ private[akka] class TypedActorGuiceConfigurator extends TypedActorConfiguratorBa /** * Add additional services to be wired in. *

-   * activeObjectConfigurator.addExternalGuiceModule(new AbstractModule {
+   * typedActorConfigurator.addExternalGuiceModule(new AbstractModule {
    *   protected void configure() {
    *     bind(Foo.class).to(FooImpl.class).in(Scopes.SINGLETON);
    *     bind(BarImpl.class);
@@ -160,7 +160,7 @@ private[akka] class TypedActorGuiceConfigurator extends TypedActorConfiguratorBa
   def reset = synchronized {
     modules = new java.util.ArrayList[Module]
     configRegistry = new HashMap[Class[_], Component]
-    activeObjectRegistry = new HashMap[Class[_], Tuple3[AnyRef, AnyRef, Component]]
+    typedActorRegistry = new HashMap[Class[_], Tuple3[AnyRef, AnyRef, Component]]
     methodToUriRegistry = new HashMap[Method, String]
     injector = null
     restartStrategy = null
diff --git a/akka-core/src/main/scala/dispatch/ThreadPoolBuilder.scala b/akka-core/src/main/scala/dispatch/ThreadPoolBuilder.scala
index a111ae87a5..5abf431ef8 100644
--- a/akka-core/src/main/scala/dispatch/ThreadPoolBuilder.scala
+++ b/akka-core/src/main/scala/dispatch/ThreadPoolBuilder.scala
@@ -234,18 +234,19 @@ trait ThreadPoolBuilder {
       extends Thread(runnable, name + "-" + MonitorableThread.created.incrementAndGet) with Logging {
 
     setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
-      def uncaughtException(thread: Thread, cause: Throwable) = log.error(cause, "UNCAUGHT in thread [%s]", thread.getName)
+      def uncaughtException(thread: Thread, cause: Throwable) = 
+        log.error(cause, "UNCAUGHT in thread [%s]", thread.getName)
     })
 
     override def run = {
       val debug = MonitorableThread.debugLifecycle
-      log.debug("Created %s", getName)
+      log.debug("Created thread %s", getName)
       try {
         MonitorableThread.alive.incrementAndGet
         super.run
       } finally {
         MonitorableThread.alive.decrementAndGet
-        log.debug("Exiting %s", getName)
+        log.debug("Exiting thread %s", getName)
       }
     }
   }
diff --git a/akka-core/src/main/scala/remote/RemoteServer.scala b/akka-core/src/main/scala/remote/RemoteServer.scala
index 55a74feab0..f3b548cd33 100644
--- a/akka-core/src/main/scala/remote/RemoteServer.scala
+++ b/akka-core/src/main/scala/remote/RemoteServer.scala
@@ -93,7 +93,7 @@ object RemoteServer {
 
   private class RemoteActorSet {
     private[RemoteServer] val actors =        new ConcurrentHashMap[String, ActorRef]
-    private[RemoteServer] val activeObjects = new ConcurrentHashMap[String, AnyRef]
+    private[RemoteServer] val typedActors = new ConcurrentHashMap[String, AnyRef]
   }
 
   private val guard = new ReadWriteGuard
@@ -104,8 +104,8 @@ object RemoteServer {
     actorsFor(RemoteServer.Address(address.getHostName, address.getPort)).actors.put(uuid, actor)
   }
 
-  private[akka] def registerTypedActor(address: InetSocketAddress, name: String, activeObject: AnyRef) = guard.withWriteGuard {
-    actorsFor(RemoteServer.Address(address.getHostName, address.getPort)).activeObjects.put(name, activeObject)
+  private[akka] def registerTypedActor(address: InetSocketAddress, name: String, typedActor: AnyRef) = guard.withWriteGuard {
+    actorsFor(RemoteServer.Address(address.getHostName, address.getPort)).typedActors.put(name, typedActor)
   }
 
   private[akka] def getOrCreateServer(address: InetSocketAddress): RemoteServer = guard.withWriteGuard {
@@ -197,7 +197,7 @@ class RemoteServer extends Logging {
         RemoteServer.register(hostname, port, this)
         val remoteActorSet = RemoteServer.actorsFor(RemoteServer.Address(hostname, port))
         val pipelineFactory = new RemoteServerPipelineFactory(
-          name, openChannels, loader, remoteActorSet.actors, remoteActorSet.activeObjects)
+          name, openChannels, loader, remoteActorSet.actors, remoteActorSet.typedActors)
         bootstrap.setPipelineFactory(pipelineFactory)
         bootstrap.setOption("child.tcpNoDelay", true)
         bootstrap.setOption("child.keepAlive", true)
@@ -292,7 +292,7 @@ class RemoteServerPipelineFactory(
     val openChannels: ChannelGroup,
     val loader: Option[ClassLoader],
     val actors: JMap[String, ActorRef],
-    val activeObjects: JMap[String, AnyRef]) extends ChannelPipelineFactory {
+    val typedActors: JMap[String, AnyRef]) extends ChannelPipelineFactory {
   import RemoteServer._
 
   def getPipeline: ChannelPipeline = {
@@ -305,7 +305,7 @@ class RemoteServerPipelineFactory(
       //case "lzf" => Some(Codec(new LzfEncoder, new LzfDecoder))
       case _ => None
     }
-    val remoteServer = new RemoteServerHandler(name, openChannels, loader, actors, activeObjects)
+    val remoteServer = new RemoteServerHandler(name, openChannels, loader, actors, typedActors)
 
     val stages: Array[ChannelHandler] =
       zipCodec.map(codec => Array(codec.decoder, lenDec, protobufDec, codec.encoder, lenPrep, protobufEnc, remoteServer))
@@ -323,7 +323,7 @@ class RemoteServerHandler(
     val openChannels: ChannelGroup,
     val applicationLoader: Option[ClassLoader],
     val actors: JMap[String, ActorRef],
-    val activeObjects: JMap[String, AnyRef]) extends SimpleChannelUpstreamHandler with Logging {
+    val typedActors: JMap[String, AnyRef]) extends SimpleChannelUpstreamHandler with Logging {
   val AW_PROXY_PREFIX = "$$ProxiedByAW".intern
 
   applicationLoader.foreach(MessageSerializer.setClassLoader(_))
@@ -405,16 +405,16 @@ class RemoteServerHandler(
     val actorInfo = request.getActorInfo
     val typedActorInfo = actorInfo.getTypedActorInfo
     log.debug("Dispatching to remote typed actor [%s :: %s]", typedActorInfo.getMethod, typedActorInfo.getInterface)
-    val activeObject = createTypedActor(actorInfo)
+    val typedActor = createTypedActor(actorInfo)
 
     val args = MessageSerializer.deserialize(request.getMessage).asInstanceOf[Array[AnyRef]].toList
     val argClasses = args.map(_.getClass)
 
     try {
-      val messageReceiver = activeObject.getClass.getDeclaredMethod(typedActorInfo.getMethod, argClasses: _*)
-      if (request.getIsOneWay) messageReceiver.invoke(activeObject, args: _*)
+      val messageReceiver = typedActor.getClass.getDeclaredMethod(typedActorInfo.getMethod, argClasses: _*)
+      if (request.getIsOneWay) messageReceiver.invoke(typedActor, args: _*)
       else {
-        val result = messageReceiver.invoke(activeObject, args: _*)
+        val result = messageReceiver.invoke(typedActor, args: _*)
         log.debug("Returning result from remote typed actor invocation [%s]", result)
         val replyBuilder = RemoteReplyProtocol.newBuilder
             .setId(request.getId)
@@ -464,9 +464,9 @@ class RemoteServerHandler(
 
   private def createTypedActor(actorInfo: ActorInfoProtocol): AnyRef = {
     val uuid = actorInfo.getUuid
-    val activeObjectOrNull = activeObjects.get(uuid)
+    val typedActorOrNull = typedActors.get(uuid)
 
-    if (activeObjectOrNull eq null) {
+    if (typedActorOrNull eq null) {
       val typedActorInfo = actorInfo.getTypedActorInfo
       val interfaceClassname = typedActorInfo.getInterface
       val targetClassname = actorInfo.getTarget
@@ -481,12 +481,12 @@ class RemoteServerHandler(
 
         val newInstance = TypedActor.newInstance(
           interfaceClass, targetClass.asInstanceOf[Class[_ <: TypedActor]], actorInfo.getTimeout).asInstanceOf[AnyRef]
-        activeObjects.put(uuid, newInstance)
+        typedActors.put(uuid, newInstance)
         newInstance
       } catch {
         case e => log.error(e, "Could not create remote typed actor instance"); throw e
       }
-    } else activeObjectOrNull
+    } else typedActorOrNull
   }
 
   private def createErrorReplyMessage(e: Throwable, request: RemoteRequestProtocol, isActor: Boolean): RemoteReplyProtocol = {
diff --git a/akka-core/src/test/scala/actor/typed-actor/RestartNestedTransactionalTypedActorSpec.scala b/akka-core/src/test/scala/actor/typed-actor/RestartNestedTransactionalTypedActorSpec.scala
index e70370c261..1769a5c47b 100644
--- a/akka-core/src/test/scala/actor/typed-actor/RestartNestedTransactionalTypedActorSpec.scala
+++ b/akka-core/src/test/scala/actor/typed-actor/RestartNestedTransactionalTypedActorSpec.scala
@@ -52,7 +52,7 @@ class RestartNestedTransactionalTypedActorSpec extends
     */
   }
 
-  describe("Restart nested supervised transactional Active Object") {
+  describe("Restart nested supervised transactional Typed Actor") {
 /*
     it("map should rollback state for stateful server in case of failure") {
       val stateful = conf.getInstance(classOf[TransactionalTypedActor])
diff --git a/akka-core/src/test/scala/actor/typed-actor/RestartTransactionalTypedActorSpec.scala b/akka-core/src/test/scala/actor/typed-actor/RestartTransactionalTypedActorSpec.scala
index 5da6f9594f..56b1e6ec5b 100644
--- a/akka-core/src/test/scala/actor/typed-actor/RestartTransactionalTypedActorSpec.scala
+++ b/akka-core/src/test/scala/actor/typed-actor/RestartTransactionalTypedActorSpec.scala
@@ -47,7 +47,7 @@ class RestartTransactionalTypedActorSpec extends
     ActorRegistry.shutdownAll
   }
 
-  describe("Restart supervised transactional Active Object ") {
+  describe("Restart supervised transactional Typed Actor ") {
 /*
     it("map should rollback state for stateful server in case of failure") {
       before
diff --git a/akka-core/src/test/scala/actor/typed-actor/TransactionalTypedActorSpec.scala b/akka-core/src/test/scala/actor/typed-actor/TransactionalTypedActorSpec.scala
index c07c53935e..b55f52c875 100644
--- a/akka-core/src/test/scala/actor/typed-actor/TransactionalTypedActorSpec.scala
+++ b/akka-core/src/test/scala/actor/typed-actor/TransactionalTypedActorSpec.scala
@@ -25,7 +25,7 @@ class TransactionalTypedActorSpec extends
 //    ActorRegistry.shutdownAll
   }
 
-  describe("Declaratively supervised transactional in-memory Active Object ") {
+  describe("Declaratively supervised transactional in-memory Typed Actor ") {
     it("map should not rollback state for stateful server in case of success") {
       val stateful = TypedActor.newInstance(classOf[TransactionalTypedActor], classOf[TransactionalTypedActorImpl])
       stateful.setMapState("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "init")
diff --git a/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedRemoteConsumer1.java b/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedRemoteConsumer1.java
index 23fa7e2181..7db5452d93 100644
--- a/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedRemoteConsumer1.java
+++ b/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedRemoteConsumer1.java
@@ -10,6 +10,6 @@ import se.scalablesolutions.akka.actor.annotation.consume;
  */
 public interface TypedRemoteConsumer1 {
 
-    @consume("jetty:http://localhost:6644/camel/remote-active-object-1")
+    @consume("jetty:http://localhost:6644/camel/remote-typed-actor-1")
     public String foo(@Body String body, @Header("name") String header);
 }
diff --git a/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedRemoteConsumer2.java b/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedRemoteConsumer2.java
index ef824acce2..2b1c068b46 100644
--- a/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedRemoteConsumer2.java
+++ b/akka-samples/akka-sample-camel/src/main/java/sample/camel/TypedRemoteConsumer2.java
@@ -9,7 +9,7 @@ import se.scalablesolutions.akka.actor.annotation.consume;
  */
 public class TypedRemoteConsumer2 {
 
-    @consume("jetty:http://localhost:6644/camel/remote-active-object-2")
+    @consume("jetty:http://localhost:6644/camel/remote-typed-actor-2")
     public String foo(@Body String body, @Header("name") String header) {
         return String.format("remote2: body=%s header=%s", body, header);
     }
diff --git a/akka-samples/akka-sample-camel/src/main/resources/context-standalone.xml b/akka-samples/akka-sample-camel/src/main/resources/context-standalone.xml
index 6dc8cfd564..9cf91056da 100644
--- a/akka-samples/akka-sample-camel/src/main/resources/context-standalone.xml
+++ b/akka-samples/akka-sample-camel/src/main/resources/context-standalone.xml
@@ -20,6 +20,6 @@ http://camel.apache.org/schema/spring/camel-spring.xsd">
     
   
 
-  
+  
 
 
diff --git a/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala b/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala
index 17a0c343d3..528700ade9 100644
--- a/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala
+++ b/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala
@@ -39,7 +39,7 @@ object StandaloneApplication {
     // internal registration is done in background. Wait a bit ...
     activation.await
 
-    // access 'internally' (automatically) registered active-objects
+    // access 'internally' (automatically) registered typed-actors
     // (see @consume annotation value at TypedConsumer2.foo method)
     assert("default: msg3" == context.createProducerTemplate.requestBody("direct:default", "msg3"))
 
@@ -54,7 +54,7 @@ object StandaloneApplication {
 class StandaloneApplicationRoute extends RouteBuilder {
   def configure = {
     // route to typed actors (in SimpleRegistry)
-    from("direct:test").to("active-object:sample?method=foo")
+    from("direct:test").to("typed-actor:sample?method=foo")
   }
 }
 
@@ -65,7 +65,7 @@ object StandaloneSpringApplication {
     // load Spring application context
     val appctx = new ClassPathXmlApplicationContext("/context-standalone.xml")
 
-    // access 'externally' registered typed actors with active-object component
+    // access 'externally' registered typed actors with typed-actor component
     assert("hello msg3" == template.requestBody("direct:test3", "msg3"))
 
     // destroy Spring application context
@@ -79,7 +79,7 @@ object StandaloneSpringApplication {
 class StandaloneSpringApplicationRoute extends RouteBuilder {
   def configure = {
     // routes to typed actor (in ApplicationContextRegistry)
-    from("direct:test3").to("active-object:pojo3?method=foo")
+    from("direct:test3").to("typed-actor:pojo3?method=foo")
   }
 }
 
diff --git a/akka-spring/akka-spring-test-java/src/main/resources/se/scalablesolutions/akka/spring/foo/dispatcher-config.xml b/akka-spring/akka-spring-test-java/src/main/resources/se/scalablesolutions/akka/spring/foo/dispatcher-config.xml
index 688d04f377..20879832d0 100644
--- a/akka-spring/akka-spring-test-java/src/main/resources/se/scalablesolutions/akka/spring/foo/dispatcher-config.xml
+++ b/akka-spring/akka-spring-test-java/src/main/resources/se/scalablesolutions/akka/spring/foo/dispatcher-config.xml
@@ -10,15 +10,15 @@ http://www.akkasource.org/schema/akka
 http://scalablesolutions.se/akka/akka-0.10.xsd">
 
 
-  
     
-  
+  
 
-  
       
-  
+  
 
 
   
@@ -69,14 +69,14 @@ http://scalablesolutions.se/akka/akka-0.10.xsd">
         java.lang.NullPointerException
       
     
-    
-      
-      
-      
+    
+      
+      
+      
         
-      
-    
+      
+    
   
 
 
diff --git a/akka-spring/akka-spring-test-java/src/main/resources/se/scalablesolutions/akka/spring/foo/supervisor-config.xml b/akka-spring/akka-spring-test-java/src/main/resources/se/scalablesolutions/akka/spring/foo/supervisor-config.xml
index 9d35a40742..d96fdb1c93 100644
--- a/akka-spring/akka-spring-test-java/src/main/resources/se/scalablesolutions/akka/spring/foo/supervisor-config.xml
+++ b/akka-spring/akka-spring-test-java/src/main/resources/se/scalablesolutions/akka/spring/foo/supervisor-config.xml
@@ -16,14 +16,14 @@ http://scalablesolutions.se/akka/akka-0.10.xsd">
         java.lang.NullPointerException
       
     
-    
-      
-      
-      
+    
+      
+      
+      
         
-      
-    
+      
+    
   
 
   
@@ -32,10 +32,10 @@ http://scalablesolutions.se/akka/akka-0.10.xsd">
         java.lang.Exception
       
     
-    
-      
+      
-    
+    
   
 
   
@@ -53,15 +53,15 @@ http://scalablesolutions.se/akka/akka-0.10.xsd">
         java.lang.Exception
       
     
-    
-      
+    
+      
         
-      
-      
+      
+      
         
         
-      
-    
+      
+    
   
 
   
@@ -70,19 +70,19 @@ http://scalablesolutions.se/akka/akka-0.10.xsd">
         java.lang.Exception
       
     
-    
-      
-      
-    
+    
+      
+      
+    
     
       
         
           java.lang.IOException
         
       
-      
-        
-      
+      
+        
+      
     
   
 
diff --git a/akka-spring/akka-spring-test-java/src/main/resources/se/scalablesolutions/akka/spring/foo/test-config.xml b/akka-spring/akka-spring-test-java/src/main/resources/se/scalablesolutions/akka/spring/foo/test-config.xml
index 13c45e6d3b..23d2476995 100644
--- a/akka-spring/akka-spring-test-java/src/main/resources/se/scalablesolutions/akka/spring/foo/test-config.xml
+++ b/akka-spring/akka-spring-test-java/src/main/resources/se/scalablesolutions/akka/spring/foo/test-config.xml
@@ -16,37 +16,37 @@ http://scalablesolutions.se/akka/akka-0.10.xsd">
     
   
 
-  
 
-  
 
-  
 
-  
     
-  
+  
 
-  
     
     
-  
+  
 
-  
+  
     
-  
+  
 
   
     
         java.lang.NullPointerException
       
     
-    
-      
-      
-      
+    
+      
+      
+      
         
-      
-    
+      
+    
   
 
 
\ No newline at end of file
diff --git a/akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/DispatcherConfigurationTest.java b/akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/DispatcherConfigurationTest.java
index 9f941e4142..862d781802 100644
--- a/akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/DispatcherConfigurationTest.java
+++ b/akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/DispatcherConfigurationTest.java
@@ -58,7 +58,7 @@ public class DispatcherConfigurationTest {
          */
         @Test
         public void testDispatcherRef() {
-      MyPojo pojo = (MyPojo) context.getBean("active-object-with-dispatcher-ref");
+      MyPojo pojo = (MyPojo) context.getBean("typed-actor-with-dispatcher-ref");
       assertNotNull(pojo);
         }
 
diff --git a/akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/TypedActorConfigurationTest.java b/akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/TypedActorConfigurationTest.java
index 4117347380..e8931fd1a2 100644
--- a/akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/TypedActorConfigurationTest.java
+++ b/akka-spring/akka-spring-test-java/src/test/java/se/scalablesolutions/akka/spring/TypedActorConfigurationTest.java
@@ -34,7 +34,7 @@ public class TypedActorConfigurationTest {
   }
 
   /**
-   * Tests that the <akka:active-object/> and <akka:supervision/> and <akka:dispatcher/> element
+   * Tests that the <akka:typed-actor/> and <akka:supervision/> and <akka:dispatcher/> element
    * can be used as a top level element.
    */
   @Test
@@ -43,15 +43,15 @@ public class TypedActorConfigurationTest {
     DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
     XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
     reader.loadBeanDefinitions(CONTEXT);
-    assertTrue(beanFactory.containsBeanDefinition("simple-active-object"));
-    assertTrue(beanFactory.containsBeanDefinition("remote-active-object"));
+    assertTrue(beanFactory.containsBeanDefinition("simple-typed-actor"));
+    assertTrue(beanFactory.containsBeanDefinition("remote-typed-actor"));
     assertTrue(beanFactory.containsBeanDefinition("supervision1"));
     assertTrue(beanFactory.containsBeanDefinition("dispatcher1"));
   }
 
   @Test
   public void testSimpleTypedActor() {
-    MyPojo myPojo = (MyPojo) context.getBean("simple-active-object");
+    MyPojo myPojo = (MyPojo) context.getBean("simple-typed-actor");
     String msg = myPojo.getFoo();
     msg += myPojo.getBar();
     assertEquals("wrong invocation order", "foobar", msg);
@@ -59,20 +59,20 @@ public class TypedActorConfigurationTest {
 
   @Test(expected = FutureTimeoutException.class)
   public void testSimpleTypedActor_Timeout() {
-    MyPojo myPojo = (MyPojo) context.getBean("simple-active-object");
+    MyPojo myPojo = (MyPojo) context.getBean("simple-typed-actor");
     myPojo.longRunning();
   }
 
   @Test
   public void testSimpleTypedActor_NoTimeout() {
-    MyPojo myPojo = (MyPojo) context.getBean("simple-active-object-long-timeout");
+    MyPojo myPojo = (MyPojo) context.getBean("simple-typed-actor-long-timeout");
     String msg = myPojo.longRunning();
     assertEquals("this took long", msg);
   }
 
   @Test
   public void testTransactionalTypedActor() {
-    MyPojo myPojo = (MyPojo) context.getBean("transactional-active-object");
+    MyPojo myPojo = (MyPojo) context.getBean("transactional-typed-actor");
     String msg = myPojo.getFoo();
     msg += myPojo.getBar();
     assertEquals("wrong invocation order", "foobar", msg);
@@ -91,7 +91,7 @@ public class TypedActorConfigurationTest {
     }
     Config.config();
 
-    MyPojo myPojo = (MyPojo) context.getBean("remote-active-object");
+    MyPojo myPojo = (MyPojo) context.getBean("remote-typed-actor");
     assertEquals("foo", myPojo.getFoo());
   }
 
diff --git a/akka-spring/src/main/resources/se/scalablesolutions/akka/spring/akka-0.10.xsd b/akka-spring/src/main/resources/se/scalablesolutions/akka/spring/akka-0.10.xsd
index 5fd9b94c38..ed83a5bdc2 100644
--- a/akka-spring/src/main/resources/se/scalablesolutions/akka/spring/akka-0.10.xsd
+++ b/akka-spring/src/main/resources/se/scalablesolutions/akka/spring/akka-0.10.xsd
@@ -135,7 +135,7 @@
   
 
   
-  
+  
    
       
       
@@ -145,10 +145,10 @@
       
     
     
-    
+    
       
         
-          Name of the target class.
+          Name of the implementation class.
         
       
     
@@ -180,10 +180,10 @@
         
       
     
-	
+    
       
         
-			Supported scopes are singleton and prototype
+          Supported scopes are singleton and prototype
         
       
     
@@ -197,9 +197,9 @@
   
 
   
-  
+  
     
-      
+      
     
   
 
@@ -235,7 +235,7 @@
   
     
       
-      
+      
       
     
     
@@ -253,7 +253,7 @@
   
 
   
-  
+  
 
   
   
diff --git a/akka-spring/src/main/scala/AkkaNamespaceHandler.scala b/akka-spring/src/main/scala/AkkaNamespaceHandler.scala
index 34dede40aa..694daa90d4 100644
--- a/akka-spring/src/main/scala/AkkaNamespaceHandler.scala
+++ b/akka-spring/src/main/scala/AkkaNamespaceHandler.scala
@@ -12,7 +12,7 @@ import AkkaSpringConfigurationTags._
  */
 class AkkaNamespaceHandler extends NamespaceHandlerSupport {
   def init = {
-    registerBeanDefinitionParser(ACTIVE_OBJECT_TAG, new TypedActorBeanDefinitionParser());
+    registerBeanDefinitionParser(TYPED_ACTOR_TAG, new TypedActorBeanDefinitionParser());
     registerBeanDefinitionParser(SUPERVISION_TAG, new SupervisionBeanDefinitionParser());
     registerBeanDefinitionParser(DISPATCHER_TAG, new DispatcherBeanDefinitionParser());
     registerBeanDefinitionParser(CAMEL_SERVICE_TAG, new CamelServiceBeanDefinitionParser);
diff --git a/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala b/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala
index 1e13865ad3..0d4ff9aaab 100644
--- a/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala
+++ b/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala
@@ -13,19 +13,19 @@ object AkkaSpringConfigurationTags {
   // --- TAGS
   //
   // top level tags
-  val ACTIVE_OBJECT_TAG = "active-object"
+  val TYPED_ACTOR_TAG = "typed-actor"
   val SUPERVISION_TAG = "supervision"
   val DISPATCHER_TAG = "dispatcher"
   val PROPERTYENTRY_TAG = "property"
   val CAMEL_SERVICE_TAG = "camel-service"
 
-  // active-object sub tags
+  // typed-actor sub tags
   val RESTART_CALLBACKS_TAG = "restart-callbacks"
   val SHUTDOWN_CALLBACK_TAG = "shutdown-callback"
   val REMOTE_TAG = "remote"
 
   // superivision sub tags
-  val ACTIVE_OBJECTS_TAG = "active-objects"
+  val TYPED_ACTORS_TAG = "typed-actors"
   val STRATEGY_TAG = "restart-strategy"
   val TRAP_EXISTS_TAG = "trap-exits"
   val TRAP_EXIT_TAG = "trap-exit"
@@ -40,7 +40,7 @@ object AkkaSpringConfigurationTags {
   //
   // typed actor attributes
   val TIMEOUT = "timeout"
-  val TARGET = "target"
+  val IMPLEMENTATION = "implementation"
   val INTERFACE = "interface"
   val TRANSACTIONAL = "transactional"
   val HOST = "host"
diff --git a/akka-spring/src/main/scala/DispatcherParser.scala b/akka-spring/src/main/scala/DispatcherParser.scala
index dc156c3d58..fb9855102e 100644
--- a/akka-spring/src/main/scala/DispatcherParser.scala
+++ b/akka-spring/src/main/scala/DispatcherParser.scala
@@ -31,8 +31,8 @@ trait DispatcherParser extends BeanParser {
     properties.name = mandatory(dispatcherElement, NAME)
     properties.dispatcherType = mandatory(dispatcherElement, TYPE)
     if (properties.dispatcherType == THREAD_BASED) {
-      if (dispatcherElement.getParentNode.getNodeName != "active-object") {
-        throw new IllegalArgumentException("Thread based dispatcher must be nested in active-object element!")
+      if (dispatcherElement.getParentNode.getNodeName != "typed-actor") {
+        throw new IllegalArgumentException("Thread based dispatcher must be nested in typed-actor element!")
       }
     }
     val threadPoolElement = DomUtils.getChildElementByTagName(dispatcherElement, THREAD_POOL_TAG);
diff --git a/akka-spring/src/main/scala/SupervisionBeanDefinitionParser.scala b/akka-spring/src/main/scala/SupervisionBeanDefinitionParser.scala
index 4a76f5b008..5d430c9450 100644
--- a/akka-spring/src/main/scala/SupervisionBeanDefinitionParser.scala
+++ b/akka-spring/src/main/scala/SupervisionBeanDefinitionParser.scala
@@ -31,9 +31,9 @@ class SupervisionBeanDefinitionParser extends AbstractSingleBeanDefinitionParser
    */
   private[akka] def parseSupervisor(element: Element, builder: BeanDefinitionBuilder) {
     val strategyElement = mandatoryElement(element, STRATEGY_TAG);
-    val activeObjectsElement = mandatoryElement(element, ACTIVE_OBJECTS_TAG);
+    val typedActorsElement = mandatoryElement(element, TYPED_ACTORS_TAG);
     parseRestartStrategy(strategyElement, builder)
-    parseTypedActorList(activeObjectsElement, builder)
+    parseTypedActorList(typedActorsElement, builder)
   }
 
   private[akka] def parseRestartStrategy(element: Element, builder: BeanDefinitionBuilder) {
@@ -47,9 +47,9 @@ class SupervisionBeanDefinitionParser extends AbstractSingleBeanDefinitionParser
   }
 
   private[akka] def parseTypedActorList(element: Element, builder: BeanDefinitionBuilder) {
-    val activeObjects = DomUtils.getChildElementsByTagName(element, ACTIVE_OBJECT_TAG).toArray.toList.asInstanceOf[List[Element]]
-    val activeObjectProperties = activeObjects.map(parseTypedActor(_))
-    builder.addPropertyValue("supervised", activeObjectProperties)
+    val typedActors = DomUtils.getChildElementsByTagName(element, TYPED_ACTOR_TAG).toArray.toList.asInstanceOf[List[Element]]
+    val typedActorProperties = typedActors.map(parseTypedActor(_))
+    builder.addPropertyValue("supervised", typedActorProperties)
   }
 
   private def parseTrapExits(element: Element): Array[Class[_ <: Throwable]] = {
diff --git a/akka-spring/src/main/scala/TypedActorBeanDefinitionParser.scala b/akka-spring/src/main/scala/TypedActorBeanDefinitionParser.scala
index 7869a6a33f..ec987aacc0 100644
--- a/akka-spring/src/main/scala/TypedActorBeanDefinitionParser.scala
+++ b/akka-spring/src/main/scala/TypedActorBeanDefinitionParser.scala
@@ -18,8 +18,8 @@ class TypedActorBeanDefinitionParser extends AbstractSingleBeanDefinitionParser
    * @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder)
    */
   override def doParse(element: Element, parserContext: ParserContext, builder: BeanDefinitionBuilder) {
-    val activeObjectConf = parseTypedActor(element)
-    activeObjectConf.setAsProperties(builder)
+    val typedActorConf = parseTypedActor(element)
+    typedActorConf.setAsProperties(builder)
   }
 
   /*
diff --git a/akka-spring/src/main/scala/TypedActorFactoryBean.scala b/akka-spring/src/main/scala/TypedActorFactoryBean.scala
index 11267586db..8ddcaced6a 100644
--- a/akka-spring/src/main/scala/TypedActorFactoryBean.scala
+++ b/akka-spring/src/main/scala/TypedActorFactoryBean.scala
@@ -46,9 +46,9 @@ class TypedActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging wit
   import StringReflect._
   import AkkaSpringConfigurationTags._
 
-  @BeanProperty var target: String = ""
-  @BeanProperty var timeout: Long = _
   @BeanProperty var interface: String = ""
+  @BeanProperty var implementation: String = ""
+  @BeanProperty var timeout: Long = _
   @BeanProperty var transactional: Boolean = false
   @BeanProperty var pre: String = ""
   @BeanProperty var post: String = ""
@@ -72,7 +72,7 @@ class TypedActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging wit
    * @see org.springframework.beans.factory.FactoryBean#getObjectType()
    */
   def getObjectType: Class[AnyRef] = try {
-    target.toClass
+    implementation.toClass
   } catch {
     // required by contract to return null
     case e: IllegalArgumentException => null
@@ -98,7 +98,7 @@ class TypedActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging wit
 
   private def setProperties(ref: AnyRef): AnyRef = {
     if (hasSetDependecies) return ref
-    log.debug("Processing properties and dependencies for target class\n\t[%s]", target)
+    log.debug("Processing properties and dependencies for implementation class\n\t[%s]", implementation)
     val beanWrapper = new BeanWrapperImpl(ref);
     if (ref.isInstanceOf[ApplicationContextAware]) {
       log.debug("Setting application context")
@@ -121,17 +121,17 @@ class TypedActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging wit
   private[akka] def create(argList: String): AnyRef = {
     if (interface == null || interface == "") throw new AkkaBeansException(
         "The 'interface' part of the 'akka:actor' element in the Spring config file can't be null or empty string")
-    if (target == null || target == "") throw new AkkaBeansException(
-        "The 'target' part of the 'akka:actor' element in the Spring config file can't be null or empty string")
+    if (implementation == null || implementation == "") throw new AkkaBeansException(
+        "The 'implementation' part of the 'akka:typed-actor' element in the Spring config file can't be null or empty string")
     argList match {
-      case "ri"  => TypedActor.newInstance(interface.toClass, target.toClass, createConfig.makeRemote(host, port))
-      case "i"   => TypedActor.newInstance(interface.toClass, target.toClass, createConfig)
-      case "id"  => TypedActor.newInstance(interface.toClass, target.toClass, createConfig.dispatcher(dispatcherInstance))
-      case "rid" => TypedActor.newInstance(interface.toClass, target.toClass, createConfig.makeRemote(host, port).dispatcher(dispatcherInstance))
-      case _     => TypedActor.newInstance(interface.toClass, target.toClass, createConfig)
-      //    case "rd"  => TypedActor.newInstance(target.toClass, createConfig.makeRemote(host, port).dispatcher(dispatcherInstance))
-      //    case "r"   => TypedActor.newInstance(target.toClass, createConfig.makeRemote(host, port))
-      //    case "d"   => TypedActor.newInstance(target.toClass, createConfig.dispatcher(dispatcherInstance))
+      case "ri"  => TypedActor.newInstance(interface.toClass, implementation.toClass, createConfig.makeRemote(host, port))
+      case "i"   => TypedActor.newInstance(interface.toClass, implementation.toClass, createConfig)
+      case "id"  => TypedActor.newInstance(interface.toClass, implementation.toClass, createConfig.dispatcher(dispatcherInstance))
+      case "rid" => TypedActor.newInstance(interface.toClass, implementation.toClass, createConfig.makeRemote(host, port).dispatcher(dispatcherInstance))
+      case _     => TypedActor.newInstance(interface.toClass, implementation.toClass, createConfig)
+      //    case "rd"  => TypedActor.newInstance(implementation.toClass, createConfig.makeRemote(host, port).dispatcher(dispatcherInstance))
+      //    case "r"   => TypedActor.newInstance(implementation.toClass, createConfig.makeRemote(host, port))
+      //    case "d"   => TypedActor.newInstance(implementation.toClass, createConfig.dispatcher(dispatcherInstance))
     }
   }
 
diff --git a/akka-spring/src/main/scala/TypedActorParser.scala b/akka-spring/src/main/scala/TypedActorParser.scala
index 43e713f00e..1483a35dba 100644
--- a/akka-spring/src/main/scala/TypedActorParser.scala
+++ b/akka-spring/src/main/scala/TypedActorParser.scala
@@ -10,7 +10,7 @@ import scala.collection.JavaConversions._
 import se.scalablesolutions.akka.actor.IllegalActorStateException
 
 /**
- * Parser trait for custom namespace configuration for active-object.
+ * Parser trait for custom namespace configuration for typed-actor.
  * @author michaelkober
  * @author Johan Rask
  * @author Martin Krasser
@@ -69,7 +69,7 @@ trait TypedActorParser extends BeanParser with DispatcherParser {
         throw nfe
     }
 
-    objectProperties.target = mandatory(element, TARGET)
+    objectProperties.target = mandatory(element, IMPLEMENTATION)
     objectProperties.transactional = if (element.getAttribute(TRANSACTIONAL).isEmpty) false else element.getAttribute(TRANSACTIONAL).toBoolean
 
     if (!element.getAttribute(INTERFACE).isEmpty) {
diff --git a/akka-spring/src/main/scala/TypedActorProperties.scala b/akka-spring/src/main/scala/TypedActorProperties.scala
index 53f2fca05a..6390110676 100644
--- a/akka-spring/src/main/scala/TypedActorProperties.scala
+++ b/akka-spring/src/main/scala/TypedActorProperties.scala
@@ -39,7 +39,7 @@ class TypedActorProperties {
     builder.addPropertyValue(POST_RESTART, postRestart)
     builder.addPropertyValue(SHUTDOWN, shutdown)
     builder.addPropertyValue(TIMEOUT, timeout)
-    builder.addPropertyValue(TARGET, target)
+    builder.addPropertyValue(IMPLEMENTATION, target)
     builder.addPropertyValue(INTERFACE, interface)
     builder.addPropertyValue(TRANSACTIONAL, transactional)
     builder.addPropertyValue(LIFECYCLE, lifecycle)
diff --git a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleRoute.java b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleRoute.java
index 84377ee3d6..5e7e5ea126 100644
--- a/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleRoute.java
+++ b/akka-spring/src/test/java/se/scalablesolutions/akka/spring/SampleRoute.java
@@ -6,6 +6,6 @@ public class SampleRoute extends RouteBuilder {
 
     @Override
     public void configure() throws Exception {
-        from("direct:test").to("active-object:sample?method=foo");
+        from("direct:test").to("typed-actor:sample?method=foo");
     }
 }
diff --git a/akka-spring/src/test/resources/appContext.xml b/akka-spring/src/test/resources/appContext.xml
index 9e83d2d927..29dc5dbd87 100644
--- a/akka-spring/src/test/resources/appContext.xml
+++ b/akka-spring/src/test/resources/appContext.xml
@@ -7,28 +7,28 @@
        http://www.akkasource.org/schema/akka
        http://scalablesolutions.se/akka/akka-0.10.xsd">
 
-    
-    
-    
     
-    
         
         
-    
+    
 
     
         
diff --git a/akka-spring/src/test/resources/appContextCamelServiceCustom.xml b/akka-spring/src/test/resources/appContextCamelServiceCustom.xml
index 7150465e7c..84f442ebf6 100644
--- a/akka-spring/src/test/resources/appContextCamelServiceCustom.xml
+++ b/akka-spring/src/test/resources/appContextCamelServiceCustom.xml
@@ -20,8 +20,8 @@ http://camel.apache.org/schema/spring/camel-spring.xsd">
     
   
 
-  
 
diff --git a/akka-spring/src/test/resources/failing-appContext.xml b/akka-spring/src/test/resources/failing-appContext.xml
index bc970b6036..66382056bd 100644
--- a/akka-spring/src/test/resources/failing-appContext.xml
+++ b/akka-spring/src/test/resources/failing-appContext.xml
@@ -7,13 +7,13 @@
        http://www.akkasource.org/schema/akka
        classpath:se/scalablesolutions/akka/spring/akka-0.10.xsd">
        
-    
                               
-    
+    
 
     
         
diff --git a/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala b/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala
index 66f9a93646..e8b0d727c3 100644
--- a/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala
+++ b/akka-spring/src/test/scala/CamelServiceSpringFeatureTest.scala
@@ -35,7 +35,7 @@ class CamelServiceSpringFeatureTest extends FeatureSpec with BeforeAndAfterEach
       assert(context.isInstanceOf[DefaultCamelContext])
       context.asInstanceOf[DefaultCamelContext].setRegistry(registry)
       // access registered typed actor
-      assert("hello sample" === template.requestBody("active-object:custom?method=foo", "sample"))
+      assert("hello sample" === template.requestBody("typed-actor:custom?method=foo", "sample"))
       appctx.close
     }
   }
diff --git a/akka-spring/src/test/scala/SupervisionBeanDefinitionParserTest.scala b/akka-spring/src/test/scala/SupervisionBeanDefinitionParserTest.scala
index 317421c207..cd185c9b4b 100644
--- a/akka-spring/src/test/scala/SupervisionBeanDefinitionParserTest.scala
+++ b/akka-spring/src/test/scala/SupervisionBeanDefinitionParserTest.scala
@@ -76,8 +76,8 @@ class SupervisionBeanDefinitionParserTest extends Spec with ShouldMatchers {
   }
 
   private def createTypedActorElement : Element = {
-    val xml = 
     dom(xml).getDocumentElement
@@ -91,16 +91,16 @@ class SupervisionBeanDefinitionParserTest extends Spec with ShouldMatchers {
                       java.lang.NullPointerException
                   
                 
-                
-                          
-                          
-                          
+                
+                          
+                          
+                          
                                   
-                          
-                          
+                          
+                          
                                   
-                          
-                  
+                          
+                  
     
     dom(xml).getDocumentElement
   }
@@ -113,9 +113,9 @@ class SupervisionBeanDefinitionParserTest extends Spec with ShouldMatchers {
                       java.io.IOException
                   
                 
-                
-                          
-                  
+                
+                          
+                  
     
     dom(xml).getDocumentElement
   }
@@ -124,10 +124,10 @@ class SupervisionBeanDefinitionParserTest extends Spec with ShouldMatchers {
     val xml = 
                 
                 
-                
-                          
-                          
-                  
+                
+                          
+                          
+                  
     
     dom(xml).getDocumentElement
   }
diff --git a/akka-spring/src/test/scala/SupervisionFactoryBeanTest.scala b/akka-spring/src/test/scala/SupervisionFactoryBeanTest.scala
index 4e3df7c047..44d1cbd079 100644
--- a/akka-spring/src/test/scala/SupervisionFactoryBeanTest.scala
+++ b/akka-spring/src/test/scala/SupervisionFactoryBeanTest.scala
@@ -16,7 +16,7 @@ private[akka] class Foo
 class SupervisionFactoryBeanTest extends Spec with ShouldMatchers {
 
   val restartStrategy = new RestartStrategy(new AllForOne(), 3, 1000, Array(classOf[Throwable]))
-  val activeObjects = List(createTypedActorProperties("se.scalablesolutions.akka.spring.Foo", 1000L))
+  val typedActors = List(createTypedActorProperties("se.scalablesolutions.akka.spring.Foo", 1000L))
 
   def createTypedActorProperties(target: String, timeout: Long) : TypedActorProperties = {
     val properties = new TypedActorProperties()
@@ -30,8 +30,8 @@ class SupervisionFactoryBeanTest extends Spec with ShouldMatchers {
     it("should have java getters and setters for all properties") {
       bean.setRestartStrategy(restartStrategy)
       assert(bean.getRestartStrategy == restartStrategy)
-      bean.setSupervised(activeObjects)
-      assert(bean.getSupervised == activeObjects)
+      bean.setSupervised(typedActors)
+      assert(bean.getSupervised == typedActors)
     }
 
     it("should return the object type TypedActorConfigurator") {
diff --git a/akka-spring/src/test/scala/TypedActorBeanDefinitionParserTest.scala b/akka-spring/src/test/scala/TypedActorBeanDefinitionParserTest.scala
index 1984e32c47..7c0dd30f37 100644
--- a/akka-spring/src/test/scala/TypedActorBeanDefinitionParserTest.scala
+++ b/akka-spring/src/test/scala/TypedActorBeanDefinitionParserTest.scala
@@ -22,13 +22,13 @@ class TypedActorBeanDefinitionParserTest extends Spec with ShouldMatchers {
   describe("An TypedActorParser") {
     val parser = new Parser()
     it("should parse the typed actor configuration") {
-      val xml = 
                                                 
-                                        
+                                        
 
       val props = parser.parseTypedActor(dom(xml).getDocumentElement);
       assert(props != null)
@@ -40,7 +40,7 @@ class TypedActorBeanDefinitionParserTest extends Spec with ShouldMatchers {
     }
 
     it("should throw IllegalArgumentException on missing mandatory attributes") {
-      val xml = 
 
@@ -48,20 +48,20 @@ class TypedActorBeanDefinitionParserTest extends Spec with ShouldMatchers {
     }
 
     it("should parse TypedActors configuration with dispatcher") {
-      val xml = 
                   
-                
+                
       val props = parser.parseTypedActor(dom(xml).getDocumentElement);
       assert(props != null)
       assert(props.dispatcher.dispatcherType === "thread-based")
     }
 
     it("should parse remote TypedActors configuration") {
-      val xml = 
                   
-                
+                
       val props = parser.parseTypedActor(dom(xml).getDocumentElement);
       assert(props != null)
       assert(props.host === "com.some.host")
diff --git a/akka-spring/src/test/scala/TypedActorFactoryBeanTest.scala b/akka-spring/src/test/scala/TypedActorFactoryBeanTest.scala
index 50a284e624..4278cf14ac 100644
--- a/akka-spring/src/test/scala/TypedActorFactoryBeanTest.scala
+++ b/akka-spring/src/test/scala/TypedActorFactoryBeanTest.scala
@@ -23,8 +23,8 @@ class TypedActorFactoryBeanTest extends Spec with ShouldMatchers with BeforeAndA
   describe("A TypedActorFactoryBean") {
     val bean = new TypedActorFactoryBean
     it("should have java getters and setters for all properties") {
-      bean.setTarget("java.lang.String")
-      assert(bean.getTarget == "java.lang.String")
+      bean.setImplementation("java.lang.String")
+      assert(bean.getImplementation == "java.lang.String")
       bean.setTimeout(1000)
       assert(bean.getTimeout == 1000)
     }
@@ -47,14 +47,14 @@ class TypedActorFactoryBeanTest extends Spec with ShouldMatchers with BeforeAndA
     }
 
     it("should return the object type") {
-      bean.setTarget("java.lang.String")
+      bean.setImplementation("java.lang.String")
       assert(bean.getObjectType == classOf[String])
     }
 
     it("should create a proxy of type PojoInf") {
       val bean = new TypedActorFactoryBean()
       bean.setInterface("se.scalablesolutions.akka.spring.PojoInf")
-      bean.setTarget("se.scalablesolutions.akka.spring.Pojo")
+      bean.setImplementation("se.scalablesolutions.akka.spring.Pojo")
       bean.timeout = 1000
       val entries = new PropertyEntries()
       val entry = new PropertyEntry()

From ae75e1416b0831914ebf90100f7adaa13594a56a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Bon=C3=A9r?= 
Date: Sat, 31 Jul 2010 12:29:17 +0200
Subject: [PATCH 080/188] Removed TypedActor annotations and the method
 callbacks in the config

---
 .../akka/annotation/consume.java              |  0
 .../akka/annotation/configuration.java        | 11 ----
 .../annotation/inittransactionalstate.java    | 11 ----
 .../akka/annotation/postrestart.java          | 11 ----
 .../akka/annotation/prerestart.java           | 11 ----
 .../akka/annotation/shutdown.java             | 14 -----
 .../akka/annotation/state.java                | 11 ----
 .../akka/annotation/transactionrequired.java  | 11 ----
 .../src/main/protocol/RemoteProtocol.proto    |  4 --
 akka-core/src/main/scala/actor/ActorRef.scala |  4 +-
 .../scala/actor/SerializationProtocol.scala   | 15 +----
 .../src/main/scala/actor/TypedActor.scala     | 39 +-----------
 .../main/scala/config/SupervisionConfig.scala | 29 +--------
 .../akka/spring/akka-0.10.xsd                 | 59 +++++--------------
 .../scala/AkkaSpringConfigurationTags.scala   |  5 --
 .../main/scala/TypedActorFactoryBean.scala    | 12 ----
 .../src/main/scala/TypedActorParser.scala     | 26 ++------
 .../src/main/scala/TypedActorProperties.scala |  6 --
 .../SupervisionBeanDefinitionParserTest.scala |  3 -
 19 files changed, 29 insertions(+), 253 deletions(-)
 rename {akka-core => akka-camel}/src/main/java/se/scalablesolutions/akka/annotation/consume.java (100%)
 delete mode 100644 akka-core/src/main/java/se/scalablesolutions/akka/annotation/configuration.java
 delete mode 100644 akka-core/src/main/java/se/scalablesolutions/akka/annotation/inittransactionalstate.java
 delete mode 100644 akka-core/src/main/java/se/scalablesolutions/akka/annotation/postrestart.java
 delete mode 100644 akka-core/src/main/java/se/scalablesolutions/akka/annotation/prerestart.java
 delete mode 100644 akka-core/src/main/java/se/scalablesolutions/akka/annotation/shutdown.java
 delete mode 100644 akka-core/src/main/java/se/scalablesolutions/akka/annotation/state.java
 delete mode 100644 akka-core/src/main/java/se/scalablesolutions/akka/annotation/transactionrequired.java

diff --git a/akka-core/src/main/java/se/scalablesolutions/akka/annotation/consume.java b/akka-camel/src/main/java/se/scalablesolutions/akka/annotation/consume.java
similarity index 100%
rename from akka-core/src/main/java/se/scalablesolutions/akka/annotation/consume.java
rename to akka-camel/src/main/java/se/scalablesolutions/akka/annotation/consume.java
diff --git a/akka-core/src/main/java/se/scalablesolutions/akka/annotation/configuration.java b/akka-core/src/main/java/se/scalablesolutions/akka/annotation/configuration.java
deleted file mode 100644
index 9c5375398b..0000000000
--- a/akka-core/src/main/java/se/scalablesolutions/akka/annotation/configuration.java
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * Copyright (C) 2009-2010 Scalable Solutions AB 
- */
-
-package se.scalablesolutions.akka.actor.annotation;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface configuration {}
diff --git a/akka-core/src/main/java/se/scalablesolutions/akka/annotation/inittransactionalstate.java b/akka-core/src/main/java/se/scalablesolutions/akka/annotation/inittransactionalstate.java
deleted file mode 100644
index 35c5f05afe..0000000000
--- a/akka-core/src/main/java/se/scalablesolutions/akka/annotation/inittransactionalstate.java
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * Copyright (C) 2009-2010 Scalable Solutions AB 
- */
-
-package se.scalablesolutions.akka.actor.annotation;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface inittransactionalstate {}
diff --git a/akka-core/src/main/java/se/scalablesolutions/akka/annotation/postrestart.java b/akka-core/src/main/java/se/scalablesolutions/akka/annotation/postrestart.java
deleted file mode 100644
index 5eed474832..0000000000
--- a/akka-core/src/main/java/se/scalablesolutions/akka/annotation/postrestart.java
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * Copyright (C) 2009-2010 Scalable Solutions AB 
- */
-
-package se.scalablesolutions.akka.actor.annotation;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface postrestart {}
diff --git a/akka-core/src/main/java/se/scalablesolutions/akka/annotation/prerestart.java b/akka-core/src/main/java/se/scalablesolutions/akka/annotation/prerestart.java
deleted file mode 100644
index 94f9a01405..0000000000
--- a/akka-core/src/main/java/se/scalablesolutions/akka/annotation/prerestart.java
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * Copyright (C) 2009-2010 Scalable Solutions AB 
- */
-
-package se.scalablesolutions.akka.actor.annotation;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface prerestart {}
diff --git a/akka-core/src/main/java/se/scalablesolutions/akka/annotation/shutdown.java b/akka-core/src/main/java/se/scalablesolutions/akka/annotation/shutdown.java
deleted file mode 100644
index f806e7bca6..0000000000
--- a/akka-core/src/main/java/se/scalablesolutions/akka/annotation/shutdown.java
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * Copyright (C) 2009-2010 Scalable Solutions AB 
- */
-
-package se.scalablesolutions.akka.actor.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface shutdown {}
\ No newline at end of file
diff --git a/akka-core/src/main/java/se/scalablesolutions/akka/annotation/state.java b/akka-core/src/main/java/se/scalablesolutions/akka/annotation/state.java
deleted file mode 100644
index 509d129c1b..0000000000
--- a/akka-core/src/main/java/se/scalablesolutions/akka/annotation/state.java
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * Copyright (C) 2009-2010 Scalable Solutions AB 
- */
-
-package se.scalablesolutions.akka.actor.annotation;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.FIELD)
-public @interface state {}
diff --git a/akka-core/src/main/java/se/scalablesolutions/akka/annotation/transactionrequired.java b/akka-core/src/main/java/se/scalablesolutions/akka/annotation/transactionrequired.java
deleted file mode 100644
index c41a09ee46..0000000000
--- a/akka-core/src/main/java/se/scalablesolutions/akka/annotation/transactionrequired.java
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * Copyright (C) 2009-2010 Scalable Solutions AB 
- */
-
-package se.scalablesolutions.akka.actor.annotation;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface transactionrequired {}
diff --git a/akka-core/src/main/protocol/RemoteProtocol.proto b/akka-core/src/main/protocol/RemoteProtocol.proto
index 0417251d55..6cf9bfd534 100644
--- a/akka-core/src/main/protocol/RemoteProtocol.proto
+++ b/akka-core/src/main/protocol/RemoteProtocol.proto
@@ -138,10 +138,6 @@ enum DispatcherType {
  */
 message LifeCycleProtocol {
   required LifeCycleType lifeCycle = 1;
-  optional string preRestart = 2;
-  optional string postRestart = 3;
-  optional string init = 4;
-  optional string shutdown = 5;
 }
 
 /**
diff --git a/akka-core/src/main/scala/actor/ActorRef.scala b/akka-core/src/main/scala/actor/ActorRef.scala
index 78585b0e1b..2fd205edeb 100644
--- a/akka-core/src/main/scala/actor/ActorRef.scala
+++ b/akka-core/src/main/scala/actor/ActorRef.scala
@@ -999,7 +999,7 @@ class LocalActorRef private[akka](
       val failedActor = actorInstance.get
       guard.withGuard {
         lifeCycle match {
-          case Some(LifeCycle(Temporary, _, _)) => shutDownTemporaryActor(this)
+          case Some(LifeCycle(Temporary)) => shutDownTemporaryActor(this)
           case _ =>
             // either permanent or none where default is permanent
             Actor.log.info("Restarting actor [%s] configured as PERMANENT.", id)
@@ -1018,7 +1018,7 @@ class LocalActorRef private[akka](
     linkedActorsAsList.foreach { actorRef =>
       actorRef.lifeCycle match {
         // either permanent or none where default is permanent
-        case Some(LifeCycle(Temporary, _, _)) => shutDownTemporaryActor(actorRef)
+        case Some(LifeCycle(Temporary)) => shutDownTemporaryActor(actorRef)
         case _ => actorRef.restart(reason, maxNrOfRetries, withinTimeRange)
       }
     }
diff --git a/akka-core/src/main/scala/actor/SerializationProtocol.scala b/akka-core/src/main/scala/actor/SerializationProtocol.scala
index b1cbb53bdc..20e9842cba 100644
--- a/akka-core/src/main/scala/actor/SerializationProtocol.scala
+++ b/akka-core/src/main/scala/actor/SerializationProtocol.scala
@@ -85,14 +85,9 @@ object ActorSerialization {
       }
       val builder = LifeCycleProtocol.newBuilder
       actorRef.lifeCycle match {
-        case Some(LifeCycle(scope, None, _)) =>
+        case Some(LifeCycle(scope)) =>
           setScope(builder, scope)
           Some(builder.build)
-        case Some(LifeCycle(scope, Some(callbacks), _)) =>
-          setScope(builder, scope)
-          builder.setPreRestart(callbacks.preRestart)
-          builder.setPostRestart(callbacks.postRestart)
-          Some(builder.build)
         case None => None
       }
     }
@@ -134,12 +129,8 @@ object ActorSerialization {
     val lifeCycle =
       if (protocol.hasLifeCycle) {
         val lifeCycleProtocol = protocol.getLifeCycle
-        val restartCallbacks =
-          if (lifeCycleProtocol.hasPreRestart || lifeCycleProtocol.hasPostRestart)
-            Some(RestartCallbacks(lifeCycleProtocol.getPreRestart, lifeCycleProtocol.getPostRestart))
-          else None
-        Some(if (lifeCycleProtocol.getLifeCycle == LifeCycleType.PERMANENT) LifeCycle(Permanent, restartCallbacks)
-             else if (lifeCycleProtocol.getLifeCycle == LifeCycleType.TEMPORARY) LifeCycle(Temporary, restartCallbacks)
+        Some(if (lifeCycleProtocol.getLifeCycle == LifeCycleType.PERMANENT) LifeCycle(Permanent)
+             else if (lifeCycleProtocol.getLifeCycle == LifeCycleType.TEMPORARY) LifeCycle(Temporary)
              else throw new IllegalActorStateException("LifeCycle type is not valid: " + lifeCycleProtocol.getLifeCycle))
       } else None
 
diff --git a/akka-core/src/main/scala/actor/TypedActor.scala b/akka-core/src/main/scala/actor/TypedActor.scala
index 460012a84f..ae72da4d70 100644
--- a/akka-core/src/main/scala/actor/TypedActor.scala
+++ b/akka-core/src/main/scala/actor/TypedActor.scala
@@ -12,7 +12,6 @@ import se.scalablesolutions.akka.dispatch.{MessageDispatcher, Future, Completabl
 import se.scalablesolutions.akka.config.ScalaConfig._
 import se.scalablesolutions.akka.serialization.Serializer
 import se.scalablesolutions.akka.util._
-import se.scalablesolutions.akka.actor.annotation._
 
 import org.codehaus.aspectwerkz.joinpoint.{MethodRtti, JoinPoint}
 import org.codehaus.aspectwerkz.proxy.Proxy
@@ -189,7 +188,6 @@ abstract class TypedActor extends Logging {
  *
  * @author Jonas Bonér
  */
-@transactionrequired
 abstract class TypedTransactor extends TypedActor
 
 /**
@@ -201,8 +199,6 @@ abstract class TypedTransactor extends TypedActor
  */
 final class TypedActorConfiguration {
   private[akka] var _timeout: Long = Actor.TIMEOUT
-  private[akka] var _restartCallbacks: Option[RestartCallbacks] = None
-  private[akka] var _shutdownCallback: Option[ShutdownCallback] = None
   private[akka] var _transactionRequired = false
   private[akka] var _host: Option[InetSocketAddress] = None
   private[akka] var _messageDispatcher: Option[MessageDispatcher] = None
@@ -213,16 +209,6 @@ final class TypedActorConfiguration {
     this
   }
 
-  def restartCallbacks(pre: String, post: String) : TypedActorConfiguration = {
-    _restartCallbacks = Some(new RestartCallbacks(pre, post))
-    this
-  }
-
-  def shutdownCallback(down: String) : TypedActorConfiguration = {
-    _shutdownCallback = Some(new ShutdownCallback(down))
-    this
-  }
-
   def makeTransactionRequired() : TypedActorConfiguration = {
     _transactionRequired = true;
     this
@@ -501,17 +487,6 @@ private[akka] object TypedActorContext {
   private[actor] val senderFuture = new DynamicVariable[CompletableFuture[Any]](null)
 }
 
-/**
- * @author Jonas Bonér
- */
-object Annotations {
-  val transactionrequired =    classOf[transactionrequired]
-  val prerestart =             classOf[prerestart]
-  val postrestart =            classOf[postrestart]
-  val shutdown =               classOf[shutdown]
-  val inittransactionalstate = classOf[inittransactionalstate]
-}
-
 /**
  * @author Jonas Bonér
  */
@@ -716,7 +691,6 @@ private[akka] sealed class TypedActorAspect {
 object Dispatcher {
   val ZERO_ITEM_CLASS_ARRAY = Array[Class[_]]()
   val ZERO_ITEM_OBJECT_ARRAY = Array[Object]()
-//  var crashedActorTl: ThreadLocal[Dispatcher] = new ThreadLocal();
 }
 
 /**
@@ -773,7 +747,6 @@ private[akka] class Dispatcher(transactionalRequired: Boolean) extends Actor {
   }
 
   override def preRestart(reason: Throwable) {
-//    crashedActorTl.set(this)
     targetInstance.preRestart(reason)
 
     // rewrite target instance in Dispatcher and AspectWerkz Proxy
@@ -785,16 +758,6 @@ private[akka] class Dispatcher(transactionalRequired: Boolean) extends Actor {
     targetInstance.postRestart(reason)
   }
 
-  override def init {
-    // Get the crashed dispatcher from thread local and intitialize this actor with the
-    // contents of the old dispatcher
-//    val oldActor = crashedActorTl.get
-//    if (oldActor != null) {
-//      initialize(oldActor.targetClass, oldActor.targetInstance, oldActor.proxy, oldActor.context)
-//      crashedActorTl.set(null)
-//    }
-  }
-
   override def shutdown {
     targetInstance.shutdown
     AspectInitRegistry.unregister(proxy);
@@ -806,7 +769,7 @@ private[akka] class Dispatcher(transactionalRequired: Boolean) extends Actor {
 
   def isTransactional(clazz: Class[_]): Boolean =
     if (clazz == null) false
-    else if (clazz.isAnnotationPresent(Annotations.transactionrequired)) true
+    else if (clazz.isAssignableFrom(classOf[TypedTransactor])) true
     else isTransactional(clazz.getSuperclass)
 
   private def serializeArguments(joinPoint: JoinPoint) = {
diff --git a/akka-core/src/main/scala/config/SupervisionConfig.scala b/akka-core/src/main/scala/config/SupervisionConfig.scala
index 1f5fd15a9b..cb0829704d 100644
--- a/akka-core/src/main/scala/config/SupervisionConfig.scala
+++ b/akka-core/src/main/scala/config/SupervisionConfig.scala
@@ -42,16 +42,7 @@ object ScalaConfig {
   case object AllForOne extends FailOverScheme
   case object OneForOne extends FailOverScheme
 
-  case class LifeCycle(scope: Scope,
-                       restartCallbacks: Option[RestartCallbacks] = None,
-                       shutdownCallback: Option[ShutdownCallback] = None) extends ConfigElement
-  case class RestartCallbacks(preRestart: String, postRestart: String) {
-    if ((preRestart eq null) || (postRestart eq null)) throw new IllegalArgumentException("Restart callback methods can't be null")
-  }
-  case class ShutdownCallback(shutdown: String) {
-    if (shutdown eq null) throw new IllegalArgumentException("Shutdown callback method can't be null")
-  }
-
+  case class LifeCycle(scope: Scope) extends ConfigElement
   case object Permanent extends Scope
   case object Temporary extends Scope
 
@@ -137,26 +128,12 @@ object JavaConfig {
       scheme.transform, maxNrOfRetries, withinTimeRange, trapExceptions.toList)
   }
 
-  class LifeCycle(@BeanProperty val scope: Scope,
-                  @BeanProperty val restartCallbacks: RestartCallbacks,
-                  @BeanProperty val shutdownCallback: ShutdownCallback) extends ConfigElement {
-    def this(scope: Scope) = this(scope, null, null)
-    def this(scope: Scope, restartCallbacks: RestartCallbacks) = this(scope, restartCallbacks, null)
-    def this(scope: Scope, shutdownCallback: ShutdownCallback) = this(scope, null, shutdownCallback)
+  class LifeCycle(@BeanProperty val scope: Scope) extends ConfigElement {
     def transform = {
-      val restartCallbacksOption = if (restartCallbacks eq null) None else Some(restartCallbacks.transform)
-      val shutdownCallbackOption = if (shutdownCallback eq null) None else Some(shutdownCallback.transform)
-      se.scalablesolutions.akka.config.ScalaConfig.LifeCycle(scope.transform, restartCallbacksOption, shutdownCallbackOption)
+      se.scalablesolutions.akka.config.ScalaConfig.LifeCycle(scope.transform)
     }
   }
 
-  class RestartCallbacks(@BeanProperty val preRestart: String, @BeanProperty val postRestart: String) {
-    def transform = se.scalablesolutions.akka.config.ScalaConfig.RestartCallbacks(preRestart, postRestart)
-  }
-  class ShutdownCallback(@BeanProperty val shutdown: String) {
-    def transform = se.scalablesolutions.akka.config.ScalaConfig.ShutdownCallback(shutdown)
-  }
-
   abstract class Scope extends ConfigElement {
     def transform: se.scalablesolutions.akka.config.ScalaConfig.Scope
   }
diff --git a/akka-spring/src/main/resources/se/scalablesolutions/akka/spring/akka-0.10.xsd b/akka-spring/src/main/resources/se/scalablesolutions/akka/spring/akka-0.10.xsd
index ed83a5bdc2..6dd0ee7681 100644
--- a/akka-spring/src/main/resources/se/scalablesolutions/akka/spring/akka-0.10.xsd
+++ b/akka-spring/src/main/resources/se/scalablesolutions/akka/spring/akka-0.10.xsd
@@ -105,46 +105,22 @@
     
   
 
-  
-  
-    
-      
-        
-          Pre restart callback method that is called during restart.
-        
-      
-    
-    
-      
-        
-          Post restart callback method that is called during restart.
-        
-      
-    
-  
-
-  
-  
-    
-      
-        
-          Shutdown callback method that is called during shut down.
-        
-      
-    
-  
-
   
   
    
       
-      
-      
       
       
       
     
     
+    
+      
+        
+          Name of the interface implemented by implementation class.
+        
+      
+    
     
       
         
@@ -155,35 +131,28 @@
     
       
         
-          default timeout for '!!' invocations
+          Theh default timeout for '!!' invocations.
         
       
     
     
       
         
-          Set to true if messages should have REQUIRES_NEW semantics
-        
-      
-    
-    
-      
-        
-          Interface implemented by target class.
+          Set this to true if messages should have REQUIRES_NEW semantics.
         
       
     
     
       
         
-          Lifecycle, permanent or temporary
+          Defines the lifecycle, can be either 'permanent' or 'temporary'.
         
       
     
     
       
         
-          Supported scopes are singleton and prototype
+          Supported scopes are 'singleton' and 'prototype'.
         
       
     
@@ -211,21 +180,21 @@
     
       
         
-          Failover scheme, AllForOne or OneForOne
+          Failover scheme, can be one of 'AllForOne' or 'OneForOne'.
         
       
     
     
       
         
-          Maximal number of retries.
+          Maximal number of restarts.
         
       
     
     
       
         
-          Timerange for restart.
+          Time range for maximal number of restart.
         
       
     
diff --git a/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala b/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala
index 0d4ff9aaab..857d20fa55 100644
--- a/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala
+++ b/akka-spring/src/main/scala/AkkaSpringConfigurationTags.scala
@@ -20,8 +20,6 @@ object AkkaSpringConfigurationTags {
   val CAMEL_SERVICE_TAG = "camel-service"
 
   // typed-actor sub tags
-  val RESTART_CALLBACKS_TAG = "restart-callbacks"
-  val SHUTDOWN_CALLBACK_TAG = "shutdown-callback"
   val REMOTE_TAG = "remote"
 
   // superivision sub tags
@@ -45,9 +43,6 @@ object AkkaSpringConfigurationTags {
   val TRANSACTIONAL = "transactional"
   val HOST = "host"
   val PORT = "port"
-  val PRE_RESTART = "pre"
-  val POST_RESTART = "post"
-  val SHUTDOWN = "shutdown"
   val LIFECYCLE = "lifecycle"
   val SCOPE = "scope"
 
diff --git a/akka-spring/src/main/scala/TypedActorFactoryBean.scala b/akka-spring/src/main/scala/TypedActorFactoryBean.scala
index 8ddcaced6a..0cb70e5ae3 100644
--- a/akka-spring/src/main/scala/TypedActorFactoryBean.scala
+++ b/akka-spring/src/main/scala/TypedActorFactoryBean.scala
@@ -21,7 +21,6 @@ import org.springframework.util.ReflectionUtils
 import org.springframework.util.StringUtils
 
 import se.scalablesolutions.akka.actor.{AspectInitRegistry, TypedActorConfiguration, TypedActor}
-import se.scalablesolutions.akka.config.ScalaConfig.{ShutdownCallback, RestartCallbacks}
 import se.scalablesolutions.akka.dispatch.MessageDispatcher
 import se.scalablesolutions.akka.util.{Logging, Duration}
 
@@ -50,9 +49,6 @@ class TypedActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging wit
   @BeanProperty var implementation: String = ""
   @BeanProperty var timeout: Long = _
   @BeanProperty var transactional: Boolean = false
-  @BeanProperty var pre: String = ""
-  @BeanProperty var post: String = ""
-  @BeanProperty var shutdown: String = ""
   @BeanProperty var host: String = ""
   @BeanProperty var port: Int = _
   @BeanProperty var lifecycle: String = ""
@@ -137,8 +133,6 @@ class TypedActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging wit
 
   private[akka] def createConfig: TypedActorConfiguration = {
     val config = new TypedActorConfiguration().timeout(Duration(timeout, "millis"))
-    if (hasRestartCallbacks) config.restartCallbacks(pre, post)
-    if (hasShutdownCallback) config.shutdownCallback(shutdown)
     if (transactional) config.makeTransactionRequired
     config
   }
@@ -147,12 +141,6 @@ class TypedActorFactoryBean extends AbstractFactoryBean[AnyRef] with Logging wit
 
   private[akka] def hasInterface = (interface != null) && (!interface.isEmpty)
 
-  private[akka] def hasRestartCallbacks =
-    ((pre != null) && !pre.isEmpty) ||
-    ((post != null) && !post.isEmpty)
-
-  private[akka] def hasShutdownCallback = ((shutdown != null) && !shutdown.isEmpty)
-
   private[akka] def hasDispatcher =
     (dispatcher != null) &&
     (dispatcher.dispatcherType != null) &&
diff --git a/akka-spring/src/main/scala/TypedActorParser.scala b/akka-spring/src/main/scala/TypedActorParser.scala
index 1483a35dba..5f4d68f297 100644
--- a/akka-spring/src/main/scala/TypedActorParser.scala
+++ b/akka-spring/src/main/scala/TypedActorParser.scala
@@ -26,8 +26,6 @@ trait TypedActorParser extends BeanParser with DispatcherParser {
   def parseTypedActor(element: Element): TypedActorProperties = {
     val objectProperties = new TypedActorProperties()
     val remoteElement = DomUtils.getChildElementByTagName(element, REMOTE_TAG);
-    val restartCallbacksElement = DomUtils.getChildElementByTagName(element, RESTART_CALLBACKS_TAG);
-    val shutdownCallbackElement = DomUtils.getChildElementByTagName(element, SHUTDOWN_CALLBACK_TAG);
     val dispatcherElement = DomUtils.getChildElementByTagName(element, DISPATCHER_TAG)
     val propertyEntries = DomUtils.getChildElementsByTagName(element,PROPERTYENTRY_TAG)
 
@@ -36,29 +34,17 @@ trait TypedActorParser extends BeanParser with DispatcherParser {
       objectProperties.port = mandatory(remoteElement, PORT).toInt
     }
 
-    if (restartCallbacksElement != null) {
-      objectProperties.preRestart = restartCallbacksElement.getAttribute(PRE_RESTART)
-      objectProperties.postRestart = restartCallbacksElement.getAttribute(POST_RESTART)
-      if ((objectProperties.preRestart.isEmpty) && (objectProperties.preRestart.isEmpty)) {
-        throw new IllegalActorStateException("At least one of pre or post must be defined.")
-      }
-    }
-
-    if (shutdownCallbackElement != null) {
-      objectProperties.shutdown = shutdownCallbackElement.getAttribute("method")
-    }
-
     if (dispatcherElement != null) {
       val dispatcherProperties = parseDispatcher(dispatcherElement)
       objectProperties.dispatcher = dispatcherProperties
     }
 
-    for(element <- propertyEntries) {
-            val entry = new PropertyEntry()
-            entry.name = element.getAttribute("name");
-        entry.value = element.getAttribute("value")
-                entry.ref   = element.getAttribute("ref")
-                objectProperties.propertyEntries.add(entry)
+    for (element <- propertyEntries) {
+      val entry = new PropertyEntry
+      entry.name = element.getAttribute("name");
+      entry.value = element.getAttribute("value")
+      entry.ref   = element.getAttribute("ref")
+      objectProperties.propertyEntries.add(entry)
     }
 
     try {
diff --git a/akka-spring/src/main/scala/TypedActorProperties.scala b/akka-spring/src/main/scala/TypedActorProperties.scala
index 6390110676..46c9cd35aa 100644
--- a/akka-spring/src/main/scala/TypedActorProperties.scala
+++ b/akka-spring/src/main/scala/TypedActorProperties.scala
@@ -17,9 +17,6 @@ class TypedActorProperties {
   var timeout: Long = _
   var interface: String = ""
   var transactional: Boolean = false
-  var preRestart: String = ""
-  var postRestart: String = ""
-  var shutdown: String = ""
   var host: String = ""
   var port: Int = _
   var lifecycle: String = ""
@@ -35,9 +32,6 @@ class TypedActorProperties {
   def setAsProperties(builder: BeanDefinitionBuilder) {
     builder.addPropertyValue(HOST, host)
     builder.addPropertyValue(PORT, port)
-    builder.addPropertyValue(PRE_RESTART, preRestart)
-    builder.addPropertyValue(POST_RESTART, postRestart)
-    builder.addPropertyValue(SHUTDOWN, shutdown)
     builder.addPropertyValue(TIMEOUT, timeout)
     builder.addPropertyValue(IMPLEMENTATION, target)
     builder.addPropertyValue(INTERFACE, interface)
diff --git a/akka-spring/src/test/scala/SupervisionBeanDefinitionParserTest.scala b/akka-spring/src/test/scala/SupervisionBeanDefinitionParserTest.scala
index cd185c9b4b..a5fc44007f 100644
--- a/akka-spring/src/test/scala/SupervisionBeanDefinitionParserTest.scala
+++ b/akka-spring/src/test/scala/SupervisionBeanDefinitionParserTest.scala
@@ -59,9 +59,6 @@ class SupervisionBeanDefinitionParserTest extends Spec with ShouldMatchers {
       expect("foo.bar.Bar") { prop2.target }
       expect("foo.bar.MyPojo") { prop3.target }
       expect("foo.bar.MyPojo") { prop4.target }
-      expect("preRestart") { prop3.preRestart }
-      expect("postRestart") { prop3.postRestart }
-      expect("shutdown") { prop4.shutdown }
       expect("permanent") { prop1.lifecycle }
       expect("temporary") { prop4.lifecycle }
     }

From e5c1a45c5800855d02eca2e640aa4f1ea3951eb8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Bon=C3=A9r?= 
Date: Sat, 31 Jul 2010 12:37:08 +0200
Subject: [PATCH 081/188] formatting

---
 project/build/AkkaProject.scala | 115 ++++++++++++++++----------------
 1 file changed, 58 insertions(+), 57 deletions(-)

diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala
index f2b1dd33bc..e63bfc573f 100644
--- a/project/build/AkkaProject.scala
+++ b/project/build/AkkaProject.scala
@@ -37,20 +37,20 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) {
   lazy val dist = zipTask(allArtifacts, "dist", distName) dependsOn (`package`) describedAs("Zips up the distribution.")
 
   // -------------------------------------------------------------------------------------------------------------------
-        // All repositories *must* go here! See ModuleConigurations below.
+  // All repositories *must* go here! See ModuleConigurations below.
   // -------------------------------------------------------------------------------------------------------------------
 
-        object Repositories {
-          lazy val AkkaRepo             = MavenRepository("Akka Repository", "http://scalablesolutions.se/akka/repository")
-          lazy val CodehausSnapshotRepo = MavenRepository("Codehaus Snapshots", "http://snapshots.repository.codehaus.org")
-          lazy val EmbeddedRepo         = MavenRepository("Embedded Repo", (info.projectPath / "embedded-repo").asURL.toString)
-          lazy val FusesourceSnapshotRepo = MavenRepository("Fusesource Snapshots", "http://repo.fusesource.com/nexus/content/repositories/snapshots")
-          lazy val GuiceyFruitRepo      = MavenRepository("GuiceyFruit Repo", "http://guiceyfruit.googlecode.com/svn/repo/releases/")
-          lazy val JBossRepo            = MavenRepository("JBoss Repo", "https://repository.jboss.org/nexus/content/groups/public/")
-          lazy val JavaNetRepo          = MavenRepository("java.net Repo", "http://download.java.net/maven/2")
-          lazy val SonatypeSnapshotRepo = MavenRepository("Sonatype OSS Repo", "http://oss.sonatype.org/content/repositories/releases")
-          lazy val SunJDMKRepo          = MavenRepository("Sun JDMK Repo", "http://wp5.e-taxonomy.eu/cdmlib/mavenrepo")
-        }
+  object Repositories {
+    lazy val AkkaRepo             = MavenRepository("Akka Repository", "http://scalablesolutions.se/akka/repository")
+    lazy val CodehausSnapshotRepo = MavenRepository("Codehaus Snapshots", "http://snapshots.repository.codehaus.org")
+    lazy val EmbeddedRepo         = MavenRepository("Embedded Repo", (info.projectPath / "embedded-repo").asURL.toString)
+    lazy val FusesourceSnapshotRepo = MavenRepository("Fusesource Snapshots", "http://repo.fusesource.com/nexus/content/repositories/snapshots")
+    lazy val GuiceyFruitRepo      = MavenRepository("GuiceyFruit Repo", "http://guiceyfruit.googlecode.com/svn/repo/releases/")
+    lazy val JBossRepo            = MavenRepository("JBoss Repo", "https://repository.jboss.org/nexus/content/groups/public/")
+    lazy val JavaNetRepo          = MavenRepository("java.net Repo", "http://download.java.net/maven/2")
+    lazy val SonatypeSnapshotRepo = MavenRepository("Sonatype OSS Repo", "http://oss.sonatype.org/content/repositories/releases")
+    lazy val SunJDMKRepo          = MavenRepository("Sun JDMK Repo", "http://wp5.e-taxonomy.eu/cdmlib/mavenrepo")
+  }
 
   // -------------------------------------------------------------------------------------------------------------------
   // ModuleConfigurations
@@ -59,7 +59,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) {
   // Therefore, if repositories are defined, this must happen as def, not as val.
   // -------------------------------------------------------------------------------------------------------------------
 
-        import Repositories._
+  import Repositories._
   lazy val atmosphereModuleConfig  = ModuleConfiguration("org.atmosphere", SonatypeSnapshotRepo)
   lazy val grizzlyModuleConfig     = ModuleConfiguration("com.sun.grizzly", JavaNetRepo)
   lazy val guiceyFruitModuleConfig = ModuleConfiguration("org.guiceyfruit", GuiceyFruitRepo)
@@ -84,16 +84,16 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) {
   lazy val ATMO_VERSION       = "0.6"
   lazy val CAMEL_VERSION      = "2.4.0"
   lazy val CASSANDRA_VERSION  = "0.6.1"
-        lazy val DispatchVersion    = "0.7.4"
+  lazy val DispatchVersion    = "0.7.4"
   lazy val HAWTDISPATCH_VERSION = "1.0"
-        lazy val JacksonVersion     = "1.2.1"
+  lazy val JacksonVersion     = "1.2.1"
   lazy val JERSEY_VERSION     = "1.2"
   lazy val LIFT_VERSION       = "2.0-scala280-SNAPSHOT"
   lazy val MULTIVERSE_VERSION = "0.6-SNAPSHOT"
   lazy val SCALATEST_VERSION  = "1.2-for-scala-2.8.0.final-SNAPSHOT"
-        lazy val Slf4jVersion       = "1.6.0"
+  lazy val Slf4jVersion       = "1.6.0"
   lazy val SPRING_VERSION     = "3.0.3.RELEASE"
-        lazy val WerkzVersion       = "2.2.1"
+  lazy val WerkzVersion       = "2.2.1"
 
   // -------------------------------------------------------------------------------------------------------------------
   // Dependencies
@@ -317,9 +317,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) {
        None
     } dependsOn(dist) describedAs("Run mvn install for artifacts in dist.")
 
-        // -------------------------------------------------------------------------------------------------------------------
-        // akka-core subproject
-        // -------------------------------------------------------------------------------------------------------------------
+  // -------------------------------------------------------------------------------------------------------------------
+  // akka-core subproject
+  // -------------------------------------------------------------------------------------------------------------------
 
   class AkkaCoreProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin {
     val aopalliance   = Dependencies.aopalliance
@@ -349,9 +349,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) {
     val scalatest = Dependencies.scalatest
   }
 
-        // -------------------------------------------------------------------------------------------------------------------
-        // akka-amqp subproject
-        // -------------------------------------------------------------------------------------------------------------------
+  // -------------------------------------------------------------------------------------------------------------------
+  // akka-amqp subproject
+  // -------------------------------------------------------------------------------------------------------------------
 
   class AkkaAMQPProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin {
     val commons_io = Dependencies.commons_io
@@ -363,9 +363,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) {
     val scalatest  = Dependencies.scalatest
   }
 
-        // -------------------------------------------------------------------------------------------------------------------
-        // akka-http subproject
-        // -------------------------------------------------------------------------------------------------------------------
+  // -------------------------------------------------------------------------------------------------------------------
+  // akka-http subproject
+  // -------------------------------------------------------------------------------------------------------------------
 
   class AkkaHttpProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin {
     val annotation       = Dependencies.annotation
@@ -392,17 +392,17 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) {
     val scalatest = Dependencies.scalatest
   }
 
-        // -------------------------------------------------------------------------------------------------------------------
-        // akka-camel subproject
-        // -------------------------------------------------------------------------------------------------------------------
+  // -------------------------------------------------------------------------------------------------------------------
+  // akka-camel subproject
+  // -------------------------------------------------------------------------------------------------------------------
 
   class AkkaCamelProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin {
     val camel_core = Dependencies.camel_core
   }
 
-        // -------------------------------------------------------------------------------------------------------------------
-        // akka-persistence subproject
-        // -------------------------------------------------------------------------------------------------------------------
+  // -------------------------------------------------------------------------------------------------------------------
+  // akka-persistence subproject
+  // -------------------------------------------------------------------------------------------------------------------
 
   class AkkaPersistenceParentProject(info: ProjectInfo) extends ParentProject(info) {
     lazy val akka_persistence_common = project("akka-persistence-common", "akka-persistence-common",
@@ -415,17 +415,18 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) {
       new AkkaCassandraProject(_), akka_persistence_common)
   }
 
-        // -------------------------------------------------------------------------------------------------------------------
-        // akka-persistence-common subproject
-        // -------------------------------------------------------------------------------------------------------------------
+  // -------------------------------------------------------------------------------------------------------------------
+  // akka-persistence-common subproject
+  // -------------------------------------------------------------------------------------------------------------------
+  
   class AkkaPersistenceCommonProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) {
     val commons_pool = Dependencies.commons_pool
     val thrift       = Dependencies.thrift
   }
 
-        // -------------------------------------------------------------------------------------------------------------------
-        // akka-persistence-redis subproject
-        // -------------------------------------------------------------------------------------------------------------------
+  // -------------------------------------------------------------------------------------------------------------------
+  // akka-persistence-redis subproject
+  // -------------------------------------------------------------------------------------------------------------------
 
   class AkkaRedisProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) {
     val commons_codec = Dependencies.commons_codec
@@ -434,9 +435,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) {
     override def testOptions = TestFilter((name: String) => name.endsWith("Test")) :: Nil
   }
 
-        // -------------------------------------------------------------------------------------------------------------------
-        // akka-persistence-mongo subproject
-        // -------------------------------------------------------------------------------------------------------------------
+  // -------------------------------------------------------------------------------------------------------------------
+  // akka-persistence-mongo subproject
+  // -------------------------------------------------------------------------------------------------------------------
 
   class AkkaMongoProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) {
     val mongo = Dependencies.mongo
@@ -444,7 +445,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) {
     override def testOptions = TestFilter((name: String) => name.endsWith("Test")) :: Nil
   }
 
-        // -------------------------------------------------------------------------------------------------------------------
+  // -------------------------------------------------------------------------------------------------------------------
         // akka-persistence-cassandra subproject
         // -------------------------------------------------------------------------------------------------------------------
 
@@ -483,9 +484,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) {
     val scalatest    = Dependencies.scalatest
   }
 
-        // -------------------------------------------------------------------------------------------------------------------
-        // akka-jta subproject
-        // -------------------------------------------------------------------------------------------------------------------
+  // -------------------------------------------------------------------------------------------------------------------
+  // akka-jta subproject
+  // -------------------------------------------------------------------------------------------------------------------
 
   class AkkaJTAProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin {
     val atomikos_transactions     = Dependencies.atomikos_transactions
@@ -495,9 +496,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) {
     //val atomikos_transactions_util = "com.atomikos" % "transactions-util" % "3.2.3" % "compile"
   }
 
-        // -------------------------------------------------------------------------------------------------------------------
-        // OSGi stuff
-        // -------------------------------------------------------------------------------------------------------------------
+  // -------------------------------------------------------------------------------------------------------------------
+  // OSGi stuff
+  // -------------------------------------------------------------------------------------------------------------------
 
   class AkkaOSGiParentProject(info: ProjectInfo) extends ParentProject(info) {
     lazy val akka_osgi_dependencies_bundle = project("akka-osgi-dependencies-bundle", "akka-osgi-dependencies-bundle",
@@ -587,9 +588,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) {
     override def artifacts = Set.empty
   }
 
-        // -------------------------------------------------------------------------------------------------------------------
-        // Test
-        // -------------------------------------------------------------------------------------------------------------------
+  // -------------------------------------------------------------------------------------------------------------------
+  // Test
+  // -------------------------------------------------------------------------------------------------------------------
 
   class AkkaTypedActorTestProject(info: ProjectInfo) extends DefaultProject(info) {
     // testing
@@ -597,9 +598,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) {
     val jmock = "org.jmock" % "jmock" % "2.4.0" % "test"
   }
 
-        // -------------------------------------------------------------------------------------------------------------------
-        // Examples
-        // -------------------------------------------------------------------------------------------------------------------
+  // -------------------------------------------------------------------------------------------------------------------
+  // Examples
+  // -------------------------------------------------------------------------------------------------------------------
 
   class AkkaSampleAntsProject(info: ProjectInfo) extends DefaultSpdeProject(info) with CodeFellowPlugin {
 //    val scalaToolsSnapshots = ScalaToolsSnapshots
@@ -682,9 +683,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) {
       new AkkaSampleOSGiProject(_), akka_core)
   }
 
-        // -------------------------------------------------------------------------------------------------------------------
-        // Helpers
-        // -------------------------------------------------------------------------------------------------------------------
+  // -------------------------------------------------------------------------------------------------------------------
+  // Helpers
+  // -------------------------------------------------------------------------------------------------------------------
 
   def removeDupEntries(paths: PathFinder) =
    Path.lazyPathFinder {

From f3497142c8cd23a6507d8a6ad3973d1b2671d839 Mon Sep 17 00:00:00 2001
From: Martin Krasser 
Date: Sun, 1 Aug 2010 15:27:06 +0200
Subject: [PATCH 082/188] Test cases for handling actor failures in Camel
 routes.

---
 .../component/ActorComponentFeatureTest.scala | 53 ++++++++++++++++++-
 1 file changed, 51 insertions(+), 2 deletions(-)

diff --git a/akka-camel/src/test/scala/component/ActorComponentFeatureTest.scala b/akka-camel/src/test/scala/component/ActorComponentFeatureTest.scala
index 7d1482c36c..3817bc239e 100644
--- a/akka-camel/src/test/scala/component/ActorComponentFeatureTest.scala
+++ b/akka-camel/src/test/scala/component/ActorComponentFeatureTest.scala
@@ -3,23 +3,31 @@ package se.scalablesolutions.akka.camel.component
 import java.util.concurrent.{TimeUnit, CountDownLatch}
 
 import org.apache.camel.RuntimeCamelException
+import org.apache.camel.builder.RouteBuilder
+import org.apache.camel.component.mock.MockEndpoint
 import org.scalatest.{BeforeAndAfterEach, BeforeAndAfterAll, FeatureSpec}
 
 import se.scalablesolutions.akka.actor.Actor._
 import se.scalablesolutions.akka.actor.{ActorRegistry, Actor}
-import se.scalablesolutions.akka.camel.{Message, CamelContextManager}
+import se.scalablesolutions.akka.camel.{Failure, Message, CamelContextManager}
 import se.scalablesolutions.akka.camel.support._
 
 class ActorComponentFeatureTest extends FeatureSpec with BeforeAndAfterAll with BeforeAndAfterEach {
+  import ActorComponentFeatureTest._
+
   override protected def beforeAll = {
     ActorRegistry.shutdownAll
     CamelContextManager.init
+    CamelContextManager.context.addRoutes(new TestRoute)
     CamelContextManager.start
   }
 
   override protected def afterAll = CamelContextManager.stop
 
-  override protected def afterEach = ActorRegistry.shutdownAll
+  override protected def afterEach = {
+    ActorRegistry.shutdownAll
+    mockEndpoint.reset
+  }
 
   feature("Communicate with an actor from a Camel application using actor endpoint URIs") {
     import CamelContextManager.template
@@ -58,5 +66,46 @@ class ActorComponentFeatureTest extends FeatureSpec with BeforeAndAfterAll with
         template.requestBody("actor:uuid:%s?blocking=true" format actor.uuid, "Martin")
       }
     }
+
+    scenario("two-way async communication with failure response") {
+      mockEndpoint.expectedBodiesReceived("whatever")
+      template.requestBody("direct:failure-test-1", "whatever")
+      mockEndpoint.assertIsSatisfied
+    }
+
+    scenario("two-way sync communication with exception") {
+      mockEndpoint.expectedBodiesReceived("whatever")
+      template.requestBody("direct:failure-test-2", "whatever")
+      mockEndpoint.assertIsSatisfied
+    }
+  }
+
+  private def mockEndpoint = CamelContextManager.context.getEndpoint("mock:mock", classOf[MockEndpoint])
+}
+
+object ActorComponentFeatureTest {
+  class FailWithMessage extends Actor {
+    protected def receive = {
+      case msg: Message => self.reply(Failure(new Exception("test")))
+    }
+  }
+
+  class FailWithException extends Actor {
+    protected def receive = {
+      case msg: Message => throw new Exception("test")
+    }
+  }
+
+  class TestRoute extends RouteBuilder {
+    val failWithMessage = actorOf[FailWithMessage].start
+    val failWithException = actorOf[FailWithException].start
+    def configure {
+      from("direct:failure-test-1")
+        .onException(classOf[Exception]).to("mock:mock").handled(true).end
+        .to("actor:uuid:%s" format failWithMessage.uuid)
+      from("direct:failure-test-2")
+        .onException(classOf[Exception]).to("mock:mock").handled(true).end
+        .to("actor:uuid:%s?blocking=true" format failWithException.uuid)
+    }
   }
 }

From 3e423acf8397963c31656aea6c89a2cfbfebd797 Mon Sep 17 00:00:00 2001
From: Peter Vlugter 
Date: Mon, 2 Aug 2010 15:49:04 +1200
Subject: [PATCH 083/188] Ref extends Multiverse BasicRef (closes #253)

---
 akka-core/src/main/scala/stm/Ref.scala        | 119 +++++-------------
 .../src/main/scala/stm/TransactionalMap.scala |  18 +--
 .../main/scala/stm/TransactionalVector.scala  |  12 +-
 .../NestedTransactionalTypedActorImpl.java    |   2 +-
 .../actor/TransactionalTypedActorImpl.java    |   2 +-
 .../scala/actor/actor/TransactorSpec.scala    |   8 +-
 akka-core/src/test/scala/stm/RefSpec.scala    |  92 +++++++-------
 akka-core/src/test/scala/stm/StmSpec.scala    |  82 ++++++------
 .../src/main/scala/Storage.scala              |  18 +--
 .../src/main/scala/Ants.scala                 |   2 +-
 10 files changed, 155 insertions(+), 200 deletions(-)

diff --git a/akka-core/src/main/scala/stm/Ref.scala b/akka-core/src/main/scala/stm/Ref.scala
index 3b13d32971..2ca6802b15 100644
--- a/akka-core/src/main/scala/stm/Ref.scala
+++ b/akka-core/src/main/scala/stm/Ref.scala
@@ -6,23 +6,15 @@ package se.scalablesolutions.akka.stm
 
 import se.scalablesolutions.akka.util.UUID
 
-import org.multiverse.api.GlobalStmInstance.getGlobalStmInstance
-
-object RefFactory {
-  private val factory = getGlobalStmInstance.getProgrammaticRefFactoryBuilder.build
-
-  def createRef[T] = factory.atomicCreateRef[T]()
-
-  def createRef[T](value: T) = factory.atomicCreateRef(value)
-}
+import org.multiverse.transactional.refs.BasicRef
 
 /**
- * Ref.
+ * Ref
  *
  * @author Jonas Bonér
  */
 object Ref {
-  def apply[T]() = new Ref[T]
+  def apply[T]() = new Ref[T]()
 
   def apply[T](initialValue: T) = new Ref[T](Some(initialValue))
 
@@ -33,77 +25,47 @@ object Ref {
 }
 
 /**
- * Implements a transactional managed reference.
+ * Transactional managed reference.
  *
  * @author Jonas Bonér
  */
-class Ref[T](initialOpt: Option[T] = None) extends Transactional {
+class Ref[T](initialOpt: Option[T] = None)
+  extends BasicRef[T](initialOpt.getOrElse(null.asInstanceOf[T]))
+  with Transactional {
+
   self =>
 
   def this() = this(None) // Java compatibility
 
-  import org.multiverse.api.ThreadLocalTransaction._
-
   val uuid = UUID.newUuid.toString
 
-  private[this] val ref = {
-    if (initialOpt.isDefined) RefFactory.createRef(initialOpt.get)
-    else RefFactory.createRef[T]
-  }
-
-  def swap(elem: T) = {
-    ensureIsInTransaction
-    ref.set(elem)
-  }
+  def swap(elem: T) = set(elem)
 
   def alter(f: T => T): T = {
-    ensureIsInTransaction
     ensureNotNull
-    ref.set(f(ref.get))
-    ref.get
+    set(f(this.get))
+    this.get
   }
 
-  def get: Option[T] = {
-    ensureIsInTransaction
-    if (ref.isNull) None
-    else Some(ref.get)
-  }
+  def getOption: Option[T] = Option(this.get)
 
-  def getOrWait: T = {
-    ensureIsInTransaction
-    ref.getOrAwait
-  }
+  def getOrWait: T = getOrAwait
 
-  def getOrElse(default: => T): T = {
-    ensureIsInTransaction
-    if (ref.isNull) default
-    else ref.get
-  }
+  def getOrElse(default: => T): T =
+    if (isNull) default else this.get
 
-  def isDefined: Boolean = {
-    ensureIsInTransaction
-    !ref.isNull
-  }
+  def isDefined: Boolean = !isNull
 
-  def isEmpty: Boolean = {
-    ensureIsInTransaction
-    ref.isNull
-  }
+  def isEmpty: Boolean = isNull
 
-  def map[B](f: T => B): Ref[B] = {
-    ensureIsInTransaction
-    if (isEmpty) Ref[B] else Ref(f(ref.get))
-  }
+  def map[B](f: T => B): Ref[B] =
+    if (isEmpty) Ref[B] else Ref(f(this.get))
 
-  def flatMap[B](f: T => Ref[B]): Ref[B] = {
-    ensureIsInTransaction
-    if (isEmpty) Ref[B] else f(ref.get)
-  }
+  def flatMap[B](f: T => Ref[B]): Ref[B] =
+    if (isEmpty) Ref[B] else f(this.get)
 
-  def filter(p: T => Boolean): Ref[T] = {
-    ensureIsInTransaction
-    if (isDefined && p(ref.get)) Ref(ref.get) else Ref[T]
-  }
+  def filter(p: T => Boolean): Ref[T] =
+    if (isDefined && p(this.get)) Ref(this.get) else Ref[T]
 
   /**
    * Necessary to keep from being implicitly converted to Iterable in for comprehensions.
@@ -117,34 +79,21 @@ class Ref[T](initialOpt: Option[T] = None) extends Transactional {
     def withFilter(q: T => Boolean): WithFilter = new WithFilter(x => p(x) && q(x))
   }
 
-  def foreach[U](f: T => U): Unit = {
-    ensureIsInTransaction
-    if (isDefined) f(ref.get)
-  }
+  def foreach[U](f: T => U): Unit =
+    if (isDefined) f(this.get)
 
-  def elements: Iterator[T] = {
-    ensureIsInTransaction
-    if (isEmpty) Iterator.empty else Iterator(ref.get)
-  }
+  def elements: Iterator[T] =
+    if (isEmpty) Iterator.empty else Iterator(this.get)
 
-  def toList: List[T] = {
-    ensureIsInTransaction
-    if (isEmpty) List() else List(ref.get)
-  }
+  def toList: List[T] =
+    if (isEmpty) List() else List(this.get)
 
-  def toRight[X](left: => X) = {
-    ensureIsInTransaction
-    if (isEmpty) Left(left) else Right(ref.get)
-  }
+  def toRight[X](left: => X) =
+    if (isEmpty) Left(left) else Right(this.get)
 
-  def toLeft[X](right: => X) = {
-    ensureIsInTransaction
-    if (isEmpty) Right(right) else Left(ref.get)
-  }
-
-  private def ensureIsInTransaction =
-   if (getThreadLocalTransaction eq null) throw new NoTransactionInScopeException
+  def toLeft[X](right: => X) =
+    if (isEmpty) Right(right) else Left(this.get)
 
   private def ensureNotNull =
-    if (ref.isNull) throw new RuntimeException("Cannot alter Ref's value when it is null")
+    if (isNull) throw new RuntimeException("Cannot alter Ref's value when it is null")
 }
diff --git a/akka-core/src/main/scala/stm/TransactionalMap.scala b/akka-core/src/main/scala/stm/TransactionalMap.scala
index be7b9c5189..54d3c59db6 100644
--- a/akka-core/src/main/scala/stm/TransactionalMap.scala
+++ b/akka-core/src/main/scala/stm/TransactionalMap.scala
@@ -41,36 +41,36 @@ class TransactionalMap[K, V](initialOpt: Option[HashMap[K, V]] = None) extends T
   }
 
   override def remove(key: K) = {
-    val map = ref.get.get
+    val map = ref.get
     val oldValue = map.get(key)
-    ref.swap(ref.get.get - key)
+    ref.swap(ref.get - key)
     oldValue
   }
 
-  def get(key: K): Option[V] = ref.get.get.get(key)
+  def get(key: K): Option[V] = ref.get.get(key)
 
   override def put(key: K, value: V): Option[V] = {
-    val map = ref.get.get
+    val map = ref.get
     val oldValue = map.get(key)
     ref.swap(map.updated(key, value))
     oldValue
   }
 
   override def update(key: K, value: V) = {
-    val map = ref.get.get
+    val map = ref.get
     val oldValue = map.get(key)
     ref.swap(map.updated(key, value))
   }
 
-  def iterator = ref.get.get.iterator
+  def iterator = ref.get.iterator
 
-  override def elements: Iterator[(K, V)] = ref.get.get.iterator
+  override def elements: Iterator[(K, V)] = ref.get.iterator
 
-  override def contains(key: K): Boolean = ref.get.get.contains(key)
+  override def contains(key: K): Boolean = ref.get.contains(key)
 
   override def clear = ref.swap(HashMap[K, V]())
 
-  override def size: Int = ref.get.get.size
+  override def size: Int = ref.get.size
 
   override def hashCode: Int = System.identityHashCode(this);
 
diff --git a/akka-core/src/main/scala/stm/TransactionalVector.scala b/akka-core/src/main/scala/stm/TransactionalVector.scala
index e2ad6a2aeb..585782d326 100644
--- a/akka-core/src/main/scala/stm/TransactionalVector.scala
+++ b/akka-core/src/main/scala/stm/TransactionalVector.scala
@@ -32,20 +32,20 @@ class TransactionalVector[T](initialOpt: Option[Vector[T]] = None) extends Trans
 
   def +(elem: T) = add(elem)
 
-  def add(elem: T) = ref.swap(ref.get.get :+ elem)
+  def add(elem: T) = ref.swap(ref.get :+ elem)
 
-  def get(index: Int): T = ref.get.get.apply(index)
+  def get(index: Int): T = ref.get.apply(index)
 
   /**
    * Removes the tail element of this vector.
    */
-  def pop = ref.swap(ref.get.get.dropRight(1))
+  def pop = ref.swap(ref.get.dropRight(1))
 
-  def update(index: Int, elem: T) = ref.swap(ref.get.get.updated(index, elem))
+  def update(index: Int, elem: T) = ref.swap(ref.get.updated(index, elem))
 
-  def length: Int = ref.get.get.length
+  def length: Int = ref.get.length
 
-  def apply(index: Int): T = ref.get.get.apply(index)
+  def apply(index: Int): T = ref.get.apply(index)
 
   override def hashCode: Int = System.identityHashCode(this);
 
diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/NestedTransactionalTypedActorImpl.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/NestedTransactionalTypedActorImpl.java
index 699f33785d..5b7eab615e 100644
--- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/NestedTransactionalTypedActorImpl.java
+++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/NestedTransactionalTypedActorImpl.java
@@ -28,7 +28,7 @@ public class NestedTransactionalTypedActorImpl extends TypedTransactor implement
   }
 
   public String getRefState() {
-    return (String) refState.get().get();
+    return (String) refState.get();
   }
 
   public void setMapState(String key, String msg) {
diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/TransactionalTypedActorImpl.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/TransactionalTypedActorImpl.java
index ddaf2fb47d..f992028caf 100644
--- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/TransactionalTypedActorImpl.java
+++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/TransactionalTypedActorImpl.java
@@ -28,7 +28,7 @@ public class TransactionalTypedActorImpl extends TypedTransactor implements Tran
   }
 
   public String getRefState() {
-    return (String)refState.get().get();
+    return (String)refState.get();
   }
 
   public void setMapState(String key, String msg) {
diff --git a/akka-core/src/test/scala/actor/actor/TransactorSpec.scala b/akka-core/src/test/scala/actor/actor/TransactorSpec.scala
index 1f48d0e740..dd23a76a88 100644
--- a/akka-core/src/test/scala/actor/actor/TransactorSpec.scala
+++ b/akka-core/src/test/scala/actor/actor/TransactorSpec.scala
@@ -35,9 +35,9 @@ class StatefulTransactor(expectedInvocationCount: Int) extends Transactor {
 
   val notifier = new CountDownLatch(expectedInvocationCount)
 
-  private lazy val mapState = TransactionalMap[String, String]()
-  private lazy val vectorState = TransactionalVector[String]()
-  private lazy val refState = Ref[String]()
+  private val mapState = TransactionalMap[String, String]()
+  private val vectorState = TransactionalVector[String]()
+  private val refState = Ref[String]()
 
   def receive = {
     case GetNotifier =>
@@ -49,7 +49,7 @@ class StatefulTransactor(expectedInvocationCount: Int) extends Transactor {
       self.reply(vectorState.length.asInstanceOf[AnyRef])
       notifier.countDown
     case GetRefState =>
-      self.reply(refState.get.get)
+      self.reply(refState.get)
       notifier.countDown
     case SetMapState(key, msg) =>
       mapState.put(key, msg)
diff --git a/akka-core/src/test/scala/stm/RefSpec.scala b/akka-core/src/test/scala/stm/RefSpec.scala
index 6e972152e5..f04c1a7c44 100644
--- a/akka-core/src/test/scala/stm/RefSpec.scala
+++ b/akka-core/src/test/scala/stm/RefSpec.scala
@@ -1,31 +1,27 @@
 package se.scalablesolutions.akka.stm
 
-import org.scalatest.Spec
-import org.scalatest.matchers.ShouldMatchers
-import org.scalatest.junit.JUnitRunner
-import org.junit.runner.RunWith
+import org.scalatest.WordSpec
+import org.scalatest.matchers.MustMatchers
 
-import se.scalablesolutions.akka.stm.local._
+class RefSpec extends WordSpec with MustMatchers {
 
-@RunWith(classOf[JUnitRunner])
-class RefSpec extends Spec with ShouldMatchers {
+  import se.scalablesolutions.akka.stm.local._
 
-  describe("A Ref") {
+  "A Ref" should {
 
-
-    it("should optionally accept an initial value") {
+    "optionally accept an initial value" in {
       val emptyRef = Ref[Int]
-      val empty = atomic { emptyRef.get }
+      val empty = atomic { emptyRef.getOption }
 
-      empty should be(None)
+      empty must be(None)
 
       val ref = Ref(3)
-      val value = atomic { ref.get.get }
+      val value = atomic { ref.get }
 
-      value should be(3)
+      value must be (3)
     }
 
-    it("should keep the initial value, even if the first transaction is rolled back") {
+    "keep the initial value, even if the first transaction is rolled back" in {
       val ref = Ref(3)
 
       try {
@@ -37,22 +33,32 @@ class RefSpec extends Spec with ShouldMatchers {
         case e => {}
       }
 
-      val value = atomic { ref.get.get }
+      val value = atomic { ref.get }
 
-      value should be(3)
+      value must be (3)
     }
 
-    it("should be settable using swap") {
+    "be settable using set" in {
+      val ref = Ref[Int]
+
+      atomic { ref.set(3) }
+
+      val value = atomic { ref.get }
+
+      value must be (3)
+    }
+
+    "be settable using swap" in {
       val ref = Ref[Int]
 
       atomic { ref.swap(3) }
 
-      val value = atomic { ref.get.get }
+      val value = atomic { ref.get }
 
-      value should be(3)
+      value must be (3)
     }
 
-    it("should be changeable using alter") {
+    "be changeable using alter" in {
       val ref = Ref(0)
 
       def increment = atomic {
@@ -63,36 +69,36 @@ class RefSpec extends Spec with ShouldMatchers {
       increment
       increment
 
-      val value = atomic { ref.get.get }
+      val value = atomic { ref.get }
 
-      value should be(3)
+      value must be (3)
     }
 
-    it("should not be changeable using alter if no value has been set") {
+    "not be changeable using alter if no value has been set" in {
       val ref = Ref[Int]
 
       def increment = atomic {
         ref alter (_ + 1)
       }
 
-      evaluating { increment } should produce [RuntimeException]
+      evaluating { increment } must produce [RuntimeException]
     }
 
-    it("should be able to be mapped") {
+    "be able to be mapped" in {
       val ref1 = Ref(1)
 
       val ref2 = atomic {
         ref1 map (_ + 1)
       }
 
-      val value1 = atomic { ref1.get.get }
-      val value2 = atomic { ref2.get.get }
+      val value1 = atomic { ref1.get }
+      val value2 = atomic { ref2.get }
 
-      value1 should be(1)
-      value2 should be(2)
+      value1 must be (1)
+      value2 must be (2)
     }
 
-    it("should be able to be used in a 'foreach' for comprehension") {
+    "be able to be used in a 'foreach' for comprehension" in {
       val ref = Ref(3)
 
       var result = 0
@@ -103,22 +109,22 @@ class RefSpec extends Spec with ShouldMatchers {
         }
       }
 
-      result should be(3)
+      result must be (3)
     }
 
-    it("should be able to be used in a 'map' for comprehension") {
+    "be able to be used in a 'map' for comprehension" in {
       val ref1 = Ref(1)
 
       val ref2 = atomic {
         for (value <- ref1) yield value + 2
       }
 
-      val value2 = atomic { ref2.get.get }
+      val value2 = atomic { ref2.get }
 
-      value2 should be(3)
+      value2 must be (3)
     }
 
-    it("should be able to be used in a 'flatMap' for comprehension") {
+    "be able to be used in a 'flatMap' for comprehension" in {
       val ref1 = Ref(1)
       val ref2 = Ref(2)
 
@@ -129,28 +135,28 @@ class RefSpec extends Spec with ShouldMatchers {
         } yield value1 + value2
       }
 
-      val value3 = atomic { ref3.get.get }
+      val value3 = atomic { ref3.get }
 
-      value3 should be(3)
+      value3 must be (3)
     }
 
-    it("should be able to be used in a 'filter' for comprehension") {
+    "be able to be used in a 'filter' for comprehension" in {
       val ref1 = Ref(1)
 
       val refLess2 = atomic {
         for (value <- ref1 if value < 2) yield value
       }
 
-      val optLess2 = atomic { refLess2.get }
+      val optLess2 = atomic { refLess2.getOption }
 
       val refGreater2 = atomic {
         for (value <- ref1 if value > 2) yield value
       }
 
-      val optGreater2 = atomic { refGreater2.get }
+      val optGreater2 = atomic { refGreater2.getOption }
 
-      optLess2 should be(Some(1))
-      optGreater2 should be(None)
+      optLess2 must be (Some(1))
+      optGreater2 must be (None)
     }
   }
 }
diff --git a/akka-core/src/test/scala/stm/StmSpec.scala b/akka-core/src/test/scala/stm/StmSpec.scala
index 0bb2851274..133725bb98 100644
--- a/akka-core/src/test/scala/stm/StmSpec.scala
+++ b/akka-core/src/test/scala/stm/StmSpec.scala
@@ -3,71 +3,66 @@ package se.scalablesolutions.akka.stm
 import se.scalablesolutions.akka.actor.{Actor, Transactor}
 import Actor._
 
-import org.scalatest.Spec
-import org.scalatest.matchers.ShouldMatchers
-import org.scalatest.BeforeAndAfterAll
-import org.scalatest.junit.JUnitRunner
-import org.junit.runner.RunWith
+import org.scalatest.WordSpec
+import org.scalatest.matchers.MustMatchers
 
-@RunWith(classOf[JUnitRunner])
-class StmSpec extends
-  Spec with
-  ShouldMatchers with
-  BeforeAndAfterAll {
+class StmSpec extends WordSpec with MustMatchers {
 
-  describe("Local STM") {
-    it("should be able to do multiple consecutive atomic {..} statements") {
-      import se.scalablesolutions.akka.stm.local._
+  "Local STM" should {
 
-      lazy val ref = Ref[Int]()
+    import se.scalablesolutions.akka.stm.local._
+
+    "be able to do multiple consecutive atomic {..} statements" in {
+      val ref = Ref(0)
 
       def increment = atomic {
-        ref.swap(ref.get.getOrElse(0) + 1)
+        ref alter (_ + 1)
       }
 
       def total: Int = atomic {
-        ref.get.getOrElse(0)
+        ref.getOrElse(0)
       }
 
       increment
       increment
       increment
-      total should equal(3)
+
+      total must be (3)
     }
 
-    it("should be able to do nested atomic {..} statements") {
-      import se.scalablesolutions.akka.stm.local._
-
-      lazy val ref = Ref[Int]()
+    "be able to do nested atomic {..} statements" in {
+      val ref = Ref(0)
 
       def increment = atomic {
-        ref.swap(ref.get.getOrElse(0) + 1)
+        ref alter (_ + 1)
       }
+
       def total: Int = atomic {
-        ref.get.getOrElse(0)
+        ref.getOrElse(0)
       }
 
       atomic {
         increment
         increment
       }
+
       atomic {
         increment
-        total should equal(3)
+        total must be (3)
       }
     }
 
-    it("should roll back failing nested atomic {..} statements") {
-      import se.scalablesolutions.akka.stm.local._
-
-      lazy val ref = Ref[Int]()
+    "roll back failing nested atomic {..} statements" in {
+      val ref = Ref(0)
 
       def increment = atomic {
-        ref.swap(ref.get.getOrElse(0) + 1)
+        ref alter (_ + 1)
       }
+
       def total: Int = atomic {
-        ref.get.getOrElse(0)
+        ref.getOrElse(0)
       }
+
       try {
         atomic(DefaultLocalTransactionFactory) {
           increment
@@ -77,21 +72,22 @@ class StmSpec extends
       } catch {
         case e => {}
       }
-      total should equal(0)
+
+      total must be (0)
     }
   }
 
-  describe("Global STM") {
-    it("should be able to initialize with atomic {..} block inside actor constructor") {
+  "Global STM" should {
+    "be able to initialize with atomic {..} block inside actor constructor" in {
       import GlobalTransactionVectorTestActor._
       try {
         val actor = actorOf[GlobalTransactionVectorTestActor].start
         actor !! Add(5)
         val size1 = (actor !! Size).as[Int].getOrElse(fail("Could not get Vector::size"))
-        size1 should equal(2)
+        size1 must be (2)
         actor !! Add(2)
         val size2 = (actor !! Size).as[Int].getOrElse(fail("Could not get Vector::size"))
-        size2 should equal(3)
+        size2 must be (3)
       } catch {
         case e =>
           e.printStackTrace
@@ -99,25 +95,26 @@ class StmSpec extends
       }
     }
   }
+
 /*
-  describe("Transactor") {
-    it("should be able receive message sent with !! and pass it along to nested transactor with !! and receive reply; multiple times in a row") {
+  "Transactor" should {
+    "be able receive message sent with !! and pass it along to nested transactor with !! and receive reply; multiple times in a row" in {
       import GlobalTransactionVectorTestActor._
       val actor = actorOf[NestedTransactorLevelOneActor].start
       actor !! (Add(2), 10000)
       val size1 = (actor !! (Size, 10000)).as[Int].getOrElse(fail("Could not get size"))
-      size1 should equal(2)
+      size1 must be (2)
       actor !! (Add(7), 10000)
       actor ! "HiLevelOne"
       val size2 = (actor !! (Size, 10000)).as[Int].getOrElse(fail("Could not get size"))
-      size2 should equal(7)
+      size2 must be (7)
       actor !! (Add(0), 10000)
       actor ! "HiLevelTwo"
       val size3 = (actor !! (Size, 10000)).as[Int].getOrElse(fail("Could not get size"))
-      size3 should equal(0)
+      size3 must be (0)
       actor !! (Add(3), 10000)
       val size4 = (actor !! (Size, 10000)).as[Int].getOrElse(fail("Could not get size"))
-      size4 should equal(3)
+      size4 must be (3)
     }
   }
   */
@@ -128,6 +125,7 @@ object GlobalTransactionVectorTestActor {
   case object Size
   case object Success
 }
+
 class GlobalTransactionVectorTestActor extends Actor {
   import GlobalTransactionVectorTestActor._
   import se.scalablesolutions.akka.stm.global._
@@ -147,6 +145,7 @@ class GlobalTransactionVectorTestActor extends Actor {
 
 class NestedTransactorLevelOneActor extends Actor {
   import GlobalTransactionVectorTestActor._
+
   private val nested = actorOf[NestedTransactorLevelTwoActor].start
   self.timeout = 10000
 
@@ -164,6 +163,7 @@ class NestedTransactorLevelOneActor extends Actor {
 
 class NestedTransactorLevelTwoActor extends Transactor {
   import GlobalTransactionVectorTestActor._
+
   private val ref = Ref(0)
   self.timeout = 10000
 
diff --git a/akka-persistence/akka-persistence-common/src/main/scala/Storage.scala b/akka-persistence/akka-persistence-common/src/main/scala/Storage.scala
index 135ee584b9..a734d4d815 100644
--- a/akka-persistence/akka-persistence-common/src/main/scala/Storage.scala
+++ b/akka-persistence/akka-persistence-common/src/main/scala/Storage.scala
@@ -90,7 +90,7 @@ trait PersistentMap[K, V] extends scala.collection.mutable.Map[K, V]
   val storage: MapStorageBackend[K, V]
 
   def commit = {
-    if (shouldClearOnCommit.isDefined && shouldClearOnCommit.get.get) storage.removeMapStorageFor(uuid)
+    if (shouldClearOnCommit.isDefined && shouldClearOnCommit.get) storage.removeMapStorageFor(uuid)
     removedEntries.toList.foreach(key => storage.removeMapStorageFor(uuid, key))
     storage.insertMapStorageEntriesFor(uuid, newAndUpdatedEntries.toList)
     newAndUpdatedEntries.clear
@@ -281,7 +281,7 @@ trait PersistentRef[T] extends Transactional with Committable with Abortable {
   val storage: RefStorageBackend[T]
 
   def commit = if (ref.isDefined) {
-    storage.insertRefStorageFor(uuid, ref.get.get)
+    storage.insertRefStorageFor(uuid, ref.get)
     ref.swap(null.asInstanceOf[T])
   }
 
@@ -292,7 +292,7 @@ trait PersistentRef[T] extends Transactional with Committable with Abortable {
     ref.swap(elem)
   }
 
-  def get: Option[T] = if (ref.isDefined) ref.get else storage.getRefStorageFor(uuid)
+  def get: Option[T] = if (ref.isDefined) ref.getOption else storage.getRefStorageFor(uuid)
 
   def isDefined: Boolean = ref.isDefined || storage.getRefStorageFor(uuid).isDefined
 
@@ -365,7 +365,7 @@ trait PersistentQueue[A] extends scala.collection.mutable.Queue[A]
         case DEQ => storage.dequeue(uuid)
       }
     }
-    if (shouldClearOnCommit.isDefined && shouldClearOnCommit.get.get) {
+    if (shouldClearOnCommit.isDefined && shouldClearOnCommit.get) {
       storage.remove(uuid)
     }
     enqueuedNDequeuedEntries.clear
@@ -386,7 +386,7 @@ trait PersistentQueue[A] extends scala.collection.mutable.Queue[A]
     register
     elems.foreach(e => {
       enqueuedNDequeuedEntries.add((Some(e), ENQ))
-      localQ.get.get.enqueue(e)
+      localQ.get.enqueue(e)
     })
   }
 
@@ -395,15 +395,15 @@ trait PersistentQueue[A] extends scala.collection.mutable.Queue[A]
     // record for later playback
     enqueuedNDequeuedEntries.add((None, DEQ))
 
-    val i = pickMeForDQ.get.get
+    val i = pickMeForDQ.get
     if (i < storage.size(uuid)) {
       // still we can DQ from storage
       pickMeForDQ.swap(i + 1)
       storage.peek(uuid, i, 1)(0)
     } else {
       // check we have transient candidates in localQ for DQ
-      if (localQ.get.get.isEmpty == false) {
-        val (a, q) = localQ.get.get.dequeue
+      if (localQ.get.isEmpty == false) {
+        val (a, q) = localQ.get.dequeue
         localQ.swap(q)
         a
       } else throw new NoSuchElementException("trying to dequeue from empty queue")
@@ -418,7 +418,7 @@ trait PersistentQueue[A] extends scala.collection.mutable.Queue[A]
   }
 
   override def size: Int = try {
-    storage.size(uuid) + localQ.get.get.length
+    storage.size(uuid) + localQ.get.length
   } catch { case e: Exception => 0 }
 
   override def isEmpty: Boolean =
diff --git a/akka-samples/akka-sample-ants/src/main/scala/Ants.scala b/akka-samples/akka-sample-ants/src/main/scala/Ants.scala
index fc53db6f22..b1e5cee0b8 100644
--- a/akka-samples/akka-sample-ants/src/main/scala/Ants.scala
+++ b/akka-samples/akka-sample-ants/src/main/scala/Ants.scala
@@ -70,7 +70,7 @@ object World {
 
   private val snapshotFactory = TransactionFactory(readonly = true, familyName = "snapshot", hooks = false)
 
-  def snapshot = atomic(snapshotFactory) { Array.tabulate(Dim, Dim)(place(_, _).get) }
+  def snapshot = atomic(snapshotFactory) { Array.tabulate(Dim, Dim)(place(_, _).getOption) }
 
   def place(loc: (Int, Int)) = places(loc._1)(loc._2)
 

From c89295379cc799b5f70c2addebdc1d9feb4c8d7e Mon Sep 17 00:00:00 2001
From: Martin Krasser 
Date: Mon, 2 Aug 2010 20:11:41 +0200
Subject: [PATCH 084/188] closes #366: CamelService should be a singleton

---
 akka-camel/src/main/scala/CamelService.scala  | 36 ++++++++++++-------
 .../test/scala/CamelServiceFeatureTest.scala  |  2 +-
 .../src/test/scala/RemoteConsumerTest.scala   |  2 +-
 .../src/main/scala/ServerApplication.scala    |  2 +-
 .../main/scala/StandaloneApplication.scala    | 14 ++++----
 .../src/test/scala/HttpConcurrencyTest.scala  |  8 ++---
 .../main/scala/CamelServiceFactoryBean.scala  |  5 +--
 7 files changed, 40 insertions(+), 29 deletions(-)

diff --git a/akka-camel/src/main/scala/CamelService.scala b/akka-camel/src/main/scala/CamelService.scala
index 8f3e504dfd..163daecf0d 100644
--- a/akka-camel/src/main/scala/CamelService.scala
+++ b/akka-camel/src/main/scala/CamelService.scala
@@ -5,6 +5,8 @@ package se.scalablesolutions.akka.camel
 
 import java.util.concurrent.CountDownLatch
 
+import org.apache.camel.CamelContext
+
 import se.scalablesolutions.akka.actor.Actor._
 import se.scalablesolutions.akka.actor.{AspectInitRegistry, ActorRegistry}
 import se.scalablesolutions.akka.util.{Bootable, Logging}
@@ -97,24 +99,34 @@ trait CamelService extends Bootable with Logging {
 }
 
 /**
- * CamelService companion object used by standalone applications to create their own
- * CamelService instance.
+ * Single CamelService instance.
  *
  * @author Martin Krasser
  */
-object CamelService {
+object CamelService extends CamelService {
 
   /**
-   * Creates a new CamelService instance.
+   * Starts the CamelService singleton.
    */
-  def newInstance: CamelService = new DefaultCamelService
+  def start = load
+
+  /**
+   * Stops the CamelService singleton.
+   */
+  def stop = unload
 }
 
-/**
- * Default CamelService implementation to be created in Java applications with
- * 
- * CamelService service = new DefaultCamelService()
- * 
- */ -class DefaultCamelService extends CamelService { +object CamelServiceFactory { + /** + * Creates a new CamelService instance + */ + def createCamelService: CamelService = new CamelService { } + + /** + * Creates a new CamelService instance + */ + def createCamelService(camelContext: CamelContext): CamelService = { + CamelContextManager.init(camelContext) + createCamelService + } } diff --git a/akka-camel/src/test/scala/CamelServiceFeatureTest.scala b/akka-camel/src/test/scala/CamelServiceFeatureTest.scala index 753730659e..71ab86599d 100644 --- a/akka-camel/src/test/scala/CamelServiceFeatureTest.scala +++ b/akka-camel/src/test/scala/CamelServiceFeatureTest.scala @@ -17,7 +17,7 @@ class CamelServiceFeatureTest extends FeatureSpec with BeforeAndAfterAll with Gi override protected def beforeAll = { ActorRegistry.shutdownAll // create new CamelService instance - service = CamelService.newInstance + service = CamelServiceFactory.createCamelService // register test consumer before starting the CamelService actorOf(new TestConsumer("direct:publish-test-1")).start // Configure a custom camel route diff --git a/akka-camel/src/test/scala/RemoteConsumerTest.scala b/akka-camel/src/test/scala/RemoteConsumerTest.scala index 4ac0033854..fd5dc52a8b 100644 --- a/akka-camel/src/test/scala/RemoteConsumerTest.scala +++ b/akka-camel/src/test/scala/RemoteConsumerTest.scala @@ -20,7 +20,7 @@ class RemoteConsumerTest extends FeatureSpec with BeforeAndAfterAll with GivenWh override protected def beforeAll = { ActorRegistry.shutdownAll - service = CamelService.newInstance + service = CamelServiceFactory.createCamelService service.load server = new RemoteServer() diff --git a/akka-samples/akka-sample-camel/src/main/scala/ServerApplication.scala b/akka-samples/akka-sample-camel/src/main/scala/ServerApplication.scala index 7d90e89720..8aa9293815 100644 --- a/akka-samples/akka-sample-camel/src/main/scala/ServerApplication.scala +++ b/akka-samples/akka-sample-camel/src/main/scala/ServerApplication.scala @@ -14,7 +14,7 @@ object ServerApplication { // def main(args: Array[String]) { - val camelService = CamelService.newInstance.load + val camelService = CamelService.start RemoteNode.start("localhost", 7777) RemoteNode.register("remote2", actorOf[RemoteActor2].start) } diff --git a/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala b/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala index 528700ade9..6fa207a6e0 100644 --- a/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala +++ b/akka-samples/akka-sample-camel/src/main/scala/StandaloneApplication.scala @@ -25,13 +25,13 @@ object StandaloneApplication { CamelContextManager.context.addRoutes(new StandaloneApplicationRoute) // start CamelService - val camelService = CamelService.newInstance.load + CamelService.start // access 'externally' registered typed actors assert("hello msg1" == context.createProducerTemplate.requestBody("direct:test", "msg1")) // set expectations on upcoming endpoint activation - val activation = camelService.expectEndpointActivationCount(1) + val activation = CamelService.expectEndpointActivationCount(1) // 'internally' register typed actor (requires CamelService) TypedActor.newInstance(classOf[TypedConsumer2], classOf[TypedConsumer2Impl]) @@ -44,7 +44,7 @@ object StandaloneApplication { assert("default: msg3" == context.createProducerTemplate.requestBody("direct:default", "msg3")) // shutdown CamelService - camelService.unload + CamelService.stop // shutdown all (internally) created actors ActorRegistry.shutdownAll @@ -91,10 +91,10 @@ object StandaloneJmsApplication { // Init CamelContextManager with custom CamelContext CamelContextManager.init(new DefaultCamelContext(registry)) - // Create new instance of CamelService and start it - val service = CamelService.newInstance.load + // Start CamelService + CamelService.start // Expect two consumer endpoints to be activated - val completion = service.expectEndpointActivationCount(2) + val completion = CamelService.expectEndpointActivationCount(2) val jmsUri = "jms:topic:test" // Wire publisher and consumer using a JMS topic @@ -116,7 +116,7 @@ object StandaloneJmsApplication { } // Graceful shutdown of all endpoints/routes - service.unload + CamelService.stop // Shutdown example actors ActorRegistry.shutdownAll diff --git a/akka-samples/akka-sample-camel/src/test/scala/HttpConcurrencyTest.scala b/akka-samples/akka-sample-camel/src/test/scala/HttpConcurrencyTest.scala index b98876a01d..54fa631744 100644 --- a/akka-samples/akka-sample-camel/src/test/scala/HttpConcurrencyTest.scala +++ b/akka-samples/akka-sample-camel/src/test/scala/HttpConcurrencyTest.scala @@ -43,23 +43,21 @@ class HttpConcurrencyTest extends JUnitSuite { } object HttpConcurrencyTest { - var service: CamelService = _ - @BeforeClass def beforeClass = { - service = CamelService.newInstance.load + CamelService.start val workers = for (i <- 1 to 8) yield actorOf[HttpServerWorker].start val balancer = loadBalancerActor(new CyclicIterator(workers.toList)) - val completion = service.expectEndpointActivationCount(1) + val completion = CamelService.expectEndpointActivationCount(1) val server = actorOf(new HttpServerActor(balancer)).start completion.await } @AfterClass def afterClass = { - service.unload + CamelService.stop ActorRegistry.shutdownAll } diff --git a/akka-spring/src/main/scala/CamelServiceFactoryBean.scala b/akka-spring/src/main/scala/CamelServiceFactoryBean.scala index 50a3bd748c..2baa36ac03 100644 --- a/akka-spring/src/main/scala/CamelServiceFactoryBean.scala +++ b/akka-spring/src/main/scala/CamelServiceFactoryBean.scala @@ -5,7 +5,8 @@ package se.scalablesolutions.akka.spring import org.apache.camel.CamelContext import org.springframework.beans.factory.{DisposableBean, InitializingBean, FactoryBean} -import se.scalablesolutions.akka.camel.{CamelContextManager, CamelService} + +import se.scalablesolutions.akka.camel.{CamelContextManager, CamelService, CamelServiceFactory} /** * Factory bean for a {@link CamelService}. @@ -31,7 +32,7 @@ class CamelServiceFactoryBean extends FactoryBean[CamelService] with Initializin if (camelContext ne null) { CamelContextManager.init(camelContext) } - instance = CamelService.newInstance + instance = CamelServiceFactory.createCamelService instance.load } From f9750d8dc6bcee22ea0a31c6e9f2f674f03ddb82 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Tue, 3 Aug 2010 11:25:09 +0200 Subject: [PATCH 085/188] Closing ticket 352 --- .../src/main/scala/actor/ActorRegistry.scala | 41 +++++++++---------- .../test/scala/misc/ActorRegistrySpec.scala | 11 +++++ .../src/main/scala/akka/SimpleService.scala | 4 +- .../src/main/scala/SimpleService.scala | 8 ++-- .../src/main/scala/SimpleService.scala | 4 +- 5 files changed, 39 insertions(+), 29 deletions(-) diff --git a/akka-core/src/main/scala/actor/ActorRegistry.scala b/akka-core/src/main/scala/actor/ActorRegistry.scala index aea37432b7..953540fc70 100644 --- a/akka-core/src/main/scala/actor/ActorRegistry.scala +++ b/akka-core/src/main/scala/actor/ActorRegistry.scala @@ -31,7 +31,6 @@ case class ActorUnregistered(actor: ActorRef) extends ActorRegistryEvent object ActorRegistry extends ListenerManagement { private val actorsByUUID = new ConcurrentHashMap[String, ActorRef] private val actorsById = new ConcurrentHashMap[String, JSet[ActorRef]] - private val actorsByClassName = new ConcurrentHashMap[String, JSet[ActorRef]] /** * Returns all actors in the system. @@ -46,6 +45,21 @@ object ActorRegistry extends ListenerManagement { while (elements.hasMoreElements) f(elements.nextElement) } + /** + * Invokes the function on all known actors until it returns Some + * Returns None if the function never returns Some + */ + def find[T](f: (ActorRef) => Option[T]) : Option[T] = { + val elements = actorsByUUID.elements + while (elements.hasMoreElements) { + val result = f(elements.nextElement) + + if(result.isDefined) + return result + } + None + } + /** * Finds all actors that are subtypes of the class passed in as the Manifest argument and supproting passed message. */ @@ -71,22 +85,20 @@ object ActorRegistry extends ListenerManagement { * Finds all actors that are subtypes of the class passed in as the Manifest argument. */ def actorsFor[T <: Actor](implicit manifest: Manifest[T]): List[ActorRef] = - filter(a => manifest.erasure.isAssignableFrom(a.actor.getClass)) + actorsFor[T](manifest.erasure.asInstanceOf[Class[T]]) /** * Finds any actor that matches T. + * FIXME: Improve performance by breaking out after the first match */ def actorFor[T <: Actor](implicit manifest: Manifest[T]): Option[ActorRef] = actorsFor[T](manifest).headOption /** - * Finds all actors of the exact type specified by the class passed in as the Class argument. + * Finds all actors of type or sub-type specified by the class passed in as the Class argument. */ - def actorsFor[T <: Actor](clazz: Class[T]): List[ActorRef] = { - if (actorsByClassName.containsKey(clazz.getName)) { - actorsByClassName.get(clazz.getName).toArray.toList.asInstanceOf[List[ActorRef]] - } else Nil - } + def actorsFor[T <: Actor](clazz: Class[T]): List[ActorRef] = + filter(a => clazz.isAssignableFrom(a.actor.getClass)) /** * Finds all actors that has a specific id. @@ -122,15 +134,6 @@ object ActorRegistry extends ListenerManagement { actorsById.put(id, set) } - // Class name - val className = actor.actorClassName - if (actorsByClassName.containsKey(className)) actorsByClassName.get(className).add(actor) - else { - val set = new ConcurrentSkipListSet[ActorRef] - set.add(actor) - actorsByClassName.put(className, set) - } - // notify listeners foreachListener(_ ! ActorRegistered(actor)) } @@ -144,9 +147,6 @@ object ActorRegistry extends ListenerManagement { val id = actor.id if (actorsById.containsKey(id)) actorsById.get(id).remove(actor) - val className = actor.actorClassName - if (actorsByClassName.containsKey(className)) actorsByClassName.get(className).remove(actor) - // notify listeners foreachListener(_ ! ActorUnregistered(actor)) } @@ -159,7 +159,6 @@ object ActorRegistry extends ListenerManagement { foreach(_.stop) actorsByUUID.clear actorsById.clear - actorsByClassName.clear log.info("All actors have been shut down and unregistered from ActorRegistry") } } diff --git a/akka-core/src/test/scala/misc/ActorRegistrySpec.scala b/akka-core/src/test/scala/misc/ActorRegistrySpec.scala index 6914472e2c..d6fc463a65 100644 --- a/akka-core/src/test/scala/misc/ActorRegistrySpec.scala +++ b/akka-core/src/test/scala/misc/ActorRegistrySpec.scala @@ -76,6 +76,17 @@ class ActorRegistrySpec extends JUnitSuite { actor.stop } + @Test def shouldFindThingsFromActorRegistry { + ActorRegistry.shutdownAll + val actor = actorOf[TestActor] + actor.start + val found = ActorRegistry.find(a => if(a.actor.isInstanceOf[TestActor]) Some(a) else None) + assert(found.isDefined) + assert(found.get.actor.isInstanceOf[TestActor]) + assert(found.get.id === "MyID") + actor.stop + } + @Test def shouldGetActorsByIdFromActorRegistry { ActorRegistry.shutdownAll val actor1 = actorOf[TestActor] diff --git a/akka-samples/akka-sample-lift/src/main/scala/akka/SimpleService.scala b/akka-samples/akka-sample-lift/src/main/scala/akka/SimpleService.scala index b361fbb16b..d5358a7d89 100644 --- a/akka-samples/akka-sample-lift/src/main/scala/akka/SimpleService.scala +++ b/akka-samples/akka-sample-lift/src/main/scala/akka/SimpleService.scala @@ -64,7 +64,7 @@ object SimpleRestService extends RestHelper { case Get("liftcount" :: _, req) => //Fetch the first actor of type SimpleServiceActor //Send it the "Tick" message and expect a Node back - val result = for( a <- ActorRegistry.actorsFor(classOf[SimpleServiceActor]).headOption; + val result = for( a <- ActorRegistry.actorFor[SimpleServiceActor]; r <- (a !! "Tick").as[Node] ) yield r //Return either the resulting NodeSeq or a default one @@ -85,7 +85,7 @@ object SimpleRestService extends RestHelper { case Get("persistentliftcount" :: _, req) => //Fetch the first actor of type SimpleServiceActor //Send it the "Tick" message and expect a Node back - val result = for( a <- ActorRegistry.actorsFor(classOf[PersistentServiceActor]).headOption; + val result = for( a <- ActorRegistry.actorFor[PersistentServiceActor]; r <- (a !! "Tick").as[Node] ) yield r //Return either the resulting NodeSeq or a default one diff --git a/akka-samples/akka-sample-rest-scala/src/main/scala/SimpleService.scala b/akka-samples/akka-sample-rest-scala/src/main/scala/SimpleService.scala index fc96bba182..c3b71a3fdf 100644 --- a/akka-samples/akka-sample-rest-scala/src/main/scala/SimpleService.scala +++ b/akka-samples/akka-sample-rest-scala/src/main/scala/SimpleService.scala @@ -16,7 +16,7 @@ import java.lang.Integer import java.nio.ByteBuffer import javax.ws.rs.core.MultivaluedMap import javax.ws.rs.{GET, POST, Path, Produces, WebApplicationException, Consumes,PathParam} -import se.scalablesolutions.akka.actor.ActorRegistry.actorsFor +import se.scalablesolutions.akka.actor.ActorRegistry.actorFor import org.atmosphere.annotation.{Broadcast, Suspend,Cluster} import org.atmosphere.util.XSSHtmlFilter import org.atmosphere.cpr.{Broadcaster, BroadcastFilter} @@ -53,7 +53,7 @@ class SimpleService { def count = { //Fetch the first actor of type SimpleServiceActor //Send it the "Tick" message and expect a NodeSeq back - val result = for{a <- actorsFor(classOf[SimpleServiceActor]).headOption + val result = for{a <- actorFor[SimpleServiceActor] r <- (a !! "Tick").as[NodeSeq]} yield r //Return either the resulting NodeSeq or a default one result getOrElse Error in counter @@ -108,7 +108,7 @@ class PersistentSimpleService { def count = { //Fetch the first actor of type PersistentSimpleServiceActor //Send it the "Tick" message and expect a NodeSeq back - val result = for{a <- actorsFor(classOf[PersistentSimpleServiceActor]).headOption + val result = for{a <- actorFor[PersistentSimpleServiceActor] r <- (a !! "Tick").as[NodeSeq]} yield r //Return either the resulting NodeSeq or a default one result getOrElse Error in counter @@ -155,7 +155,7 @@ class Chat { val msg = ChatMsg(form.getFirst("name"),form.getFirst("action"),form.getFirst("message")) //Fetch the first actor of type ChatActor //Send it the "Tick" message and expect a NodeSeq back - val result = for{a <- actorsFor(classOf[ChatActor]).headOption + val result = for{a <- actorFor[ChatActor] r <- (a !! msg).as[String]} yield r //Return either the resulting String or a default one result getOrElse "System__error" diff --git a/akka-samples/akka-sample-security/src/main/scala/SimpleService.scala b/akka-samples/akka-sample-security/src/main/scala/SimpleService.scala index e5c8029eb8..02af6174c6 100644 --- a/akka-samples/akka-sample-security/src/main/scala/SimpleService.scala +++ b/akka-samples/akka-sample-security/src/main/scala/SimpleService.scala @@ -10,7 +10,7 @@ import se.scalablesolutions.akka.config.ScalaConfig._ import se.scalablesolutions.akka.util.Logging import se.scalablesolutions.akka.security.{BasicAuthenticationActor,BasicCredentials,SpnegoAuthenticationActor,DigestAuthenticationActor, UserInfo} import se.scalablesolutions.akka.stm.TransactionalMap -import se.scalablesolutions.akka.actor.ActorRegistry.actorsFor +import se.scalablesolutions.akka.actor.ActorRegistry.actorFor class Boot { val factory = SupervisorFactory( @@ -122,7 +122,7 @@ class SecureTickService { def tick = { //Fetch the first actor of type PersistentSimpleServiceActor //Send it the "Tick" message and expect a NdeSeq back - val result = for{a <- actorsFor(classOf[SecureTickActor]).headOption + val result = for{a <- actorFor[SecureTickActor] r <- (a !! "Tick").as[Integer]} yield r //Return either the resulting NodeSeq or a default one result match { From 80a325ef3465d9b0bc415a973bb81158681b06ce Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Tue, 3 Aug 2010 14:42:42 +0200 Subject: [PATCH 086/188] Closing ticket 355 --- .../main/scala/component/ActorComponent.scala | 5 ++-- .../src/main/scala/actor/ActorRegistry.scala | 23 ++++++++++--------- .../akka/actor/SampleUntypedActor.java | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/akka-camel/src/main/scala/component/ActorComponent.scala b/akka-camel/src/main/scala/component/ActorComponent.scala index 1cd29ced00..7ef8e0750c 100644 --- a/akka-camel/src/main/scala/component/ActorComponent.scala +++ b/akka-camel/src/main/scala/component/ActorComponent.scala @@ -148,9 +148,8 @@ class ActorProducer(val ep: ActorEndpoint) extends DefaultProducer(ep) with Asyn else targetByUuid(ep.uuid.get) private def targetById(id: String) = ActorRegistry.actorsFor(id) match { - case Nil => None - case actor :: Nil => Some(actor) - case actors => Some(actors.head) + case actors if actors.length == 0 => None + case actors => Some(actors(0)) } private def targetByUuid(uuid: String) = ActorRegistry.actorFor(uuid) diff --git a/akka-core/src/main/scala/actor/ActorRegistry.scala b/akka-core/src/main/scala/actor/ActorRegistry.scala index 953540fc70..63ddb939c7 100644 --- a/akka-core/src/main/scala/actor/ActorRegistry.scala +++ b/akka-core/src/main/scala/actor/ActorRegistry.scala @@ -32,10 +32,12 @@ object ActorRegistry extends ListenerManagement { private val actorsByUUID = new ConcurrentHashMap[String, ActorRef] private val actorsById = new ConcurrentHashMap[String, JSet[ActorRef]] + private val Naught = Array[ActorRef]() //Nil for Arrays + /** * Returns all actors in the system. */ - def actors: List[ActorRef] = filter(_ => true) + def actors: Array[ActorRef] = filter(_ => true) /** * Invokes a function for all actors. @@ -63,13 +65,13 @@ object ActorRegistry extends ListenerManagement { /** * Finds all actors that are subtypes of the class passed in as the Manifest argument and supproting passed message. */ - def actorsFor[T <: Actor](message: Any)(implicit manifest: Manifest[T] ): List[ActorRef] = + def actorsFor[T <: Actor](message: Any)(implicit manifest: Manifest[T] ): Array[ActorRef] = filter(a => manifest.erasure.isAssignableFrom(a.actor.getClass) && a.isDefinedAt(message)) /** * Finds all actors that satisfy a predicate. */ - def filter(p: ActorRef => Boolean): List[ActorRef] = { + def filter(p: ActorRef => Boolean): Array[ActorRef] = { val all = new ListBuffer[ActorRef] val elements = actorsByUUID.elements while (elements.hasMoreElements) { @@ -78,35 +80,34 @@ object ActorRegistry extends ListenerManagement { all += actorId } } - all.toList + all.toArray } /** * Finds all actors that are subtypes of the class passed in as the Manifest argument. */ - def actorsFor[T <: Actor](implicit manifest: Manifest[T]): List[ActorRef] = + def actorsFor[T <: Actor](implicit manifest: Manifest[T]): Array[ActorRef] = actorsFor[T](manifest.erasure.asInstanceOf[Class[T]]) /** * Finds any actor that matches T. - * FIXME: Improve performance by breaking out after the first match */ def actorFor[T <: Actor](implicit manifest: Manifest[T]): Option[ActorRef] = - actorsFor[T](manifest).headOption + find(a => if(manifest.erasure.isAssignableFrom(a.actor.getClass)) Some(a) else None) /** * Finds all actors of type or sub-type specified by the class passed in as the Class argument. */ - def actorsFor[T <: Actor](clazz: Class[T]): List[ActorRef] = + def actorsFor[T <: Actor](clazz: Class[T]): Array[ActorRef] = filter(a => clazz.isAssignableFrom(a.actor.getClass)) /** * Finds all actors that has a specific id. */ - def actorsFor(id: String): List[ActorRef] = { + def actorsFor(id: String): Array[ActorRef] = { if (actorsById.containsKey(id)) { - actorsById.get(id).toArray.toList.asInstanceOf[List[ActorRef]] - } else Nil + actorsById.get(id).toArray(Naught) + } else Naught } /** diff --git a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SampleUntypedActor.java b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SampleUntypedActor.java index 8040e1394f..ed8a67ab13 100644 --- a/akka-core/src/test/java/se/scalablesolutions/akka/actor/SampleUntypedActor.java +++ b/akka-core/src/test/java/se/scalablesolutions/akka/actor/SampleUntypedActor.java @@ -36,7 +36,7 @@ public class SampleUntypedActor extends UntypedActor { } else if (msg.equals("ForwardMessage")) { // Retreive an actor from the ActorRegistry by ID and get an ActorRef back - ActorRef actorRef = ActorRegistry.actorsFor("some-actor-id").head(); + ActorRef actorRef = ActorRegistry.actorsFor("some-actor-id")[0]; // Wrap the ActorRef in an UntypedActorRef and forward the message to this actor UntypedActorRef.wrap(actorRef).forward(msg, self); From 774424afe31a3389382d39013aad396f807ee819 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Tue, 3 Aug 2010 16:13:19 +0200 Subject: [PATCH 087/188] Closing ticket 367 --- project/build/AkkaProject.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index e63bfc573f..02f72d7f0e 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -347,6 +347,8 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // testing val junit = Dependencies.junit val scalatest = Dependencies.scalatest + + override def bndImportPackage = "javax.transaction;version=1.1" :: super.bndImportPackage.toList } // ------------------------------------------------------------------------------------------------------------------- From 573c0bf1d5117bbdb12f393b7034a47930d42d4e Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Wed, 4 Aug 2010 10:45:29 +0200 Subject: [PATCH 088/188] Closing ticket 368 --- .../src/main/java/sample/rest/java/Boot.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/Boot.java b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/Boot.java index cd382ae6ec..d9b41cd136 100644 --- a/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/Boot.java +++ b/akka-samples/akka-sample-rest-java/src/main/java/sample/rest/java/Boot.java @@ -15,10 +15,12 @@ public class Boot { new Component[] { new Component( SimpleService.class, + SimpleServiceImpl.class, new LifeCycle(new Permanent()), 1000), new Component( PersistentSimpleService.class, + PersistentSimpleServiceImpl.class, new LifeCycle(new Permanent()), 1000) }).supervise(); From 5168bb5caeb0cee3b855b6f4d85eef0ba998bfcd Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Wed, 4 Aug 2010 13:31:41 +0200 Subject: [PATCH 089/188] Uncommenting SSL support --- akka-core/src/main/scala/remote/RemoteServer.scala | 5 ++--- config/akka-reference.conf | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/akka-core/src/main/scala/remote/RemoteServer.scala b/akka-core/src/main/scala/remote/RemoteServer.scala index 5d25d81b75..db4490761b 100644 --- a/akka-core/src/main/scala/remote/RemoteServer.scala +++ b/akka-core/src/main/scala/remote/RemoteServer.scala @@ -76,8 +76,7 @@ object RemoteServer { } val SECURE = { - //TODO: Remove this when SSL is in working condition - /*if(config.getBool("akka.remote.ssl.service",false)){ + if(config.getBool("akka.remote.ssl.service",false)){ val properties = List( ("key-store-type" ,"keyStoreType"), @@ -98,7 +97,7 @@ object RemoteServer { true } - else */ + else false } diff --git a/config/akka-reference.conf b/config/akka-reference.conf index 33806c1d3d..3b80953fe6 100644 --- a/config/akka-reference.conf +++ b/config/akka-reference.conf @@ -76,7 +76,7 @@ akka { zlib-compression-level = 6 # Options: 0-9 (1 being fastest and 9 being the most compressed), default is 6 ssl { - service = off #on / off (THIS FEATURE IS NOT ACTIVATED YET, STAY TUNED) + service = off #on / off #You can either use java command-line options or use the settings below From e58e9b9fa2d459e27208f6155187b2becd48d04b Mon Sep 17 00:00:00 2001 From: rossputin Date: Wed, 4 Aug 2010 14:57:36 +0100 Subject: [PATCH 090/188] update run-akka script to use 2.8.0 final --- scripts/run_akka.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/run_akka.sh b/scripts/run_akka.sh index 2d87a08148..f2ededd90f 100755 --- a/scripts/run_akka.sh +++ b/scripts/run_akka.sh @@ -1,6 +1,6 @@ #!/bin/bash cd $AKKA_HOME -VERSION=akka_2.8.0.RC3-0.10 +VERSION=akka_2.8.0-0.10 TARGET_DIR=dist/$VERSION/$1 shift 1 VMARGS=$@ From c2a156d514d78ef486b7e643978b8fa142ebd06f Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Thu, 5 Aug 2010 12:04:32 +0200 Subject: [PATCH 091/188] Race condition should be patched now --- .../src/main/scala/actor/ActorRegistry.scala | 34 +++++++++++++------ .../ExecutorBasedEventDrivenDispatcher.scala | 2 +- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/akka-core/src/main/scala/actor/ActorRegistry.scala b/akka-core/src/main/scala/actor/ActorRegistry.scala index 63ddb939c7..905d1e7f2e 100644 --- a/akka-core/src/main/scala/actor/ActorRegistry.scala +++ b/akka-core/src/main/scala/actor/ActorRegistry.scala @@ -122,19 +122,30 @@ object ActorRegistry extends ListenerManagement { * Registers an actor in the ActorRegistry. */ def register(actor: ActorRef) = { - // UUID - actorsByUUID.put(actor.uuid, actor) - // ID val id = actor.id if (id eq null) throw new IllegalActorStateException("Actor.id is null " + actor) - if (actorsById.containsKey(id)) actorsById.get(id).add(actor) - else { - val set = new ConcurrentSkipListSet[ActorRef] - set.add(actor) - actorsById.put(id, set) + + //Tries to avoid a race-condition + def registerById(attemptNo: Int = 0,maxAttempts: Int = 10) { + if(attemptNo >= maxAttempts) + throw new IllegalStateException("Tried to add %s to the ActorRegistry %d times but failed.".format(actor,maxAttempts)) + val set = actorsById.get(id) + if(set ne null) + set.add(actor) + else { + val newSet = new ConcurrentSkipListSet[ActorRef] + newSet.add(actor) + if(actorsById.putIfAbsent(id,newSet) ne null) + registerById(attemptNo+1) + } } + registerById() + + // UUID + actorsByUUID.put(actor.uuid, actor) + // notify listeners foreachListener(_ ! ActorRegistered(actor)) } @@ -145,8 +156,11 @@ object ActorRegistry extends ListenerManagement { def unregister(actor: ActorRef) = { actorsByUUID remove actor.uuid - val id = actor.id - if (actorsById.containsKey(id)) actorsById.get(id).remove(actor) + val set = actorsById.get(actor.id) + if (set ne null) + set remove actor + + //FIXME: safely remove set if empty, leaks memory // notify listeners foreachListener(_ ! ActorUnregistered(actor)) diff --git a/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenDispatcher.scala b/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenDispatcher.scala index 836dc0ea86..1f03c1eba2 100644 --- a/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenDispatcher.scala +++ b/akka-core/src/main/scala/dispatch/ExecutorBasedEventDrivenDispatcher.scala @@ -82,7 +82,7 @@ class ExecutorBasedEventDrivenDispatcher(_name: String, throughput: Int = Dispat override def register(actorRef: ActorRef) = { // The actor will need a ConcurrentLinkedDeque based mailbox - if( actorRef.mailbox == null ) { + if( actorRef.mailbox eq null ) { actorRef.mailbox = new ConcurrentLinkedDeque[MessageInvocation]() } super.register(actorRef) From 88053cf39a877134e175afeda5e3135de57dc6fb Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Thu, 5 Aug 2010 17:28:07 +0200 Subject: [PATCH 092/188] Added unit test to test for race-condition in ActorRegistry --- .../test/scala/misc/ActorRegistrySpec.scala | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/akka-core/src/test/scala/misc/ActorRegistrySpec.scala b/akka-core/src/test/scala/misc/ActorRegistrySpec.scala index d6fc463a65..61626e9db3 100644 --- a/akka-core/src/test/scala/misc/ActorRegistrySpec.scala +++ b/akka-core/src/test/scala/misc/ActorRegistrySpec.scala @@ -3,6 +3,7 @@ package se.scalablesolutions.akka.actor import org.scalatest.junit.JUnitSuite import org.junit.Test import Actor._ +import java.util.concurrent.{CyclicBarrier, TimeUnit, CountDownLatch} object ActorRegistrySpec { var record = "" @@ -214,4 +215,41 @@ class ActorRegistrySpec extends JUnitSuite { ActorRegistry.unregister(actor2) assert(ActorRegistry.actors.size === 0) } + + @Test def shouldBeAbleToRegisterActorsConcurrently { + ActorRegistry.shutdownAll + + val latch = new CountDownLatch(3) + val barrier = new CyclicBarrier(3) + + def mkTestActor(i:Int) = actorOf( new Actor { + self.id = i.toString + def receive = { case _ => } + }) + + def mkTestActors = for(i <- 1 to 10;j <- 1 to 1000) yield mkTestActor(i) + + def mkThread(actors: Iterable[ActorRef]) = new Thread { + start + override def run { + barrier.await + actors foreach { _.start } + latch.countDown + } + } + + val testActors1 = mkTestActors + val testActors2 = mkTestActors + val testActors3 = mkTestActors + + mkThread(testActors1) + mkThread(testActors2) + mkThread(testActors3) + + assert(latch.await(30,TimeUnit.SECONDS) === true) + + for(i <- 1 to 10) { + assert(ActorRegistry.actorsFor(i.toString).length === 3000) + } + } } From 17e97ead5ab7990327fda9d7289e119b2dad1941 Mon Sep 17 00:00:00 2001 From: momania Date: Fri, 6 Aug 2010 13:35:44 +0200 Subject: [PATCH 093/188] - made rpc handler reqular function instead of partial function - add queuename as optional parameter for rpc server (for i.e. loadbalancing purposes) --- akka-amqp/src/main/scala/ExampleSession.scala | 8 ++-- akka-amqp/src/main/scala/RpcServerActor.scala | 2 +- .../test/scala/AMQPRpcClientServerTest.scala | 44 +++++++++---------- akka-amqp/src/test/scala/AMQPTest.scala | 2 +- 4 files changed, 27 insertions(+), 29 deletions(-) diff --git a/akka-amqp/src/main/scala/ExampleSession.scala b/akka-amqp/src/main/scala/ExampleSession.scala index 97571e2783..4fa1358a29 100644 --- a/akka-amqp/src/main/scala/ExampleSession.scala +++ b/akka-amqp/src/main/scala/ExampleSession.scala @@ -144,10 +144,10 @@ object ExampleSession { } val rpcServerSerializer = new RpcServerSerializer[String, Int](serverFromBinary, serverToBinary) - val rpcServer = AMQP.newRpcServer[String,Int](connection, exchangeParameters, "rpc.in.key", rpcServerSerializer, { - case "rpc_request" => 3 - case _ => error("unknown request") - }) + def requestHandler(request: String) = 3 + + val rpcServer = AMQP.newRpcServer[String,Int](connection, exchangeParameters, "rpc.in.key", rpcServerSerializer, + requestHandler, queueName = Some("rpc.in.key.queue")) /** Client */ diff --git a/akka-amqp/src/main/scala/RpcServerActor.scala b/akka-amqp/src/main/scala/RpcServerActor.scala index c64ef9058e..99d74d9b56 100644 --- a/akka-amqp/src/main/scala/RpcServerActor.scala +++ b/akka-amqp/src/main/scala/RpcServerActor.scala @@ -8,7 +8,7 @@ import se.scalablesolutions.akka.actor.{ActorRef, Actor} import com.rabbitmq.client.AMQP.BasicProperties import se.scalablesolutions.akka.amqp.AMQP.RpcServerSerializer -class RpcServerActor[I,O](producer: ActorRef, serializer: RpcServerSerializer[I,O], requestHandler: PartialFunction[I, O]) extends Actor { +class RpcServerActor[I,O](producer: ActorRef, serializer: RpcServerSerializer[I,O], requestHandler: I => O) extends Actor { log.info("%s started", this) diff --git a/akka-amqp/src/test/scala/AMQPRpcClientServerTest.scala b/akka-amqp/src/test/scala/AMQPRpcClientServerTest.scala index dcaec4cd06..c585675098 100644 --- a/akka-amqp/src/test/scala/AMQPRpcClientServerTest.scala +++ b/akka-amqp/src/test/scala/AMQPRpcClientServerTest.scala @@ -11,11 +11,9 @@ import se.scalablesolutions.akka.amqp._ import se.scalablesolutions.akka.actor.Actor._ import org.scalatest.matchers.MustMatchers import java.util.concurrent.{CountDownLatch, TimeUnit} -import se.scalablesolutions.akka.serialization.Serializer import se.scalablesolutions.akka.amqp.AMQP._ class AMQPRpcClientServerTest extends JUnitSuite with MustMatchers with Logging { - @Test def consumerMessage = if (AMQPTest.enabled) { val connection = AMQP.newConnection() @@ -32,31 +30,31 @@ class AMQPRpcClientServerTest extends JUnitSuite with MustMatchers with Logging val channelParameters = ChannelParameters(channelCallback = Some(channelCallback)) - val serverFromBinary = new FromBinary[String] { - def fromBinary(bytes: Array[Byte]) = new String(bytes) - } - val serverToBinary = new ToBinary[Int] { - def toBinary(t: Int) = Array(t.toByte) - } - val rpcServerSerializer = new RpcServerSerializer[String, Int](serverFromBinary, serverToBinary) - val rpcServer = AMQP.newRpcServer[String,Int](connection, exchangeParameters, "rpc.routing", rpcServerSerializer, { - case "some_payload" => 3 - case _ => error("unknown request") - }, channelParameters = Some(channelParameters)) + val rpcServerSerializer = new RpcServerSerializer[String, Int]( + new FromBinary[String] { + def fromBinary(bytes: Array[Byte]) = new String(bytes) + }, new ToBinary[Int] { + def toBinary(t: Int) = Array(t.toByte) + }) - val clientToBinary = new ToBinary[String] { - def toBinary(t: String) = t.getBytes - } - val clientFromBinary = new FromBinary[Int] { - def fromBinary(bytes: Array[Byte]) = bytes.head.toInt - } - val rpcClientSerializer = new RpcClientSerializer[String, Int](clientToBinary, clientFromBinary) - val rpcClient = AMQP.newRpcClient[String,Int](connection, exchangeParameters, "rpc.routing", rpcClientSerializer, + def requestHandler(request: String) = 3 + + val rpcServer = AMQP.newRpcServer[String, Int](connection, exchangeParameters, "rpc.routing", rpcServerSerializer, + requestHandler, channelParameters = Some(channelParameters)) + + val rpcClientSerializer = new RpcClientSerializer[String, Int]( + new ToBinary[String] { + def toBinary(t: String) = t.getBytes + }, new FromBinary[Int] { + def fromBinary(bytes: Array[Byte]) = bytes.head.toInt + }) + + val rpcClient = AMQP.newRpcClient[String, Int](connection, exchangeParameters, "rpc.routing", rpcClientSerializer, channelParameters = Some(channelParameters)) - countDown.await(2, TimeUnit.SECONDS) must be (true) + countDown.await(2, TimeUnit.SECONDS) must be(true) val response = rpcClient !! "some_payload" - response must be (Some(3)) + response must be(Some(3)) } finally { connection.stop } diff --git a/akka-amqp/src/test/scala/AMQPTest.scala b/akka-amqp/src/test/scala/AMQPTest.scala index 5ff9157bc5..8cad27ba60 100644 --- a/akka-amqp/src/test/scala/AMQPTest.scala +++ b/akka-amqp/src/test/scala/AMQPTest.scala @@ -5,5 +5,5 @@ package se.scalablesolutions.akka.amqp.test object AMQPTest { - def enabled = false + def enabled = true } From f6d86ed79c021659efac506814a9f3208fa9d82d Mon Sep 17 00:00:00 2001 From: momania Date: Fri, 6 Aug 2010 13:36:18 +0200 Subject: [PATCH 094/188] - move helper object actors in specs companion object to avoid clashes with the server spec (where the helpers have the same name) --- .../ClientInitiatedRemoteActorSpec.scala | 73 ++++++++++--------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/akka-core/src/test/scala/remote/ClientInitiatedRemoteActorSpec.scala b/akka-core/src/test/scala/remote/ClientInitiatedRemoteActorSpec.scala index e9ed8d4fa5..7ff46ab910 100644 --- a/akka-core/src/test/scala/remote/ClientInitiatedRemoteActorSpec.scala +++ b/akka-core/src/test/scala/remote/ClientInitiatedRemoteActorSpec.scala @@ -9,54 +9,57 @@ import se.scalablesolutions.akka.dispatch.Dispatchers import se.scalablesolutions.akka.actor.{ActorRef, Actor} import Actor._ -case class Send(actor: Actor) +object ClientInitiatedRemoteActorSpec { + case class Send(actor: Actor) -object RemoteActorSpecActorUnidirectional { - val latch = new CountDownLatch(1) -} -class RemoteActorSpecActorUnidirectional extends Actor { - self.dispatcher = Dispatchers.newThreadBasedDispatcher(self) - - def receive = { - case "OneWay" => - RemoteActorSpecActorUnidirectional.latch.countDown + object RemoteActorSpecActorUnidirectional { + val latch = new CountDownLatch(1) } -} + class RemoteActorSpecActorUnidirectional extends Actor { + self.dispatcher = Dispatchers.newThreadBasedDispatcher(self) -class RemoteActorSpecActorBidirectional extends Actor { - def receive = { - case "Hello" => - self.reply("World") - case "Failure" => - throw new RuntimeException("Expected exception; to test fault-tolerance") + def receive = { + case "OneWay" => + RemoteActorSpecActorUnidirectional.latch.countDown + } } -} -class SendOneWayAndReplyReceiverActor extends Actor { - def receive = { - case "Hello" => - self.reply("World") + class RemoteActorSpecActorBidirectional extends Actor { + def receive = { + case "Hello" => + self.reply("World") + case "Failure" => + throw new RuntimeException("Expected exception; to test fault-tolerance") + } } -} -object SendOneWayAndReplySenderActor { - val latch = new CountDownLatch(1) -} -class SendOneWayAndReplySenderActor extends Actor { - var state: Option[AnyRef] = None - var sendTo: ActorRef = _ - var latch: CountDownLatch = _ + class SendOneWayAndReplyReceiverActor extends Actor { + def receive = { + case "Hello" => + self.reply("World") + } + } - def sendOff = sendTo ! "Hello" + object SendOneWayAndReplySenderActor { + val latch = new CountDownLatch(1) + } + class SendOneWayAndReplySenderActor extends Actor { + var state: Option[AnyRef] = None + var sendTo: ActorRef = _ + var latch: CountDownLatch = _ - def receive = { - case msg: AnyRef => - state = Some(msg) - SendOneWayAndReplySenderActor.latch.countDown + def sendOff = sendTo ! "Hello" + + def receive = { + case msg: AnyRef => + state = Some(msg) + SendOneWayAndReplySenderActor.latch.countDown + } } } class ClientInitiatedRemoteActorSpec extends JUnitSuite { + import ClientInitiatedRemoteActorSpec._ se.scalablesolutions.akka.config.Config.config val HOSTNAME = "localhost" From 09d7cc75eb3c2b45735f29fdaa12bbd1c77d1d08 Mon Sep 17 00:00:00 2001 From: momania Date: Fri, 6 Aug 2010 13:39:24 +0200 Subject: [PATCH 095/188] - forgot the api commit - disable tests again :S --- akka-amqp/src/main/scala/AMQP.scala | 6 ++++-- akka-amqp/src/test/scala/AMQPTest.scala | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/akka-amqp/src/main/scala/AMQP.scala b/akka-amqp/src/main/scala/AMQP.scala index 0bfbd93063..b1e08ae752 100644 --- a/akka-amqp/src/main/scala/AMQP.scala +++ b/akka-amqp/src/main/scala/AMQP.scala @@ -95,13 +95,15 @@ object AMQP { exchangeParameters: ExchangeParameters, routingKey: String, serializer: RpcServerSerializer[I,O], - requestHandler: PartialFunction[I, O], + requestHandler: I => O, + queueName: Option[String] = None, channelParameters: Option[ChannelParameters] = None) = { val producer = newProducer(connection, new ProducerParameters(new ExchangeParameters("", ExchangeType.Direct), channelParameters = channelParameters)) val rpcServer = actorOf(new RpcServerActor[I,O](producer, serializer, requestHandler)) val consumer = newConsumer(connection, new ConsumerParameters(exchangeParameters, routingKey, rpcServer , channelParameters = channelParameters - , selfAcknowledging = false)) + , selfAcknowledging = false + , queueName = queueName)) } diff --git a/akka-amqp/src/test/scala/AMQPTest.scala b/akka-amqp/src/test/scala/AMQPTest.scala index 8cad27ba60..5ff9157bc5 100644 --- a/akka-amqp/src/test/scala/AMQPTest.scala +++ b/akka-amqp/src/test/scala/AMQPTest.scala @@ -5,5 +5,5 @@ package se.scalablesolutions.akka.amqp.test object AMQPTest { - def enabled = true + def enabled = false } From 6c6d3d246b3e057d36e9f6adcbbeef0ddeb12ada Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Fri, 6 Aug 2010 16:03:36 +0200 Subject: [PATCH 096/188] Closing ticket 337 --- akka-core/src/main/scala/util/Logging.scala | 127 +++++++++++++++++++- config/akka-reference.conf | 14 --- config/log4j.properties | 2 +- project/build/AkkaProject.scala | 15 ++- 4 files changed, 136 insertions(+), 22 deletions(-) diff --git a/akka-core/src/main/scala/util/Logging.scala b/akka-core/src/main/scala/util/Logging.scala index 8c6ea0fb99..9be0ba6087 100644 --- a/akka-core/src/main/scala/util/Logging.scala +++ b/akka-core/src/main/scala/util/Logging.scala @@ -4,7 +4,7 @@ package se.scalablesolutions.akka.util -import net.lag.logging.Logger +import org.slf4j.{Logger => SLFLogger,LoggerFactory => SLFLoggerFactory} import java.io.StringWriter import java.io.PrintWriter @@ -17,9 +17,132 @@ import java.net.UnknownHostException * @author Jonas Bonér */ trait Logging { - @sjson.json.JSONProperty(ignore = true) @transient lazy val log = Logger.get(this.getClass.getName) + @sjson.json.JSONProperty(ignore = true) @transient lazy val log = Logger(this.getClass.getName) } +/** + * Scala SLF4J wrapper + * + * ex. + * + * class Foo extends Logging { + * log.info("My foo is %s","alive") + * log.error(new Exception(),"My foo is %s","broken") + * } + */ +class Logger(val logger: SLFLogger) +{ + def name = logger.getName + + def trace_? = logger.isTraceEnabled + def debug_? = logger.isDebugEnabled + def info_? = logger.isInfoEnabled + def warning_? = logger.isWarnEnabled + def error_? = logger.isErrorEnabled + + //Trace + def trace(t: => Throwable,msg: => String,args: Any*){ + ifTrace(t,message(msg,args:_*)) + } + + def trace(msg: => String,args: Any*){ + ifTrace(message(msg,args:_*)) + } + + def ifTrace(msg: => String): Unit = if (trace_?) logger trace msg + + def ifTrace(t: => Throwable,msg: => String): Unit = { + if(trace_?) logger.trace(msg,t) + } + + //Debug + def debug(t: => Throwable,msg: => String,args: Any*){ + ifDebug(t,message(msg,args:_*)) + } + + def debug(msg: => String,args: Any*){ + ifDebug(message(msg,args:_*)) + } + + def ifDebug(msg: => String): Unit = if (debug_?) logger debug msg + + def ifDebug(t: => Throwable,msg: => String): Unit = { + if(debug_?) logger.debug(msg,t) + } + + //Info + def info(t: => Throwable,msg: => String,args: Any*){ + ifInfo(t,message(msg,args:_*)) + } + + def info(msg: => String,args: Any*){ + ifInfo(message(msg,args:_*)) + } + + def ifInfo(msg: => String): Unit = if (info_?) logger info msg + + def ifInfo(t: => Throwable,msg: => String): Unit = { + if(info_?) logger.info(msg,t) + } + + //Warning + def warning(t: => Throwable,msg: => String,args: Any*){ + ifWarning(t,message(msg,args:_*)) + } + + def warning(msg: => String,args: Any*){ + ifWarning(message(msg,args:_*)) + } + + def ifWarning(msg: => String): Unit = if (warning_?) logger warn msg + + def ifWarning(t: => Throwable,msg: => String): Unit = { + if(warning_?) logger.warn(msg,t) + } + + //Error + def error(t: => Throwable,msg: => String,args: Any*){ + ifError(t,message(msg,args:_*)) + } + + def error(msg: => String,args: Any*){ + ifError(message(msg,args:_*)) + } + + def ifError(msg: => String): Unit = if (error_?) logger error msg + + def ifError(t: => Throwable,msg: => String): Unit = { + if(error_?) logger.error(msg,t) + } + + protected def message(msg: String, args: Any*) : String = { + if(args.isEmpty || (args eq null)) + msg + else + msg.format(args:_*) + } +} + +/** + * Logger factory + * + * ex. + * + * val logger = Logger("my.cool.logger") + * val logger = Logger(classOf[Banana]) + * val rootLogger = Logger.root + */ +object Logger +{ + def apply(logger: String) : Logger = new Logger(SLFLoggerFactory getLogger logger) + + def apply(clazz: Class[_]) : Logger = apply(clazz.getName) + + def root : Logger = apply(SLFLogger.ROOT_LOGGER_NAME) +} + + + /** * LoggableException is a subclass of Exception and can be used as the base exception * for application specific exceptions. diff --git a/config/akka-reference.conf b/config/akka-reference.conf index 3b80953fe6..cda3f01d6d 100644 --- a/config/akka-reference.conf +++ b/config/akka-reference.conf @@ -5,20 +5,6 @@ # This file has all the default settings, so all these could be removed with no visible effect. # Modify as needed. -log { - filename = "./logs/akka.log" - roll = "daily" # Options: never, hourly, daily, sunday/monday/... - level = "debug" # Options: fatal, critical, error, warning, info, debug, trace - console = on - # syslog_host = "" - # syslog_server_name = "" - - akka { # example of package level logging settings - node = "se.scalablesolutions.akka" - level = "debug" - } -} - akka { version = "0.10" diff --git a/config/log4j.properties b/config/log4j.properties index 76d3661163..9ea188f8c4 100755 --- a/config/log4j.properties +++ b/config/log4j.properties @@ -17,4 +17,4 @@ log4j.appender.R.layout.ConversionPattern=%5p [%t] %d{ISO8601} %F (line %L) %m%n # Edit the next line to point to your logs directory log4j.appender.R.File=./logs/akka.log -log4j.logger.org.atmosphere=DEBUG +log4j.logger.se.scalablesolutions=INFO diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 02f72d7f0e..c247f475af 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -266,7 +266,12 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { ) // Exclude slf4j1.5.11 from the classpath, it's conflicting... - override def runClasspath = super.runClasspath --- (super.runClasspath ** "slf4j*1.5.11.jar") + override def runClasspath = super.runClasspath +++ + descendents(info.projectPath / "config", "*") --- + (super.runClasspath ** "slf4j*1.5.11.jar") + + override def mainResources = super.mainResources +++ + descendents(info.projectPath / "config", "*") // ------------------------------------------------------------ // publishing @@ -343,6 +348,9 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { val sjson = Dependencies.sjson val werkz = Dependencies.werkz val werkz_core = Dependencies.werkz_core + val slf4j = Dependencies.slf4j + val slf4j_log4j = Dependencies.slf4j_log4j + val log4j = Dependencies.log4j // testing val junit = Dependencies.junit @@ -453,9 +461,6 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { class AkkaCassandraProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) { val cassandra = Dependencies.cassandra - val log4j = Dependencies.log4j - val slf4j = Dependencies.slf4j - val slf4j_log4j = Dependencies.slf4j_log4j // testing val cassandra_clhm = Dependencies.cassandra_clhm @@ -634,6 +639,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { } class AkkaSampleCamelProject(info: ProjectInfo) extends AkkaDefaultProject(info, deployPath) with CodeFellowPlugin { + //Must be like this to be able to exclude the geronimo-servlet_2.4_spec which is a too old Servlet spec override def ivyXML = @@ -701,7 +707,6 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { ((outputPath ##) / defaultJarName) +++ mainResources +++ mainDependencies.scalaJars +++ - descendents(info.projectPath, "*.conf") +++ descendents(info.projectPath / "scripts", "run_akka.sh") +++ descendents(info.projectPath / "dist", "*.jar") +++ descendents(info.projectPath / "deploy", "*.jar") +++ From db842dee4b518ae6d0fac87e6a07d7d0322a9994 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Fri, 6 Aug 2010 17:13:31 +0200 Subject: [PATCH 097/188] Fixing ticket 372 --- akka-core/src/main/scala/actor/ActorRef.scala | 16 ++++---- .../src/main/scala/actor/Scheduler.scala | 39 +++---------------- 2 files changed, 14 insertions(+), 41 deletions(-) diff --git a/akka-core/src/main/scala/actor/ActorRef.scala b/akka-core/src/main/scala/actor/ActorRef.scala index 2fd205edeb..39a1ff774c 100644 --- a/akka-core/src/main/scala/actor/ActorRef.scala +++ b/akka-core/src/main/scala/actor/ActorRef.scala @@ -24,13 +24,13 @@ import org.multiverse.api.exceptions.DeadTransactionException import java.net.InetSocketAddress import java.util.concurrent.locks.ReentrantLock import java.util.concurrent.atomic.AtomicReference -import java.util.concurrent.{ConcurrentHashMap, TimeUnit} import java.util.{Map => JMap} import java.lang.reflect.Field import jsr166x.{Deque, ConcurrentLinkedDeque} import com.google.protobuf.ByteString +import java.util.concurrent.{ScheduledFuture, ConcurrentHashMap, TimeUnit} /** * ActorRef is an immutable and serializable handle to an Actor. @@ -72,7 +72,7 @@ trait ActorRef extends TransactionManagement with java.lang.Comparable[ActorRef] @volatile protected[this] var _isShutDown = false @volatile protected[akka] var _isBeingRestarted = false @volatile protected[akka] var _homeAddress = new InetSocketAddress(RemoteServer.HOSTNAME, RemoteServer.PORT) - @volatile protected[akka] var _timeoutActor: Option[ActorRef] = None + @volatile protected[akka] var _futureTimeout: Option[ScheduledFuture[AnyRef]] = None @volatile protected[akka] var startOnCreation = false @volatile protected[akka] var registeredInRemoteNodeDuringSerialization = false protected[this] val guard = new ReentrantGuard @@ -559,14 +559,16 @@ trait ActorRef extends TransactionManagement with java.lang.Comparable[ActorRef] cancelReceiveTimeout receiveTimeout.foreach { time => log.debug("Scheduling timeout for %s", this) - _timeoutActor = Some(Scheduler.scheduleOnce(this, ReceiveTimeout, time, TimeUnit.MILLISECONDS)) + _futureTimeout = Some(Scheduler.scheduleOnce(this, ReceiveTimeout, time, TimeUnit.MILLISECONDS)) } } - protected[akka] def cancelReceiveTimeout = _timeoutActor.foreach { timeoutActor => - if (timeoutActor.isRunning) Scheduler.unschedule(timeoutActor) - _timeoutActor = None - log.debug("Timeout canceled for %s", this) + protected[akka] def cancelReceiveTimeout = { + if(_futureTimeout.isDefined) { + _futureTimeout.get.cancel(true) + _futureTimeout = None + log.debug("Timeout canceled for %s", this) + } } } diff --git a/akka-core/src/main/scala/actor/Scheduler.scala b/akka-core/src/main/scala/actor/Scheduler.scala index 6f4f099bb2..07486521ec 100644 --- a/akka-core/src/main/scala/actor/Scheduler.scala +++ b/akka-core/src/main/scala/actor/Scheduler.scala @@ -23,59 +23,39 @@ import se.scalablesolutions.akka.util.Logging object Scheduler extends Logging { import Actor._ - case object UnSchedule case class SchedulerException(msg: String, e: Throwable) extends RuntimeException(msg, e) private var service = Executors.newSingleThreadScheduledExecutor(SchedulerThreadFactory) - private val schedulers = new ConcurrentHashMap[ActorRef, ActorRef] + log.info("Starting up Scheduler") - def schedule(receiver: ActorRef, message: AnyRef, initialDelay: Long, delay: Long, timeUnit: TimeUnit): ActorRef = { + def schedule(receiver: ActorRef, message: AnyRef, initialDelay: Long, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] = { log.trace( "Schedule scheduled event\n\tevent = [%s]\n\treceiver = [%s]\n\tinitialDelay = [%s]\n\tdelay = [%s]\n\ttimeUnit = [%s]", message, receiver, initialDelay, delay, timeUnit) try { - val future = service.scheduleAtFixedRate( + service.scheduleAtFixedRate( new Runnable { def run = receiver ! message }, initialDelay, delay, timeUnit).asInstanceOf[ScheduledFuture[AnyRef]] - createAndStoreScheduleActorForFuture(future) - val scheduler = actorOf(new ScheduleActor(future)).start - schedulers.put(scheduler, scheduler) - scheduler } catch { case e => throw SchedulerException(message + " could not be scheduled on " + receiver, e) } } - def scheduleOnce(receiver: ActorRef, message: AnyRef, delay: Long, timeUnit: TimeUnit): ActorRef = { + def scheduleOnce(receiver: ActorRef, message: AnyRef, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] = { log.trace( "Schedule one-time event\n\tevent = [%s]\n\treceiver = [%s]\n\tdelay = [%s]\n\ttimeUnit = [%s]", message, receiver, delay, timeUnit) try { - val future = service.schedule( + service.schedule( new Runnable { def run = receiver ! message }, delay, timeUnit).asInstanceOf[ScheduledFuture[AnyRef]] - createAndStoreScheduleActorForFuture(future) } catch { case e => throw SchedulerException(message + " could not be scheduled on " + receiver, e) } } - private def createAndStoreScheduleActorForFuture(future: ScheduledFuture[AnyRef]): ActorRef = { - val scheduler = actorOf(new ScheduleActor(future)).start - schedulers.put(scheduler, scheduler) - scheduler - } - - def unschedule(scheduleActor: ActorRef) = { - scheduleActor ! UnSchedule - schedulers.remove(scheduleActor) - } - def shutdown = { log.info("Shutting down Scheduler") - import scala.collection.JavaConversions._ - schedulers.values.foreach(_ ! UnSchedule) - schedulers.clear service.shutdown } @@ -86,15 +66,6 @@ object Scheduler extends Logging { } } -private class ScheduleActor(future: ScheduledFuture[AnyRef]) extends Actor { - def receive = { - case Scheduler.UnSchedule => - Scheduler.log.trace("Unschedule event handled by scheduleActor\n\tactorRef = [%s]", self.toString) - future.cancel(true) - self.stop - } -} - private object SchedulerThreadFactory extends ThreadFactory { private var count = 0 val threadFactory = Executors.defaultThreadFactory() From be4be45a8d3728bb51ee0bbb7201b4417e286556 Mon Sep 17 00:00:00 2001 From: momania Date: Fri, 6 Aug 2010 17:31:37 +0200 Subject: [PATCH 098/188] - moved all into package folder structure - added simple protobuf based rpc convenience --- .../scalablesolutions/akka/amqp}/AMQP.scala | 53 ++------- .../akka/amqp}/AMQPMessage.scala | 0 .../akka/amqp}/ConsumerActor.scala | 0 .../akka/amqp}/ExampleSession.scala | 6 +- .../akka/amqp}/ExchangeType.scala | 0 .../amqp}/FaultTolerantChannelActor.scala | 0 .../amqp}/FaultTolerantConnectionActor.scala | 0 .../akka/amqp}/ProducerActor.scala | 0 .../scalablesolutions/akka/amqp/rpc/RPC.scala | 110 ++++++++++++++++++ .../akka/amqp/rpc}/RpcClientActor.scala | 6 +- .../akka/amqp/rpc}/RpcServerActor.scala | 2 +- .../test}/AMQPConnectionRecoveryTest.scala | 17 +-- .../AMQPConsumerChannelRecoveryTest.scala | 18 +-- .../AMQPConsumerConnectionRecoveryTest.scala | 20 +--- .../AMQPConsumerManualAcknowledgeTest.scala | 18 +-- .../amqp/test}/AMQPConsumerMessageTest.scala | 18 +-- .../AMQPProducerChannelRecoveryTest.scala | 18 +-- .../AMQPProducerConnectionRecoveryTest.scala | 18 +-- .../amqp/test}/AMQPProducerMessageTest.scala | 18 +-- .../amqp/test}/AMQPRpcClientServerTest.scala | 25 ++-- .../akka/amqp/test/AMQPRpcProtobufTest.scala | 35 ++++++ .../akka/amqp/test}/AMQPTest.scala | 2 +- project/build/AkkaProject.scala | 50 ++++---- 23 files changed, 238 insertions(+), 196 deletions(-) rename akka-amqp/src/main/scala/{ => se/scalablesolutions/akka/amqp}/AMQP.scala (69%) rename akka-amqp/src/main/scala/{ => se/scalablesolutions/akka/amqp}/AMQPMessage.scala (100%) rename akka-amqp/src/main/scala/{ => se/scalablesolutions/akka/amqp}/ConsumerActor.scala (100%) rename akka-amqp/src/main/scala/{ => se/scalablesolutions/akka/amqp}/ExampleSession.scala (94%) rename akka-amqp/src/main/scala/{ => se/scalablesolutions/akka/amqp}/ExchangeType.scala (100%) rename akka-amqp/src/main/scala/{ => se/scalablesolutions/akka/amqp}/FaultTolerantChannelActor.scala (100%) rename akka-amqp/src/main/scala/{ => se/scalablesolutions/akka/amqp}/FaultTolerantConnectionActor.scala (100%) rename akka-amqp/src/main/scala/{ => se/scalablesolutions/akka/amqp}/ProducerActor.scala (100%) create mode 100644 akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/rpc/RPC.scala rename akka-amqp/src/main/scala/{ => se/scalablesolutions/akka/amqp/rpc}/RpcClientActor.scala (89%) rename akka-amqp/src/main/scala/{ => se/scalablesolutions/akka/amqp/rpc}/RpcServerActor.scala (94%) rename akka-amqp/src/test/scala/{ => se/scalablesolutions/akka/amqp/test}/AMQPConnectionRecoveryTest.scala (85%) rename akka-amqp/src/test/scala/{ => se/scalablesolutions/akka/amqp/test}/AMQPConsumerChannelRecoveryTest.scala (88%) rename akka-amqp/src/test/scala/{ => se/scalablesolutions/akka/amqp/test}/AMQPConsumerConnectionRecoveryTest.scala (88%) rename akka-amqp/src/test/scala/{ => se/scalablesolutions/akka/amqp/test}/AMQPConsumerManualAcknowledgeTest.scala (88%) rename akka-amqp/src/test/scala/{ => se/scalablesolutions/akka/amqp/test}/AMQPConsumerMessageTest.scala (86%) rename akka-amqp/src/test/scala/{ => se/scalablesolutions/akka/amqp/test}/AMQPProducerChannelRecoveryTest.scala (86%) rename akka-amqp/src/test/scala/{ => se/scalablesolutions/akka/amqp/test}/AMQPProducerConnectionRecoveryTest.scala (86%) rename akka-amqp/src/test/scala/{ => se/scalablesolutions/akka/amqp/test}/AMQPProducerMessageTest.scala (84%) rename akka-amqp/src/test/scala/{ => se/scalablesolutions/akka/amqp/test}/AMQPRpcClientServerTest.scala (77%) create mode 100644 akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPRpcProtobufTest.scala rename akka-amqp/src/test/scala/{ => se/scalablesolutions/akka/amqp/test}/AMQPTest.scala (87%) diff --git a/akka-amqp/src/main/scala/AMQP.scala b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/AMQP.scala similarity index 69% rename from akka-amqp/src/main/scala/AMQP.scala rename to akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/AMQP.scala index b1e08ae752..0823f306cd 100644 --- a/akka-amqp/src/main/scala/AMQP.scala +++ b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/AMQP.scala @@ -1,15 +1,16 @@ -/** - * Copyright (C) 2009-2010 Scalable Solutions AB - */ - package se.scalablesolutions.akka.amqp -import se.scalablesolutions.akka.actor.{Actor, ActorRef} -import se.scalablesolutions.akka.actor.Actor._ +/** + * Copyright (C) 2009-2010 Scalable Solutions AB + */ + import se.scalablesolutions.akka.config.OneForOneStrategy import com.rabbitmq.client.{ReturnListener, ShutdownListener, ConnectionFactory} import java.lang.IllegalArgumentException import se.scalablesolutions.akka.util.Logging +import se.scalablesolutions.akka.actor.{Actor, ActorRef} +import Actor._ + /** * AMQP Actor API. Implements Connection, Producer and Consumer materialized as Actors. * @@ -80,33 +81,6 @@ object AMQP { consumer } - def newRpcClient[O,I](connection: ActorRef, - exchangeParameters: ExchangeParameters, - routingKey: String, - serializer: RpcClientSerializer[O,I], - channelParameters: Option[ChannelParameters] = None): ActorRef = { - val rpcActor: ActorRef = actorOf(new RpcClientActor[O,I](exchangeParameters, routingKey, serializer, channelParameters)) - connection.startLink(rpcActor) - rpcActor ! Start - rpcActor - } - - def newRpcServer[I,O](connection: ActorRef, - exchangeParameters: ExchangeParameters, - routingKey: String, - serializer: RpcServerSerializer[I,O], - requestHandler: I => O, - queueName: Option[String] = None, - channelParameters: Option[ChannelParameters] = None) = { - val producer = newProducer(connection, new ProducerParameters(new ExchangeParameters("", ExchangeType.Direct), channelParameters = channelParameters)) - val rpcServer = actorOf(new RpcServerActor[I,O](producer, serializer, requestHandler)) - val consumer = newConsumer(connection, new ConsumerParameters(exchangeParameters, routingKey, rpcServer - , channelParameters = channelParameters - , selfAcknowledging = false - , queueName = queueName)) - - } - private val supervisor = new AMQPSupervisor class AMQPSupervisor extends Logging { @@ -129,17 +103,4 @@ object AMQP { connectionActor } } - - trait FromBinary[T] { - def fromBinary(bytes: Array[Byte]): T - } - - trait ToBinary[T] { - def toBinary(t: T): Array[Byte] - } - - - case class RpcClientSerializer[O,I](toBinary: ToBinary[O], fromBinary: FromBinary[I]) - - case class RpcServerSerializer[I,O](fromBinary: FromBinary[I], toBinary: ToBinary[O]) } diff --git a/akka-amqp/src/main/scala/AMQPMessage.scala b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/AMQPMessage.scala similarity index 100% rename from akka-amqp/src/main/scala/AMQPMessage.scala rename to akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/AMQPMessage.scala diff --git a/akka-amqp/src/main/scala/ConsumerActor.scala b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/ConsumerActor.scala similarity index 100% rename from akka-amqp/src/main/scala/ConsumerActor.scala rename to akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/ConsumerActor.scala diff --git a/akka-amqp/src/main/scala/ExampleSession.scala b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/ExampleSession.scala similarity index 94% rename from akka-amqp/src/main/scala/ExampleSession.scala rename to akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/ExampleSession.scala index 4fa1358a29..f2ae5e8295 100644 --- a/akka-amqp/src/main/scala/ExampleSession.scala +++ b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/ExampleSession.scala @@ -4,6 +4,8 @@ package se.scalablesolutions.akka.amqp +import rpc.RPC +import rpc.RPC.{RpcClientSerializer, RpcServerSerializer, ToBinary, FromBinary} import se.scalablesolutions.akka.actor.{Actor, ActorRegistry} import Actor._ import java.util.concurrent.{CountDownLatch, TimeUnit} @@ -146,7 +148,7 @@ object ExampleSession { def requestHandler(request: String) = 3 - val rpcServer = AMQP.newRpcServer[String,Int](connection, exchangeParameters, "rpc.in.key", rpcServerSerializer, + val rpcServer = RPC.newRpcServer[String,Int](connection, exchangeParameters, "rpc.in.key", rpcServerSerializer, requestHandler, queueName = Some("rpc.in.key.queue")) @@ -159,7 +161,7 @@ object ExampleSession { } val rpcClientSerializer = new RpcClientSerializer[String, Int](clientToBinary, clientFromBinary) - val rpcClient = AMQP.newRpcClient[String,Int](connection, exchangeParameters, "rpc.in.key", rpcClientSerializer) + val rpcClient = RPC.newRpcClient[String,Int](connection, exchangeParameters, "rpc.in.key", rpcClientSerializer) val response = (rpcClient !! "rpc_request") log.info("Response: " + response) diff --git a/akka-amqp/src/main/scala/ExchangeType.scala b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/ExchangeType.scala similarity index 100% rename from akka-amqp/src/main/scala/ExchangeType.scala rename to akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/ExchangeType.scala diff --git a/akka-amqp/src/main/scala/FaultTolerantChannelActor.scala b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/FaultTolerantChannelActor.scala similarity index 100% rename from akka-amqp/src/main/scala/FaultTolerantChannelActor.scala rename to akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/FaultTolerantChannelActor.scala diff --git a/akka-amqp/src/main/scala/FaultTolerantConnectionActor.scala b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/FaultTolerantConnectionActor.scala similarity index 100% rename from akka-amqp/src/main/scala/FaultTolerantConnectionActor.scala rename to akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/FaultTolerantConnectionActor.scala diff --git a/akka-amqp/src/main/scala/ProducerActor.scala b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/ProducerActor.scala similarity index 100% rename from akka-amqp/src/main/scala/ProducerActor.scala rename to akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/ProducerActor.scala diff --git a/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/rpc/RPC.scala b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/rpc/RPC.scala new file mode 100644 index 0000000000..a711a01cc5 --- /dev/null +++ b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/rpc/RPC.scala @@ -0,0 +1,110 @@ +package se.scalablesolutions.akka.amqp.rpc + +import se.scalablesolutions.akka.amqp.AMQP._ +import com.google.protobuf.Message +import se.scalablesolutions.akka.actor.{Actor, ActorRef} +import Actor._ +import se.scalablesolutions.akka.amqp._ + +object RPC { + + def newRpcClient[O, I](connection: ActorRef, + exchangeParameters: ExchangeParameters, + routingKey: String, + serializer: RpcClientSerializer[O, I], + channelParameters: Option[ChannelParameters] = None): ActorRef = { + val rpcActor: ActorRef = actorOf(new RpcClientActor[O, I](exchangeParameters, routingKey, serializer, channelParameters)) + connection.startLink(rpcActor) + rpcActor ! Start + rpcActor + } + + def newRpcServer[I, O](connection: ActorRef, + exchangeParameters: ExchangeParameters, + routingKey: String, + serializer: RpcServerSerializer[I, O], + requestHandler: I => O, + queueName: Option[String] = None, + channelParameters: Option[ChannelParameters] = None) = { + val producer = newProducer(connection, new ProducerParameters(new ExchangeParameters("", ExchangeType.Direct), channelParameters = channelParameters)) + val rpcServer = actorOf(new RpcServerActor[I, O](producer, serializer, requestHandler)) + val consumer = newConsumer(connection, new ConsumerParameters(exchangeParameters, routingKey, rpcServer + , channelParameters = channelParameters + , selfAcknowledging = false + , queueName = queueName)) + + } + + trait FromBinary[T] { + def fromBinary(bytes: Array[Byte]): T + } + + trait ToBinary[T] { + def toBinary(t: T): Array[Byte] + } + + + case class RpcClientSerializer[O, I](toBinary: ToBinary[O], fromBinary: FromBinary[I]) + + case class RpcServerSerializer[I, O](fromBinary: FromBinary[I], toBinary: ToBinary[O]) + + + /** + * RPC convenience + */ + trait RpcClient[O, I] { + def callService(request: O, timeout: Long = 5000): Option[I] + } + + private class RpcServiceClient[O, I](client: ActorRef) extends RpcClient[O, I] { + def callService(request: O, timeout: Long = 5000): Option[I] = { + (client.!!(request, timeout)).as[I] + } + } + + private val ARRAY_OF_BYTE_ARRAY = Array[Class[_]](classOf[Array[Byte]]) + + def startProtobufServer[I <: Message, O <: Message]( + connection: ActorRef, serviceName: String, requestHandler: I => O)(implicit manifest: Manifest[I]) = { + + val serializer = new RpcServerSerializer[I, O]( + new FromBinary[I] { + def fromBinary(bytes: Array[Byte]): I = { + createProtobufFromBytes[I](bytes) + } + }, new ToBinary[O] { + def toBinary(t: O) = t.toByteArray + }) + + val exchangeParameters = new ExchangeParameters(serviceName, ExchangeType.Topic) + val routingKey = "%s.request".format(serviceName) + val queueName = "%s.in".format(routingKey) + + newRpcServer[I, O](connection, exchangeParameters, routingKey, serializer, requestHandler, + queueName = Some(queueName)) + } + + def startProtobufClient[O <: Message, I <: Message]( + connection: ActorRef, serviceName: String)(implicit manifest: Manifest[I]): RpcClient[O, I] = { + + val serializer = new RpcClientSerializer[O, I]( + new ToBinary[O] { + def toBinary(t: O) = t.toByteArray + }, new FromBinary[I] { + def fromBinary(bytes: Array[Byte]): I = { + createProtobufFromBytes[I](bytes) + } + }) + + val exchangeParameters = new ExchangeParameters(serviceName, ExchangeType.Topic) + val routingKey = "%s.request".format(serviceName) + val queueName = "%s.in".format(routingKey) + + val client = newRpcClient[O, I](connection, exchangeParameters, routingKey, serializer) + new RpcServiceClient[O, I](client) + } + + private def createProtobufFromBytes[I](bytes: Array[Byte])(implicit manifest: Manifest[I]): I = { + manifest.erasure.getDeclaredMethod("parseFrom", ARRAY_OF_BYTE_ARRAY: _*).invoke(null, bytes).asInstanceOf[I] + } +} \ No newline at end of file diff --git a/akka-amqp/src/main/scala/RpcClientActor.scala b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/rpc/RpcClientActor.scala similarity index 89% rename from akka-amqp/src/main/scala/RpcClientActor.scala rename to akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/rpc/RpcClientActor.scala index 2935982a67..40665194fc 100644 --- a/akka-amqp/src/main/scala/RpcClientActor.scala +++ b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/rpc/RpcClientActor.scala @@ -4,11 +4,9 @@ package se.scalablesolutions.akka.amqp -import se.scalablesolutions.akka.serialization.Serializer -import se.scalablesolutions.akka.amqp.AMQP.{ChannelParameters, ExchangeParameters} - import com.rabbitmq.client.{Channel, RpcClient} -import se.scalablesolutions.akka.amqp.AMQP.{RpcClientSerializer, ChannelParameters, ExchangeParameters} +import rpc.RPC.RpcClientSerializer +import se.scalablesolutions.akka.amqp.AMQP.{ChannelParameters, ExchangeParameters} class RpcClientActor[I,O](exchangeParameters: ExchangeParameters, routingKey: String, diff --git a/akka-amqp/src/main/scala/RpcServerActor.scala b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/rpc/RpcServerActor.scala similarity index 94% rename from akka-amqp/src/main/scala/RpcServerActor.scala rename to akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/rpc/RpcServerActor.scala index 99d74d9b56..7c1cc01d01 100644 --- a/akka-amqp/src/main/scala/RpcServerActor.scala +++ b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/rpc/RpcServerActor.scala @@ -4,9 +4,9 @@ package se.scalablesolutions.akka.amqp +import rpc.RPC.RpcServerSerializer import se.scalablesolutions.akka.actor.{ActorRef, Actor} import com.rabbitmq.client.AMQP.BasicProperties -import se.scalablesolutions.akka.amqp.AMQP.RpcServerSerializer class RpcServerActor[I,O](producer: ActorRef, serializer: RpcServerSerializer[I,O], requestHandler: I => O) extends Actor { diff --git a/akka-amqp/src/test/scala/AMQPConnectionRecoveryTest.scala b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPConnectionRecoveryTest.scala similarity index 85% rename from akka-amqp/src/test/scala/AMQPConnectionRecoveryTest.scala rename to akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPConnectionRecoveryTest.scala index c1af35546a..ef2ee5b80f 100644 --- a/akka-amqp/src/test/scala/AMQPConnectionRecoveryTest.scala +++ b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPConnectionRecoveryTest.scala @@ -1,12 +1,9 @@ +package se.scalablesolutions.akka.amqp.test + /** * Copyright (C) 2009-2010 Scalable Solutions AB */ -package se.scalablesolutions.akka.amqp.test - -import se.scalablesolutions.akka.util.Logging -import org.scalatest.junit.JUnitSuite -import org.junit.Test import java.util.concurrent.TimeUnit import se.scalablesolutions.akka.actor.{Actor, ActorRef} import org.multiverse.api.latches.StandardLatch @@ -14,8 +11,10 @@ import com.rabbitmq.client.ShutdownSignalException import se.scalablesolutions.akka.amqp._ import se.scalablesolutions.akka.amqp.AMQP.ConnectionParameters import org.scalatest.matchers.MustMatchers +import org.scalatest.junit.JUnitSuite +import org.junit.Test -class AMQPConnectionRecoveryTest extends JUnitSuite with MustMatchers with Logging { +class AMQPConnectionRecoveryTest extends JUnitSuite with MustMatchers { @Test def connectionAndRecovery = if (AMQPTest.enabled) { @@ -50,10 +49,4 @@ class AMQPConnectionRecoveryTest extends JUnitSuite with MustMatchers with Loggi } } - @Test - def dummy { - // amqp tests need local rabbitmq server running, so a disabled by default. - // this dummy test makes sure that the whole test class doesn't fail because of missing tests - assert(true) - } } diff --git a/akka-amqp/src/test/scala/AMQPConsumerChannelRecoveryTest.scala b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPConsumerChannelRecoveryTest.scala similarity index 88% rename from akka-amqp/src/test/scala/AMQPConsumerChannelRecoveryTest.scala rename to akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPConsumerChannelRecoveryTest.scala index a0b44f4739..3c21fa36af 100644 --- a/akka-amqp/src/test/scala/AMQPConsumerChannelRecoveryTest.scala +++ b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPConsumerChannelRecoveryTest.scala @@ -1,12 +1,9 @@ +package se.scalablesolutions.akka.amqp.test + /** * Copyright (C) 2009-2010 Scalable Solutions AB */ -package se.scalablesolutions.akka.amqp.test - -import se.scalablesolutions.akka.util.Logging -import org.scalatest.junit.JUnitSuite -import se.scalablesolutions.akka.actor.Actor._ import org.multiverse.api.latches.StandardLatch import com.rabbitmq.client.ShutdownSignalException import se.scalablesolutions.akka.amqp._ @@ -15,8 +12,10 @@ import java.util.concurrent.TimeUnit import se.scalablesolutions.akka.actor.ActorRef import org.junit.Test import se.scalablesolutions.akka.amqp.AMQP._ +import org.scalatest.junit.JUnitSuite +import se.scalablesolutions.akka.actor.Actor._ -class AMQPConsumerChannelRecoveryTest extends JUnitSuite with MustMatchers with Logging { +class AMQPConsumerChannelRecoveryTest extends JUnitSuite with MustMatchers { @Test def consumerChannelRecovery = if (AMQPTest.enabled) { @@ -60,11 +59,4 @@ class AMQPConsumerChannelRecoveryTest extends JUnitSuite with MustMatchers with connection.stop } } - - @Test - def dummy { - // amqp tests need local rabbitmq server running, so a disabled by default. - // this dummy test makes sure that the whole test class doesn't fail because of missing tests - assert(true) - } } diff --git a/akka-amqp/src/test/scala/AMQPConsumerConnectionRecoveryTest.scala b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPConsumerConnectionRecoveryTest.scala similarity index 88% rename from akka-amqp/src/test/scala/AMQPConsumerConnectionRecoveryTest.scala rename to akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPConsumerConnectionRecoveryTest.scala index bf4885fea5..301489bd8f 100644 --- a/akka-amqp/src/test/scala/AMQPConsumerConnectionRecoveryTest.scala +++ b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPConsumerConnectionRecoveryTest.scala @@ -1,22 +1,21 @@ +package se.scalablesolutions.akka.amqp.test + /** * Copyright (C) 2009-2010 Scalable Solutions AB */ -package se.scalablesolutions.akka.amqp.test - -import se.scalablesolutions.akka.util.Logging -import org.scalatest.junit.JUnitSuite -import se.scalablesolutions.akka.actor.Actor._ import org.multiverse.api.latches.StandardLatch import com.rabbitmq.client.ShutdownSignalException import se.scalablesolutions.akka.amqp._ import org.scalatest.matchers.MustMatchers import java.util.concurrent.TimeUnit -import se.scalablesolutions.akka.actor.ActorRef import org.junit.Test import se.scalablesolutions.akka.amqp.AMQP._ +import org.scalatest.junit.JUnitSuite +import se.scalablesolutions.akka.actor.{Actor, ActorRef} +import Actor._ -class AMQPConsumerConnectionRecoveryTest extends JUnitSuite with MustMatchers with Logging { +class AMQPConsumerConnectionRecoveryTest extends JUnitSuite with MustMatchers { @Test def consumerConnectionRecovery = if (AMQPTest.enabled) { @@ -79,11 +78,4 @@ class AMQPConsumerConnectionRecoveryTest extends JUnitSuite with MustMatchers wi connection.stop } } - - @Test - def dummy { - // amqp tests need local rabbitmq server running, so a disabled by default. - // this dummy test makes sure that the whole test class doesn't fail because of missing tests - assert(true) - } } diff --git a/akka-amqp/src/test/scala/AMQPConsumerManualAcknowledgeTest.scala b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPConsumerManualAcknowledgeTest.scala similarity index 88% rename from akka-amqp/src/test/scala/AMQPConsumerManualAcknowledgeTest.scala rename to akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPConsumerManualAcknowledgeTest.scala index 2dc4ee939b..a18db40d5f 100644 --- a/akka-amqp/src/test/scala/AMQPConsumerManualAcknowledgeTest.scala +++ b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPConsumerManualAcknowledgeTest.scala @@ -1,12 +1,9 @@ +package se.scalablesolutions.akka.amqp.test + /** * Copyright (C) 2009-2010 Scalable Solutions AB */ -package se.scalablesolutions.akka.amqp.test - -import se.scalablesolutions.akka.util.Logging -import org.scalatest.junit.JUnitSuite -import org.multiverse.api.latches.StandardLatch import se.scalablesolutions.akka.actor.Actor._ import org.scalatest.matchers.MustMatchers import se.scalablesolutions.akka.amqp._ @@ -14,8 +11,10 @@ import org.junit.Test import se.scalablesolutions.akka.actor.ActorRef import java.util.concurrent.{CountDownLatch, TimeUnit} import se.scalablesolutions.akka.amqp.AMQP.{ExchangeParameters, ConsumerParameters, ChannelParameters, ProducerParameters} +import org.multiverse.api.latches.StandardLatch +import org.scalatest.junit.JUnitSuite -class AMQPConsumerManualAcknowledgeTest extends JUnitSuite with MustMatchers with Logging { +class AMQPConsumerManualAcknowledgeTest extends JUnitSuite with MustMatchers { @Test def consumerMessageManualAcknowledge = if (AMQPTest.enabled) { @@ -57,11 +56,4 @@ class AMQPConsumerManualAcknowledgeTest extends JUnitSuite with MustMatchers wit connection.stop } } - - @Test - def dummy { - // amqp tests need local rabbitmq server running, so a disabled by default. - // this dummy test makes sure that the whole test class doesn't fail because of missing tests - assert(true) - } } diff --git a/akka-amqp/src/test/scala/AMQPConsumerMessageTest.scala b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPConsumerMessageTest.scala similarity index 86% rename from akka-amqp/src/test/scala/AMQPConsumerMessageTest.scala rename to akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPConsumerMessageTest.scala index 5d34f867d6..9eb7aa9158 100644 --- a/akka-amqp/src/test/scala/AMQPConsumerMessageTest.scala +++ b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPConsumerMessageTest.scala @@ -1,20 +1,19 @@ +package se.scalablesolutions.akka.amqp.test + /** * Copyright (C) 2009-2010 Scalable Solutions AB */ -package se.scalablesolutions.akka.amqp.test - -import se.scalablesolutions.akka.util.Logging -import org.scalatest.junit.JUnitSuite -import org.junit.Test import se.scalablesolutions.akka.amqp._ import org.multiverse.api.latches.StandardLatch import se.scalablesolutions.akka.actor.Actor._ import org.scalatest.matchers.MustMatchers import java.util.concurrent.{CountDownLatch, TimeUnit} import se.scalablesolutions.akka.amqp.AMQP.{ExchangeParameters, ConsumerParameters, ChannelParameters, ProducerParameters} +import org.scalatest.junit.JUnitSuite +import org.junit.Test -class AMQPConsumerMessageTest extends JUnitSuite with MustMatchers with Logging { +class AMQPConsumerMessageTest extends JUnitSuite with MustMatchers { @Test def consumerMessage = if (AMQPTest.enabled) { @@ -46,11 +45,4 @@ class AMQPConsumerMessageTest extends JUnitSuite with MustMatchers with Logging connection.stop } } - - @Test - def dummy { - // amqp tests need local rabbitmq server running, so a disabled by default. - // this dummy test makes sure that the whole test class doesn't fail because of missing tests - assert(true) - } } diff --git a/akka-amqp/src/test/scala/AMQPProducerChannelRecoveryTest.scala b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPProducerChannelRecoveryTest.scala similarity index 86% rename from akka-amqp/src/test/scala/AMQPProducerChannelRecoveryTest.scala rename to akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPProducerChannelRecoveryTest.scala index 26b2d78393..3aec05c122 100644 --- a/akka-amqp/src/test/scala/AMQPProducerChannelRecoveryTest.scala +++ b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPProducerChannelRecoveryTest.scala @@ -1,12 +1,9 @@ +package se.scalablesolutions.akka.amqp.test + /** * Copyright (C) 2009-2010 Scalable Solutions AB */ -package se.scalablesolutions.akka.amqp.test - -import se.scalablesolutions.akka.util.Logging -import org.scalatest.junit.JUnitSuite -import org.junit.Test import java.util.concurrent.TimeUnit import se.scalablesolutions.akka.actor.{Actor, ActorRef} import org.multiverse.api.latches.StandardLatch @@ -14,8 +11,10 @@ import com.rabbitmq.client.ShutdownSignalException import se.scalablesolutions.akka.amqp._ import org.scalatest.matchers.MustMatchers import se.scalablesolutions.akka.amqp.AMQP.{ExchangeParameters, ChannelParameters, ProducerParameters, ConnectionParameters} +import org.scalatest.junit.JUnitSuite +import org.junit.Test -class AMQPProducerChannelRecoveryTest extends JUnitSuite with MustMatchers with Logging { +class AMQPProducerChannelRecoveryTest extends JUnitSuite with MustMatchers { @Test def producerChannelRecovery = if (AMQPTest.enabled) { @@ -53,11 +52,4 @@ class AMQPProducerChannelRecoveryTest extends JUnitSuite with MustMatchers with connection.stop } } - - @Test - def dummy { - // amqp tests need local rabbitmq server running, so a disabled by default. - // this dummy test makes sure that the whole test class doesn't fail because of missing tests - assert(true) - } } diff --git a/akka-amqp/src/test/scala/AMQPProducerConnectionRecoveryTest.scala b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPProducerConnectionRecoveryTest.scala similarity index 86% rename from akka-amqp/src/test/scala/AMQPProducerConnectionRecoveryTest.scala rename to akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPProducerConnectionRecoveryTest.scala index fe8259b208..b1a4cc1027 100644 --- a/akka-amqp/src/test/scala/AMQPProducerConnectionRecoveryTest.scala +++ b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPProducerConnectionRecoveryTest.scala @@ -1,12 +1,9 @@ +package se.scalablesolutions.akka.amqp.test + /** * Copyright (C) 2009-2010 Scalable Solutions AB */ -package se.scalablesolutions.akka.amqp.test - -import se.scalablesolutions.akka.util.Logging -import org.scalatest.junit.JUnitSuite -import org.junit.Test import java.util.concurrent.TimeUnit import se.scalablesolutions.akka.actor.{Actor, ActorRef} import org.multiverse.api.latches.StandardLatch @@ -14,8 +11,10 @@ import com.rabbitmq.client.ShutdownSignalException import se.scalablesolutions.akka.amqp._ import org.scalatest.matchers.MustMatchers import se.scalablesolutions.akka.amqp.AMQP.{ExchangeParameters, ChannelParameters, ProducerParameters, ConnectionParameters} +import org.scalatest.junit.JUnitSuite +import org.junit.Test -class AMQPProducerConnectionRecoveryTest extends JUnitSuite with MustMatchers with Logging { +class AMQPProducerConnectionRecoveryTest extends JUnitSuite with MustMatchers { @Test def producerConnectionRecovery = if (AMQPTest.enabled) { @@ -52,11 +51,4 @@ class AMQPProducerConnectionRecoveryTest extends JUnitSuite with MustMatchers wi connection.stop } } - - @Test - def dummy { - // amqp tests need local rabbitmq server running, so a disabled by default. - // this dummy test makes sure that the whole test class doesn't fail because of missing tests - assert(true) - } } diff --git a/akka-amqp/src/test/scala/AMQPProducerMessageTest.scala b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPProducerMessageTest.scala similarity index 84% rename from akka-amqp/src/test/scala/AMQPProducerMessageTest.scala rename to akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPProducerMessageTest.scala index 5b19df351f..587f03ec92 100644 --- a/akka-amqp/src/test/scala/AMQPProducerMessageTest.scala +++ b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPProducerMessageTest.scala @@ -1,12 +1,9 @@ +package se.scalablesolutions.akka.amqp.test + /** * Copyright (C) 2009-2010 Scalable Solutions AB */ -package se.scalablesolutions.akka.amqp.test - -import se.scalablesolutions.akka.util.Logging -import org.scalatest.junit.JUnitSuite -import org.junit.Test import java.util.concurrent.TimeUnit import se.scalablesolutions.akka.actor.ActorRef import org.multiverse.api.latches.StandardLatch @@ -16,8 +13,10 @@ import com.rabbitmq.client.AMQP.BasicProperties import java.lang.String import org.scalatest.matchers.MustMatchers import se.scalablesolutions.akka.amqp.AMQP.{ExchangeParameters, ProducerParameters} +import org.scalatest.junit.JUnitSuite +import org.junit.Test -class AMQPProducerMessageTest extends JUnitSuite with MustMatchers with Logging { +class AMQPProducerMessageTest extends JUnitSuite with MustMatchers { @Test def producerMessage = if (AMQPTest.enabled) { @@ -41,11 +40,4 @@ class AMQPProducerMessageTest extends JUnitSuite with MustMatchers with Logging connection.stop } } - - @Test - def dummy { - // amqp tests need local rabbitmq server running, so a disabled by default. - // this dummy test makes sure that the whole test class doesn't fail because of missing tests - assert(true) - } } diff --git a/akka-amqp/src/test/scala/AMQPRpcClientServerTest.scala b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPRpcClientServerTest.scala similarity index 77% rename from akka-amqp/src/test/scala/AMQPRpcClientServerTest.scala rename to akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPRpcClientServerTest.scala index c585675098..bf0ee6610d 100644 --- a/akka-amqp/src/test/scala/AMQPRpcClientServerTest.scala +++ b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPRpcClientServerTest.scala @@ -1,19 +1,21 @@ +package se.scalablesolutions.akka.amqp.test + /** * Copyright (C) 2009-2010 Scalable Solutions AB */ -package se.scalablesolutions.akka.amqp.test - -import se.scalablesolutions.akka.util.Logging -import org.scalatest.junit.JUnitSuite -import org.junit.Test import se.scalablesolutions.akka.amqp._ +import rpc.RPC +import rpc.RPC.{RpcClientSerializer, RpcServerSerializer, FromBinary, ToBinary} import se.scalablesolutions.akka.actor.Actor._ import org.scalatest.matchers.MustMatchers import java.util.concurrent.{CountDownLatch, TimeUnit} import se.scalablesolutions.akka.amqp.AMQP._ +import org.scalatest.junit.JUnitSuite +import org.junit.Test -class AMQPRpcClientServerTest extends JUnitSuite with MustMatchers with Logging { +class AMQPRpcClientServerTest extends JUnitSuite with MustMatchers { + @Test def consumerMessage = if (AMQPTest.enabled) { val connection = AMQP.newConnection() @@ -39,7 +41,7 @@ class AMQPRpcClientServerTest extends JUnitSuite with MustMatchers with Logging def requestHandler(request: String) = 3 - val rpcServer = AMQP.newRpcServer[String, Int](connection, exchangeParameters, "rpc.routing", rpcServerSerializer, + val rpcServer = RPC.newRpcServer[String, Int](connection, exchangeParameters, "rpc.routing", rpcServerSerializer, requestHandler, channelParameters = Some(channelParameters)) val rpcClientSerializer = new RpcClientSerializer[String, Int]( @@ -49,7 +51,7 @@ class AMQPRpcClientServerTest extends JUnitSuite with MustMatchers with Logging def fromBinary(bytes: Array[Byte]) = bytes.head.toInt }) - val rpcClient = AMQP.newRpcClient[String, Int](connection, exchangeParameters, "rpc.routing", rpcClientSerializer, + val rpcClient = RPC.newRpcClient[String, Int](connection, exchangeParameters, "rpc.routing", rpcClientSerializer, channelParameters = Some(channelParameters)) countDown.await(2, TimeUnit.SECONDS) must be(true) @@ -59,11 +61,4 @@ class AMQPRpcClientServerTest extends JUnitSuite with MustMatchers with Logging connection.stop } } - - @Test - def dummy { - // amqp tests need local rabbitmq server running, so a disabled by default. - // this dummy test makes sure that the whole test class doesn't fail because of missing tests - assert(true) - } } diff --git a/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPRpcProtobufTest.scala b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPRpcProtobufTest.scala new file mode 100644 index 0000000000..b0ca3f8ffe --- /dev/null +++ b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPRpcProtobufTest.scala @@ -0,0 +1,35 @@ +package se.scalablesolutions.akka.amqp.test + +/** + * Copyright (C) 2009-2010 Scalable Solutions AB + */ +import org.scalatest.matchers.MustMatchers +import org.scalatest.junit.JUnitSuite +import se.scalablesolutions.akka.amqp.AMQP +import se.scalablesolutions.akka.remote.protocol.RemoteProtocol.AddressProtocol +import org.junit.Test +import se.scalablesolutions.akka.amqp.rpc.RPC + +class AMQPRpcProtobufTest extends JUnitSuite with MustMatchers { + + @Test + def consumerMessage = if (AMQPTest.enabled) { + + val connection = AMQP.newConnection() + + RPC.startProtobufServer(connection, "protoservice", requestHandler) + + val protobufClient = RPC.startProtobufClient[AddressProtocol, AddressProtocol](connection, "protoservice") + + val request = AddressProtocol.newBuilder.setHostname("testhost").setPort(4321).build + + protobufClient.callService(request) match { + case Some(response) => assert(response.getHostname == request.getHostname.reverse) + case None => fail("no response") + } + } + + def requestHandler(request: AddressProtocol): AddressProtocol = { + AddressProtocol.newBuilder.setHostname(request.getHostname.reverse).setPort(request.getPort).build + } +} \ No newline at end of file diff --git a/akka-amqp/src/test/scala/AMQPTest.scala b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPTest.scala similarity index 87% rename from akka-amqp/src/test/scala/AMQPTest.scala rename to akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPTest.scala index 5ff9157bc5..8cad27ba60 100644 --- a/akka-amqp/src/test/scala/AMQPTest.scala +++ b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPTest.scala @@ -5,5 +5,5 @@ package se.scalablesolutions.akka.amqp.test object AMQPTest { - def enabled = false + def enabled = true } diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 02f72d7f0e..7e3477027f 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -41,15 +41,15 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- object Repositories { - lazy val AkkaRepo = MavenRepository("Akka Repository", "http://scalablesolutions.se/akka/repository") - lazy val CodehausSnapshotRepo = MavenRepository("Codehaus Snapshots", "http://snapshots.repository.codehaus.org") +// lazy val AkkaRepo = MavenRepository("Akka Repository", "http://scalablesolutions.se/akka/repository") +// lazy val CodehausSnapshotRepo = MavenRepository("Codehaus Snapshots", "http://snapshots.repository.codehaus.org") lazy val EmbeddedRepo = MavenRepository("Embedded Repo", (info.projectPath / "embedded-repo").asURL.toString) - lazy val FusesourceSnapshotRepo = MavenRepository("Fusesource Snapshots", "http://repo.fusesource.com/nexus/content/repositories/snapshots") - lazy val GuiceyFruitRepo = MavenRepository("GuiceyFruit Repo", "http://guiceyfruit.googlecode.com/svn/repo/releases/") - lazy val JBossRepo = MavenRepository("JBoss Repo", "https://repository.jboss.org/nexus/content/groups/public/") - lazy val JavaNetRepo = MavenRepository("java.net Repo", "http://download.java.net/maven/2") - lazy val SonatypeSnapshotRepo = MavenRepository("Sonatype OSS Repo", "http://oss.sonatype.org/content/repositories/releases") - lazy val SunJDMKRepo = MavenRepository("Sun JDMK Repo", "http://wp5.e-taxonomy.eu/cdmlib/mavenrepo") +// lazy val FusesourceSnapshotRepo = MavenRepository("Fusesource Snapshots", "http://repo.fusesource.com/nexus/content/repositories/snapshots") +// lazy val GuiceyFruitRepo = MavenRepository("GuiceyFruit Repo", "http://guiceyfruit.googlecode.com/svn/repo/releases/") +// lazy val JBossRepo = MavenRepository("JBoss Repo", "https://repository.jboss.org/nexus/content/groups/public/") +// lazy val JavaNetRepo = MavenRepository("java.net Repo", "http://download.java.net/maven/2") +// lazy val SonatypeSnapshotRepo = MavenRepository("Sonatype OSS Repo", "http://oss.sonatype.org/content/repositories/releases") +// lazy val SunJDMKRepo = MavenRepository("Sun JDMK Repo", "http://wp5.e-taxonomy.eu/cdmlib/mavenrepo") } // ------------------------------------------------------------------------------------------------------------------- @@ -60,23 +60,26 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- import Repositories._ - lazy val atmosphereModuleConfig = ModuleConfiguration("org.atmosphere", SonatypeSnapshotRepo) - lazy val grizzlyModuleConfig = ModuleConfiguration("com.sun.grizzly", JavaNetRepo) - lazy val guiceyFruitModuleConfig = ModuleConfiguration("org.guiceyfruit", GuiceyFruitRepo) - // lazy val hawtdispatchModuleConfig = ModuleConfiguration("org.fusesource.hawtdispatch", FusesourceSnapshotRepo) - lazy val jbossModuleConfig = ModuleConfiguration("org.jboss", JBossRepo) - lazy val jdmkModuleConfig = ModuleConfiguration("com.sun.jdmk", SunJDMKRepo) - lazy val jerseyContrModuleConfig = ModuleConfiguration("com.sun.jersey.contribs", JavaNetRepo) - lazy val jerseyModuleConfig = ModuleConfiguration("com.sun.jersey", JavaNetRepo) - lazy val jgroupsModuleConfig = ModuleConfiguration("jgroups", JBossRepo) - lazy val jmsModuleConfig = ModuleConfiguration("javax.jms", SunJDMKRepo) - lazy val jmxModuleConfig = ModuleConfiguration("com.sun.jmx", SunJDMKRepo) - lazy val liftModuleConfig = ModuleConfiguration("net.liftweb", ScalaToolsSnapshots) - lazy val multiverseModuleConfig = ModuleConfiguration("org.multiverse", CodehausSnapshotRepo) - lazy val nettyModuleConfig = ModuleConfiguration("org.jboss.netty", JBossRepo) - lazy val scalaTestModuleConfig = ModuleConfiguration("org.scalatest", ScalaToolsSnapshots) +// lazy val atmosphereModuleConfig = ModuleConfiguration("org.atmosphere", SonatypeSnapshotRepo) +// lazy val grizzlyModuleConfig = ModuleConfiguration("com.sun.grizzly", JavaNetRepo) +// lazy val guiceyFruitModuleConfig = ModuleConfiguration("org.guiceyfruit", GuiceyFruitRepo) +// // lazy val hawtdispatchModuleConfig = ModuleConfiguration("org.fusesource.hawtdispatch", FusesourceSnapshotRepo) +// lazy val jbossModuleConfig = ModuleConfiguration("org.jboss", JBossRepo) +// lazy val jdmkModuleConfig = ModuleConfiguration("com.sun.jdmk", SunJDMKRepo) +// lazy val jerseyContrModuleConfig = ModuleConfiguration("com.sun.jersey.contribs", JavaNetRepo) +// lazy val jerseyModuleConfig = ModuleConfiguration("com.sun.jersey", JavaNetRepo) +// lazy val jgroupsModuleConfig = ModuleConfiguration("jgroups", JBossRepo) +// lazy val jmsModuleConfig = ModuleConfiguration("javax.jms", SunJDMKRepo) +// lazy val jmxModuleConfig = ModuleConfiguration("com.sun.jmx", SunJDMKRepo) +// lazy val liftModuleConfig = ModuleConfiguration("net.liftweb", ScalaToolsSnapshots) +// lazy val multiverseModuleConfig = ModuleConfiguration("org.multiverse", CodehausSnapshotRepo) +// lazy val nettyModuleConfig = ModuleConfiguration("org.jboss.netty", JBossRepo) +// lazy val scalaTestModuleConfig = ModuleConfiguration("org.scalatest", ScalaToolsSnapshots) lazy val embeddedRepo = EmbeddedRepo // This is the only exception, because the embedded repo is fast! + val mavenLocal = "Local Maven Repository" at "file:/e:/maven-repository" + val efgfpNexusReleasesRepository = "Nexus Releases" at "http://nexus/nexus/content/groups/public" + val efgfpNexusSnaphotsRepository = "Nexus Snapshots" at "http://nexus/nexus/content/groups/public-snapshots" // ------------------------------------------------------------------------------------------------------------------- // Versions // ------------------------------------------------------------------------------------------------------------------- @@ -358,6 +361,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { class AkkaAMQPProject(info: ProjectInfo) extends AkkaDefaultProject(info, distPath) with CodeFellowPlugin { val commons_io = Dependencies.commons_io val rabbit = Dependencies.rabbit + val protobuf = Dependencies.protobuf // testing val junit = Dependencies.junit From 533319d6679a28f9caec3b377344b4c41faac30a Mon Sep 17 00:00:00 2001 From: momania Date: Fri, 6 Aug 2010 17:32:01 +0200 Subject: [PATCH 099/188] disable ampq tests --- .../scala/se/scalablesolutions/akka/amqp/test/AMQPTest.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPTest.scala b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPTest.scala index 8cad27ba60..5ff9157bc5 100644 --- a/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPTest.scala +++ b/akka-amqp/src/test/scala/se/scalablesolutions/akka/amqp/test/AMQPTest.scala @@ -5,5 +5,5 @@ package se.scalablesolutions.akka.amqp.test object AMQPTest { - def enabled = true + def enabled = false } From b1fe483c53fcf77da6ac917cb85615692eb7b981 Mon Sep 17 00:00:00 2001 From: momania Date: Fri, 6 Aug 2010 17:33:55 +0200 Subject: [PATCH 100/188] remove rpcclient trait... --- .../scala/se/scalablesolutions/akka/amqp/rpc/RPC.scala | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/rpc/RPC.scala b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/rpc/RPC.scala index a711a01cc5..3097e64cd9 100644 --- a/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/rpc/RPC.scala +++ b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/rpc/RPC.scala @@ -52,11 +52,7 @@ object RPC { /** * RPC convenience */ - trait RpcClient[O, I] { - def callService(request: O, timeout: Long = 5000): Option[I] - } - - private class RpcServiceClient[O, I](client: ActorRef) extends RpcClient[O, I] { + class RpcClient[O, I](client: ActorRef){ def callService(request: O, timeout: Long = 5000): Option[I] = { (client.!!(request, timeout)).as[I] } @@ -101,7 +97,7 @@ object RPC { val queueName = "%s.in".format(routingKey) val client = newRpcClient[O, I](connection, exchangeParameters, routingKey, serializer) - new RpcServiceClient[O, I](client) + new RpcClient[O, I](client) } private def createProtobufFromBytes[I](bytes: Array[Byte])(implicit manifest: Manifest[I]): I = { From bc7326e9d65ee3831ba15c7eadaafbb4764192da Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 9 Aug 2010 09:35:41 +0200 Subject: [PATCH 101/188] Closing ticket 370 --- project/build/AkkaProject.scala | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index c247f475af..1317756b2b 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -628,6 +628,7 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { val junit = Dependencies.junit def deployPath = AkkaParentProject.this.deployPath + override def jarPath = warPath } class AkkaSampleRestJavaProject(info: ProjectInfo) extends AkkaDefaultProject(info, deployPath) with CodeFellowPlugin @@ -723,27 +724,28 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------ class AkkaDefaultProject(info: ProjectInfo, val deployPath: Path) extends DefaultProject(info) with DeployProject with OSGiProject - trait DeployProject { self: Project => +} + + trait DeployProject { self: BasicScalaProject => // defines where the deployTask copies jars to def deployPath: Path - lazy val dist = distAction - def distAction = deployTask(jarPath, packageDocsJar, packageSrcJar, deployPath, true, true, true) dependsOn( + lazy val dist = deployTask(jarPath, packageDocsJar, packageSrcJar, deployPath, true, true, true) dependsOn( `package`, packageDocs, packageSrc) describedAs("Deploying") def deployTask(jar: Path, docs: Path, src: Path, toDir: Path, genJar: Boolean, genDocs: Boolean, genSource: Boolean) = task { - gen(jar, toDir, genJar, "Deploying bits") orElse - gen(docs, toDir, genDocs, "Deploying docs") orElse - gen(src, toDir, genSource, "Deploying sources") - } - private def gen(jar: Path, toDir: Path, flag: Boolean, msg: String): Option[String] = + def gen(jar: Path, toDir: Path, flag: Boolean, msg: String): Option[String] = if (flag) { log.info(msg + " " + jar) FileUtilities.copyFile(jar, toDir / jar.name, log) } else None + + gen(jar, toDir, genJar, "Deploying bits") orElse + gen(docs, toDir, genDocs, "Deploying docs") orElse + gen(src, toDir, genSource, "Deploying sources") + } } - trait OSGiProject extends DefaultProject with BNDPlugin { + trait OSGiProject extends BNDPlugin { self: DefaultProject => override def bndExportPackage = Seq("se.scalablesolutions.akka.*;version=%s".format(projectVersion.value)) - } -} + } \ No newline at end of file From d41f64df2fa1510a010dc72eae76a76e0b0bf69c Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 9 Aug 2010 10:09:26 +0200 Subject: [PATCH 102/188] Formatting --- project/build/AkkaProject.scala | 39 ++++++++++++++++----------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 1317756b2b..9ffd653496 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -723,29 +723,28 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------ class AkkaDefaultProject(info: ProjectInfo, val deployPath: Path) extends DefaultProject(info) with DeployProject with OSGiProject - } - trait DeployProject { self: BasicScalaProject => - // defines where the deployTask copies jars to - def deployPath: Path +trait DeployProject { self: BasicScalaProject => + // defines where the deployTask copies jars to + def deployPath: Path - lazy val dist = deployTask(jarPath, packageDocsJar, packageSrcJar, deployPath, true, true, true) dependsOn( - `package`, packageDocs, packageSrc) describedAs("Deploying") - def deployTask(jar: Path, docs: Path, src: Path, toDir: Path, - genJar: Boolean, genDocs: Boolean, genSource: Boolean) = task { - def gen(jar: Path, toDir: Path, flag: Boolean, msg: String): Option[String] = - if (flag) { - log.info(msg + " " + jar) - FileUtilities.copyFile(jar, toDir / jar.name, log) - } else None + lazy val dist = deployTask(jarPath, packageDocsJar, packageSrcJar, deployPath, true, true, true) dependsOn( + `package`, packageDocs, packageSrc) describedAs("Deploying") + def deployTask(jar: Path, docs: Path, src: Path, toDir: Path, + genJar: Boolean, genDocs: Boolean, genSource: Boolean) = task { + def gen(jar: Path, toDir: Path, flag: Boolean, msg: String): Option[String] = + if (flag) { + log.info(msg + " " + jar) + FileUtilities.copyFile(jar, toDir / jar.name, log) + } else None - gen(jar, toDir, genJar, "Deploying bits") orElse - gen(docs, toDir, genDocs, "Deploying docs") orElse - gen(src, toDir, genSource, "Deploying sources") - } + gen(jar, toDir, genJar, "Deploying bits") orElse + gen(docs, toDir, genDocs, "Deploying docs") orElse + gen(src, toDir, genSource, "Deploying sources") } +} - trait OSGiProject extends BNDPlugin { self: DefaultProject => - override def bndExportPackage = Seq("se.scalablesolutions.akka.*;version=%s".format(projectVersion.value)) - } \ No newline at end of file +trait OSGiProject extends BNDPlugin { self: DefaultProject => + override def bndExportPackage = Seq("se.scalablesolutions.akka.*;version=%s".format(projectVersion.value)) +} \ No newline at end of file From 75c2c147eec9001e06c9d3df6eb6f0a98376b574 Mon Sep 17 00:00:00 2001 From: momania Date: Mon, 9 Aug 2010 10:28:19 +0200 Subject: [PATCH 103/188] added optional routingkey and queuename to parameters --- .../scalablesolutions/akka/amqp/rpc/RPC.scala | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/rpc/RPC.scala b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/rpc/RPC.scala index 3097e64cd9..26887dbff4 100644 --- a/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/rpc/RPC.scala +++ b/akka-amqp/src/main/scala/se/scalablesolutions/akka/amqp/rpc/RPC.scala @@ -61,7 +61,9 @@ object RPC { private val ARRAY_OF_BYTE_ARRAY = Array[Class[_]](classOf[Array[Byte]]) def startProtobufServer[I <: Message, O <: Message]( - connection: ActorRef, serviceName: String, requestHandler: I => O)(implicit manifest: Manifest[I]) = { + connection: ActorRef, exchange: String, requestHandler: I => O, + routingKey: Option[String] = None, + queueName: Option[String] = None)(implicit manifest: Manifest[I]) = { val serializer = new RpcServerSerializer[I, O]( new FromBinary[I] { @@ -72,16 +74,18 @@ object RPC { def toBinary(t: O) = t.toByteArray }) - val exchangeParameters = new ExchangeParameters(serviceName, ExchangeType.Topic) - val routingKey = "%s.request".format(serviceName) - val queueName = "%s.in".format(routingKey) + val exchangeParameters = new ExchangeParameters(exchange, ExchangeType.Topic) + val rKey = routingKey.getOrElse("%s.request".format(exchange)) + val qName = queueName.getOrElse("%s.in".format(rKey)) - newRpcServer[I, O](connection, exchangeParameters, routingKey, serializer, requestHandler, - queueName = Some(queueName)) + newRpcServer[I, O](connection, exchangeParameters, rKey, serializer, requestHandler, + queueName = Some(qName)) } def startProtobufClient[O <: Message, I <: Message]( - connection: ActorRef, serviceName: String)(implicit manifest: Manifest[I]): RpcClient[O, I] = { + connection: ActorRef, exchange: String, + routingKey: Option[String] = None)(implicit manifest: Manifest[I]): RpcClient[O, I] = { + val serializer = new RpcClientSerializer[O, I]( new ToBinary[O] { @@ -92,11 +96,10 @@ object RPC { } }) - val exchangeParameters = new ExchangeParameters(serviceName, ExchangeType.Topic) - val routingKey = "%s.request".format(serviceName) - val queueName = "%s.in".format(routingKey) + val exchangeParameters = new ExchangeParameters(exchange, ExchangeType.Topic) + val rKey = routingKey.getOrElse("%s.request".format(exchange)) - val client = newRpcClient[O, I](connection, exchangeParameters, routingKey, serializer) + val client = newRpcClient[O, I](connection, exchangeParameters, rKey, serializer) new RpcClient[O, I](client) } From 6a586d1198373becf9ca6f7fa99a249f9c45ff34 Mon Sep 17 00:00:00 2001 From: momania Date: Mon, 9 Aug 2010 10:42:00 +0200 Subject: [PATCH 104/188] undo local repo settings (for the 25953467296th time :S ) --- project/build/AkkaProject.scala | 49 ++++++++++++++++----------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/project/build/AkkaProject.scala b/project/build/AkkaProject.scala index 7e3477027f..bf1e9e6478 100644 --- a/project/build/AkkaProject.scala +++ b/project/build/AkkaProject.scala @@ -41,15 +41,15 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- object Repositories { -// lazy val AkkaRepo = MavenRepository("Akka Repository", "http://scalablesolutions.se/akka/repository") -// lazy val CodehausSnapshotRepo = MavenRepository("Codehaus Snapshots", "http://snapshots.repository.codehaus.org") + lazy val AkkaRepo = MavenRepository("Akka Repository", "http://scalablesolutions.se/akka/repository") + lazy val CodehausSnapshotRepo = MavenRepository("Codehaus Snapshots", "http://snapshots.repository.codehaus.org") lazy val EmbeddedRepo = MavenRepository("Embedded Repo", (info.projectPath / "embedded-repo").asURL.toString) -// lazy val FusesourceSnapshotRepo = MavenRepository("Fusesource Snapshots", "http://repo.fusesource.com/nexus/content/repositories/snapshots") -// lazy val GuiceyFruitRepo = MavenRepository("GuiceyFruit Repo", "http://guiceyfruit.googlecode.com/svn/repo/releases/") -// lazy val JBossRepo = MavenRepository("JBoss Repo", "https://repository.jboss.org/nexus/content/groups/public/") -// lazy val JavaNetRepo = MavenRepository("java.net Repo", "http://download.java.net/maven/2") -// lazy val SonatypeSnapshotRepo = MavenRepository("Sonatype OSS Repo", "http://oss.sonatype.org/content/repositories/releases") -// lazy val SunJDMKRepo = MavenRepository("Sun JDMK Repo", "http://wp5.e-taxonomy.eu/cdmlib/mavenrepo") + lazy val FusesourceSnapshotRepo = MavenRepository("Fusesource Snapshots", "http://repo.fusesource.com/nexus/content/repositories/snapshots") + lazy val GuiceyFruitRepo = MavenRepository("GuiceyFruit Repo", "http://guiceyfruit.googlecode.com/svn/repo/releases/") + lazy val JBossRepo = MavenRepository("JBoss Repo", "https://repository.jboss.org/nexus/content/groups/public/") + lazy val JavaNetRepo = MavenRepository("java.net Repo", "http://download.java.net/maven/2") + lazy val SonatypeSnapshotRepo = MavenRepository("Sonatype OSS Repo", "http://oss.sonatype.org/content/repositories/releases") + lazy val SunJDMKRepo = MavenRepository("Sun JDMK Repo", "http://wp5.e-taxonomy.eu/cdmlib/mavenrepo") } // ------------------------------------------------------------------------------------------------------------------- @@ -60,26 +60,23 @@ class AkkaParentProject(info: ProjectInfo) extends DefaultProject(info) { // ------------------------------------------------------------------------------------------------------------------- import Repositories._ -// lazy val atmosphereModuleConfig = ModuleConfiguration("org.atmosphere", SonatypeSnapshotRepo) -// lazy val grizzlyModuleConfig = ModuleConfiguration("com.sun.grizzly", JavaNetRepo) -// lazy val guiceyFruitModuleConfig = ModuleConfiguration("org.guiceyfruit", GuiceyFruitRepo) -// // lazy val hawtdispatchModuleConfig = ModuleConfiguration("org.fusesource.hawtdispatch", FusesourceSnapshotRepo) -// lazy val jbossModuleConfig = ModuleConfiguration("org.jboss", JBossRepo) -// lazy val jdmkModuleConfig = ModuleConfiguration("com.sun.jdmk", SunJDMKRepo) -// lazy val jerseyContrModuleConfig = ModuleConfiguration("com.sun.jersey.contribs", JavaNetRepo) -// lazy val jerseyModuleConfig = ModuleConfiguration("com.sun.jersey", JavaNetRepo) -// lazy val jgroupsModuleConfig = ModuleConfiguration("jgroups", JBossRepo) -// lazy val jmsModuleConfig = ModuleConfiguration("javax.jms", SunJDMKRepo) -// lazy val jmxModuleConfig = ModuleConfiguration("com.sun.jmx", SunJDMKRepo) -// lazy val liftModuleConfig = ModuleConfiguration("net.liftweb", ScalaToolsSnapshots) -// lazy val multiverseModuleConfig = ModuleConfiguration("org.multiverse", CodehausSnapshotRepo) -// lazy val nettyModuleConfig = ModuleConfiguration("org.jboss.netty", JBossRepo) -// lazy val scalaTestModuleConfig = ModuleConfiguration("org.scalatest", ScalaToolsSnapshots) + lazy val atmosphereModuleConfig = ModuleConfiguration("org.atmosphere", SonatypeSnapshotRepo) + lazy val grizzlyModuleConfig = ModuleConfiguration("com.sun.grizzly", JavaNetRepo) + lazy val guiceyFruitModuleConfig = ModuleConfiguration("org.guiceyfruit", GuiceyFruitRepo) + // lazy val hawtdispatchModuleConfig = ModuleConfiguration("org.fusesource.hawtdispatch", FusesourceSnapshotRepo) + lazy val jbossModuleConfig = ModuleConfiguration("org.jboss", JBossRepo) + lazy val jdmkModuleConfig = ModuleConfiguration("com.sun.jdmk", SunJDMKRepo) + lazy val jerseyContrModuleConfig = ModuleConfiguration("com.sun.jersey.contribs", JavaNetRepo) + lazy val jerseyModuleConfig = ModuleConfiguration("com.sun.jersey", JavaNetRepo) + lazy val jgroupsModuleConfig = ModuleConfiguration("jgroups", JBossRepo) + lazy val jmsModuleConfig = ModuleConfiguration("javax.jms", SunJDMKRepo) + lazy val jmxModuleConfig = ModuleConfiguration("com.sun.jmx", SunJDMKRepo) + lazy val liftModuleConfig = ModuleConfiguration("net.liftweb", ScalaToolsSnapshots) + lazy val multiverseModuleConfig = ModuleConfiguration("org.multiverse", CodehausSnapshotRepo) + lazy val nettyModuleConfig = ModuleConfiguration("org.jboss.netty", JBossRepo) + lazy val scalaTestModuleConfig = ModuleConfiguration("org.scalatest", ScalaToolsSnapshots) lazy val embeddedRepo = EmbeddedRepo // This is the only exception, because the embedded repo is fast! - val mavenLocal = "Local Maven Repository" at "file:/e:/maven-repository" - val efgfpNexusReleasesRepository = "Nexus Releases" at "http://nexus/nexus/content/groups/public" - val efgfpNexusSnaphotsRepository = "Nexus Snapshots" at "http://nexus/nexus/content/groups/public-snapshots" // ------------------------------------------------------------------------------------------------------------------- // Versions // ------------------------------------------------------------------------------------------------------------------- From 6f42eee6089d886011554c679246529e6cb859f6 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 9 Aug 2010 11:36:56 +0200 Subject: [PATCH 105/188] Removed if*-methods and improved performance for arg-less logging --- akka-core/src/main/scala/actor/ActorRef.scala | 6 +- .../src/main/scala/actor/TypedActor.scala | 4 +- akka-core/src/main/scala/stm/JTA.scala | 6 +- .../src/main/scala/stm/Transaction.scala | 8 +- .../scala/stm/TransactionManagement.scala | 4 +- akka-core/src/main/scala/util/Logging.scala | 107 ++++++++++-------- 6 files changed, 72 insertions(+), 63 deletions(-) diff --git a/akka-core/src/main/scala/actor/ActorRef.scala b/akka-core/src/main/scala/actor/ActorRef.scala index 2fd205edeb..902943f24d 100644 --- a/akka-core/src/main/scala/actor/ActorRef.scala +++ b/akka-core/src/main/scala/actor/ActorRef.scala @@ -1101,7 +1101,7 @@ class LocalActorRef private[akka]( clearTransactionSet createNewTransactionSet } else oldTxSet - Actor.log.ifTrace("Joining transaction set [" + currentTxSet + + Actor.log.trace("Joining transaction set [" + currentTxSet + "];\n\tactor " + toString + "\n\twith message [" + message + "]") val mtx = ThreadLocalTransaction.getThreadLocalTransaction @@ -1110,7 +1110,7 @@ class LocalActorRef private[akka]( } private def dispatch[T](messageHandle: MessageInvocation) = { - Actor.log.ifTrace("Invoking actor with message:\n" + messageHandle) + Actor.log.trace("Invoking actor with message:\n" + messageHandle) val message = messageHandle.message //serializeMessage(messageHandle.message) var topLevelTransaction = false val txSet: Option[CountDownCommitBarrier] = @@ -1118,7 +1118,7 @@ class LocalActorRef private[akka]( else { topLevelTransaction = true // FIXME create a new internal atomic block that can wait for X seconds if top level tx if (isTransactor) { - Actor.log.ifTrace("Creating a new transaction set (top-level transaction)\n\tfor actor " + toString + + Actor.log.trace("Creating a new transaction set (top-level transaction)\n\tfor actor " + toString + "\n\twith message " + messageHandle) Some(createNewTransactionSet) } else None diff --git a/akka-core/src/main/scala/actor/TypedActor.scala b/akka-core/src/main/scala/actor/TypedActor.scala index ae72da4d70..9c68a7dc01 100644 --- a/akka-core/src/main/scala/actor/TypedActor.scala +++ b/akka-core/src/main/scala/actor/TypedActor.scala @@ -449,7 +449,7 @@ object TypedActor extends Logging { val parent = clazz.getSuperclass if (parent != null) injectTypedActorContext0(typedActor, parent) else { - log.ifTrace("Can't set 'TypedActorContext' for TypedActor [" + + log.trace("Can't set 'TypedActorContext' for TypedActor [" + typedActor.getClass.getName + "] since no field of this type could be found.") None @@ -728,7 +728,7 @@ private[akka] class Dispatcher(transactionalRequired: Boolean) extends Actor { def receive = { case invocation @ Invocation(joinPoint, isOneWay, _, sender, senderFuture) => - TypedActor.log.ifTrace("Invoking Typed Actor with message:\n" + invocation) + TypedActor.log.trace("Invoking Typed Actor with message:\n" + invocation) context.foreach { ctx => if (sender ne null) ctx._sender = sender if (senderFuture ne null) ctx._senderFuture = senderFuture diff --git a/akka-core/src/main/scala/stm/JTA.scala b/akka-core/src/main/scala/stm/JTA.scala index 1c0af88d73..0fb10af4f0 100644 --- a/akka-core/src/main/scala/stm/JTA.scala +++ b/akka-core/src/main/scala/stm/JTA.scala @@ -122,7 +122,7 @@ class TransactionContainer private (val tm: Either[Option[UserTransaction], Opti } def begin = { - TransactionContainer.log.ifTrace("Starting JTA transaction") + TransactionContainer.log.trace("Starting JTA transaction") tm match { case Left(Some(userTx)) => userTx.begin case Right(Some(txMan)) => txMan.begin @@ -131,7 +131,7 @@ class TransactionContainer private (val tm: Either[Option[UserTransaction], Opti } def commit = { - TransactionContainer.log.ifTrace("Committing JTA transaction") + TransactionContainer.log.trace("Committing JTA transaction") tm match { case Left(Some(userTx)) => userTx.commit case Right(Some(txMan)) => txMan.commit @@ -140,7 +140,7 @@ class TransactionContainer private (val tm: Either[Option[UserTransaction], Opti } def rollback = { - TransactionContainer.log.ifTrace("Aborting JTA transaction") + TransactionContainer.log.trace("Aborting JTA transaction") tm match { case Left(Some(userTx)) => userTx.rollback case Right(Some(txMan)) => txMan.rollback diff --git a/akka-core/src/main/scala/stm/Transaction.scala b/akka-core/src/main/scala/stm/Transaction.scala index 0951cbc5c5..a0e2077155 100644 --- a/akka-core/src/main/scala/stm/Transaction.scala +++ b/akka-core/src/main/scala/stm/Transaction.scala @@ -83,12 +83,12 @@ object Transaction { if (JTA_AWARE) Some(TransactionContainer()) else None - log.ifTrace("Creating transaction " + toString) + log.trace("Creating transaction " + toString) // --- public methods --------- def begin = synchronized { - log.ifTrace("Starting transaction " + toString) + log.trace("Starting transaction " + toString) jta.foreach { txContainer => txContainer.begin txContainer.registerSynchronization(new StmSynchronization(txContainer, this)) @@ -96,14 +96,14 @@ object Transaction { } def commit = synchronized { - log.ifTrace("Committing transaction " + toString) + log.trace("Committing transaction " + toString) persistentStateMap.valuesIterator.foreach(_.commit) status = TransactionStatus.Completed jta.foreach(_.commit) } def abort = synchronized { - log.ifTrace("Aborting transaction " + toString) + log.trace("Aborting transaction " + toString) jta.foreach(_.rollback) persistentStateMap.valuesIterator.foreach(_.abort) persistentStateMap.clear diff --git a/akka-core/src/main/scala/stm/TransactionManagement.scala b/akka-core/src/main/scala/stm/TransactionManagement.scala index 65f8d7624c..83bb5f1323 100644 --- a/akka-core/src/main/scala/stm/TransactionManagement.scala +++ b/akka-core/src/main/scala/stm/TransactionManagement.scala @@ -120,7 +120,7 @@ class LocalStm extends TransactionManagement with Logging { def call(mtx: MultiverseTransaction): T = { factory.addHooks val result = body - log.ifTrace("Committing local transaction [" + mtx + "]") + log.trace("Committing local transaction [" + mtx + "]") result } }) @@ -155,7 +155,7 @@ class GlobalStm extends TransactionManagement with Logging { factory.addHooks val result = body val txSet = getTransactionSetInScope - log.ifTrace("Committing global transaction [" + mtx + "]\n\tand joining transaction set [" + txSet + "]") + log.trace("Committing global transaction [" + mtx + "]\n\tand joining transaction set [" + txSet + "]") try { txSet.tryJoinCommit( mtx, diff --git a/akka-core/src/main/scala/util/Logging.scala b/akka-core/src/main/scala/util/Logging.scala index 9be0ba6087..159511f2cc 100644 --- a/akka-core/src/main/scala/util/Logging.scala +++ b/akka-core/src/main/scala/util/Logging.scala @@ -29,6 +29,8 @@ trait Logging { * log.info("My foo is %s","alive") * log.error(new Exception(),"My foo is %s","broken") * } + * + * The if*-methods do not take vararg parameters, and are therefor faster */ class Logger(val logger: SLFLogger) { @@ -41,85 +43,91 @@ class Logger(val logger: SLFLogger) def error_? = logger.isErrorEnabled //Trace - def trace(t: => Throwable,msg: => String,args: Any*){ - ifTrace(t,message(msg,args:_*)) + def trace(t: Throwable, fmt: => String, arg: Any, argN: Any*){ + trace(t,message(fmt,arg,argN)) } - def trace(msg: => String,args: Any*){ - ifTrace(message(msg,args:_*)) - } - - def ifTrace(msg: => String): Unit = if (trace_?) logger trace msg - - def ifTrace(t: => Throwable,msg: => String): Unit = { + def trace(t: Throwable, msg: => String){ if(trace_?) logger.trace(msg,t) } + def trace(fmt: => String, arg: Any, argN: Any*){ + trace(message(fmt,arg,argN)) + } + + def trace(msg: => String){ + if(trace_?) logger trace msg + } //Debug - def debug(t: => Throwable,msg: => String,args: Any*){ - ifDebug(t,message(msg,args:_*)) + def debug(t: Throwable, fmt: => String, arg: Any, argN: Any*){ + debug(t,message(fmt,arg,argN)) } - def debug(msg: => String,args: Any*){ - ifDebug(message(msg,args:_*)) - } - - def ifDebug(msg: => String): Unit = if (debug_?) logger debug msg - - def ifDebug(t: => Throwable,msg: => String): Unit = { + def debug(t: Throwable, msg: => String){ if(debug_?) logger.debug(msg,t) } + def debug(fmt: => String, arg: Any, argN: Any*){ + debug(message(fmt,arg,argN)) + } + + def debug(msg: => String){ + if(debug_?) logger debug msg + } //Info - def info(t: => Throwable,msg: => String,args: Any*){ - ifInfo(t,message(msg,args:_*)) + def info(t: Throwable, fmt: => String, arg: Any, argN: Any*){ + info(t,message(fmt,arg,argN)) } - def info(msg: => String,args: Any*){ - ifInfo(message(msg,args:_*)) - } - - def ifInfo(msg: => String): Unit = if (info_?) logger info msg - - def ifInfo(t: => Throwable,msg: => String): Unit = { + def info(t: Throwable, msg: => String){ if(info_?) logger.info(msg,t) } + def info(fmt: => String, arg: Any, argN: Any*){ + info(message(fmt,arg,argN)) + } + + def info(msg: => String){ + if(info_?) logger info msg + } //Warning - def warning(t: => Throwable,msg: => String,args: Any*){ - ifWarning(t,message(msg,args:_*)) + def warning(t: Throwable, fmt: => String, arg: Any, argN: Any*){ + warning(t,message(fmt,arg,argN)) } - def warning(msg: => String,args: Any*){ - ifWarning(message(msg,args:_*)) - } - - def ifWarning(msg: => String): Unit = if (warning_?) logger warn msg - - def ifWarning(t: => Throwable,msg: => String): Unit = { + def warning(t: Throwable, msg: => String){ if(warning_?) logger.warn(msg,t) } + def warning(fmt: => String, arg: Any, argN: Any*){ + warning(message(fmt,arg,argN)) + } + + def warning(msg: => String){ + if(warning_?) logger warn msg + } //Error - def error(t: => Throwable,msg: => String,args: Any*){ - ifError(t,message(msg,args:_*)) + def error(t: Throwable, fmt: => String, arg: Any, argN: Any*){ + error(t,message(fmt,arg,argN)) } - def error(msg: => String,args: Any*){ - ifError(message(msg,args:_*)) - } - - def ifError(msg: => String): Unit = if (error_?) logger error msg - - def ifError(t: => Throwable,msg: => String): Unit = { + def error(t: Throwable, msg: => String){ if(error_?) logger.error(msg,t) } - protected def message(msg: String, args: Any*) : String = { - if(args.isEmpty || (args eq null)) - msg + def error(fmt: => String, arg: Any, argN: Any*){ + error(message(fmt,arg,argN)) + } + + def error(msg: => String){ + if(error_?) logger error msg + } + + protected def message(msg: String,arg: Any, argN: Any*) : String = { + if((argN eq null) || argN.isEmpty) + msg.format(arg) else - msg.format(args:_*) + msg.format((arg +: argN):_*) } } @@ -131,6 +139,7 @@ class Logger(val logger: SLFLogger) * val logger = Logger("my.cool.logger") * val logger = Logger(classOf[Banana]) * val rootLogger = Logger.root + * */ object Logger { From d99e566004a100fb7beae6fb657a86c8cf68eda0 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 9 Aug 2010 11:48:23 +0200 Subject: [PATCH 106/188] Updated docs --- akka-core/src/main/scala/util/Logging.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/akka-core/src/main/scala/util/Logging.scala b/akka-core/src/main/scala/util/Logging.scala index 159511f2cc..d211c2b5da 100644 --- a/akka-core/src/main/scala/util/Logging.scala +++ b/akka-core/src/main/scala/util/Logging.scala @@ -30,7 +30,8 @@ trait Logging { * log.error(new Exception(),"My foo is %s","broken") * } * - * The if*-methods do not take vararg parameters, and are therefor faster + * The logger uses String.format: + * http://download-llnw.oracle.com/javase/6/docs/api/java/lang/String.html#format(java.lang.String,%20java.lang.Object...) */ class Logger(val logger: SLFLogger) { From 6d41299c61265dfcba2f4613d6d517a432616ced Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 9 Aug 2010 14:18:18 +0200 Subject: [PATCH 107/188] The unborkening --- akka-core/src/main/scala/util/Logging.scala | 26 ++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/akka-core/src/main/scala/util/Logging.scala b/akka-core/src/main/scala/util/Logging.scala index d211c2b5da..59f3848f5d 100644 --- a/akka-core/src/main/scala/util/Logging.scala +++ b/akka-core/src/main/scala/util/Logging.scala @@ -45,7 +45,7 @@ class Logger(val logger: SLFLogger) //Trace def trace(t: Throwable, fmt: => String, arg: Any, argN: Any*){ - trace(t,message(fmt,arg,argN)) + trace(t,message(fmt,arg,argN:_*)) } def trace(t: Throwable, msg: => String){ @@ -53,7 +53,7 @@ class Logger(val logger: SLFLogger) } def trace(fmt: => String, arg: Any, argN: Any*){ - trace(message(fmt,arg,argN)) + trace(message(fmt,arg,argN:_*)) } def trace(msg: => String){ @@ -61,7 +61,7 @@ class Logger(val logger: SLFLogger) } //Debug def debug(t: Throwable, fmt: => String, arg: Any, argN: Any*){ - debug(t,message(fmt,arg,argN)) + debug(t,message(fmt,arg,argN:_*)) } def debug(t: Throwable, msg: => String){ @@ -69,7 +69,7 @@ class Logger(val logger: SLFLogger) } def debug(fmt: => String, arg: Any, argN: Any*){ - debug(message(fmt,arg,argN)) + debug(message(fmt,arg,argN:_*)) } def debug(msg: => String){ @@ -77,7 +77,7 @@ class Logger(val logger: SLFLogger) } //Info def info(t: Throwable, fmt: => String, arg: Any, argN: Any*){ - info(t,message(fmt,arg,argN)) + info(t,message(fmt,arg,argN:_*)) } def info(t: Throwable, msg: => String){ @@ -85,7 +85,7 @@ class Logger(val logger: SLFLogger) } def info(fmt: => String, arg: Any, argN: Any*){ - info(message(fmt,arg,argN)) + info(message(fmt,arg,argN:_*)) } def info(msg: => String){ @@ -93,7 +93,7 @@ class Logger(val logger: SLFLogger) } //Warning def warning(t: Throwable, fmt: => String, arg: Any, argN: Any*){ - warning(t,message(fmt,arg,argN)) + warning(t,message(fmt,arg,argN:_*)) } def warning(t: Throwable, msg: => String){ @@ -101,7 +101,7 @@ class Logger(val logger: SLFLogger) } def warning(fmt: => String, arg: Any, argN: Any*){ - warning(message(fmt,arg,argN)) + warning(message(fmt,arg,argN:_*)) } def warning(msg: => String){ @@ -109,7 +109,7 @@ class Logger(val logger: SLFLogger) } //Error def error(t: Throwable, fmt: => String, arg: Any, argN: Any*){ - error(t,message(fmt,arg,argN)) + error(t,message(fmt,arg,argN:_*)) } def error(t: Throwable, msg: => String){ @@ -117,18 +117,18 @@ class Logger(val logger: SLFLogger) } def error(fmt: => String, arg: Any, argN: Any*){ - error(message(fmt,arg,argN)) + error(message(fmt,arg,argN:_*)) } def error(msg: => String){ if(error_?) logger error msg } - protected def message(msg: String,arg: Any, argN: Any*) : String = { + protected def message(fmt: String, arg: Any, argN: Any*) : String = { if((argN eq null) || argN.isEmpty) - msg.format(arg) + fmt.format(arg) else - msg.format((arg +: argN):_*) + fmt.format((arg +: argN):_*) } } From 3ad5f34ff780a1f05d9ed2eb04880ee87e6f525c Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Mon, 9 Aug 2010 17:42:14 +0200 Subject: [PATCH 108/188] Cleanup and Atmo+Lift version bump --- akka-core/src/main/scala/actor/ActorRef.scala | 3 +- .../actor/BootableActorLoaderService.scala | 2 +- .../shoal-jxta/jxta/1.1-20090818/LICENSE.txt | 263 ------------------ .../jxta/1.1-20090818/jxta-1.1-20090818.jar | Bin 1774884 -> 0 bytes .../jxta/1.1-20090818/jxta-1.1-20090818.pom | 8 - .../shoal-jxta/shoal/1.1-20090818/LICENSE.txt | 263 ------------------ .../shoal/1.1-20090818/shoal-1.1-20090818.jar | Bin 292054 -> 0 bytes .../shoal/1.1-20090818/shoal-1.1-20090818.pom | 8 - project/build/AkkaProject.scala | 10 +- 9 files changed, 8 insertions(+), 549 deletions(-) delete mode 100644 embedded-repo/shoal-jxta/jxta/1.1-20090818/LICENSE.txt delete mode 100644 embedded-repo/shoal-jxta/jxta/1.1-20090818/jxta-1.1-20090818.jar delete mode 100755 embedded-repo/shoal-jxta/jxta/1.1-20090818/jxta-1.1-20090818.pom delete mode 100644 embedded-repo/shoal-jxta/shoal/1.1-20090818/LICENSE.txt delete mode 100644 embedded-repo/shoal-jxta/shoal/1.1-20090818/shoal-1.1-20090818.jar delete mode 100755 embedded-repo/shoal-jxta/shoal/1.1-20090818/shoal-1.1-20090818.pom diff --git a/akka-core/src/main/scala/actor/ActorRef.scala b/akka-core/src/main/scala/actor/ActorRef.scala index 902943f24d..307b3e5da1 100644 --- a/akka-core/src/main/scala/actor/ActorRef.scala +++ b/akka-core/src/main/scala/actor/ActorRef.scala @@ -1069,8 +1069,8 @@ class LocalActorRef private[akka]( } private[this] def newActor: Actor = { + Actor.actorRefInCreation.withValue(Some(this)){ isInInitialization = true - Actor.actorRefInCreation.value = Some(this) val actor = actorFactory match { case Left(Some(clazz)) => try { @@ -1092,6 +1092,7 @@ class LocalActorRef private[akka]( "Actor instance passed to ActorRef can not be 'null'") isInInitialization = false actor + } } private def joinTransaction(message: Any) = if (isTransactionSetInScope) { diff --git a/akka-core/src/main/scala/actor/BootableActorLoaderService.scala b/akka-core/src/main/scala/actor/BootableActorLoaderService.scala index 22878b416a..041d632bf6 100644 --- a/akka-core/src/main/scala/actor/BootableActorLoaderService.scala +++ b/akka-core/src/main/scala/actor/BootableActorLoaderService.scala @@ -26,7 +26,7 @@ class AkkaDeployClassLoader(urls : List[URL], parent : ClassLoader) extends URLC } def listClassesInPackage(jar : URL, pkg : String) = { - val f = new File(jar.getFile) + val f = new File(jar.getFile) val jf = new JarFile(f) try { val es = jf.entries diff --git a/embedded-repo/shoal-jxta/jxta/1.1-20090818/LICENSE.txt b/embedded-repo/shoal-jxta/jxta/1.1-20090818/LICENSE.txt deleted file mode 100644 index 4aea53745d..0000000000 --- a/embedded-repo/shoal-jxta/jxta/1.1-20090818/LICENSE.txt +++ /dev/null @@ -1,263 +0,0 @@ -COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 - -1. Definitions. - - 1.1. Contributor. means each individual or entity that creates or contributes to the creation of Modifications. - - 1.2. Contributor Version. means the combination of the Original Software, prior Modifications used by a Contributor (if any), and the Modifications made by that particular Contributor. - - 1.3. Covered Software. means (a) the Original Software, or (b) Modifications, or (c) the combination of files containing Original Software with files containing Modifications, in each case including portions thereof. - - 1.4. Executable. means the Covered Software in any form other than Source Code. - - 1.5. Initial Developer. means the individual or entity that first makes Original Software available under this License. - - 1.6. Larger Work. means a work which combines Covered Software or portions thereof with code not governed by the terms of this License. - - 1.7. License. means this document. - - 1.8. Licensable. means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein. - - 1.9. Modifications. means the Source Code and Executable form of any of the following: - - A. Any file that results from an addition to, deletion from or modification of the contents of a file containing Original Software or previous Modifications; - - B. Any new file that contains any part of the Original Software or previous Modification; or - - C. Any new file that is contributed or otherwise made available under the terms of this License. - - 1.10. Original Software. means the Source Code and Executable form of computer software code that is originally released under this License. - - 1.11. Patent Claims. means any patent claim(s), now owned or hereafter acquired, including without limitation, method, process, and apparatus claims, in any patent Licensable by grantor. - - 1.12. Source Code. means (a) the common form of computer software code in which modifications are made and (b) associated documentation included in or with such code. - - 1.13. You. (or .Your.) means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, .You. includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, .control. means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. - -2. License Grants. - - 2.1. The Initial Developer Grant. - - Conditioned upon Your compliance with Section 3.1 below and subject to third party intellectual property claims, the Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license: - - (a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer, to use, reproduce, modify, display, perform, sublicense and distribute the Original Software (or portions thereof), with or without Modifications, and/or as part of a Larger Work; and - - (b) under Patent Claims infringed by the making, using or selling of Original Software, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Software (or portions thereof). - - (c) The licenses granted in Sections 2.1(a) and (b) are effective on the date Initial Developer first distributes or otherwise makes the Original Software available to a third party under the terms of this License. - - (d) Notwithstanding Section 2.1(b) above, no patent license is granted: (1) for code that You delete from the Original Software, or (2) for infringements caused by: (i) the modification of the Original Software, or (ii) the combination of the Original Software with other software or devices. - - 2.2. Contributor Grant. - - Conditioned upon Your compliance with Section 3.1 below and subject to third party intellectual property claims, each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: - - (a) under intellectual property rights (other than patent or trademark) Licensable by Contributor to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof), either on an unmodified basis, with other Modifications, as Covered Software and/or as part of a Larger Work; and - - (b) under Patent Claims infringed by the making, using, or selling of Modifications made by that Contributor either alone and/or in combination with its Contributor Version (or portions of such combination), to make, use, sell, offer for sale, have made, and/or otherwise dispose of: (1) Modifications made by that Contributor (or portions thereof); and (2) the combination of Modifications made by that Contributor with its Contributor Version (or portions of such combination). - - (c) The licenses granted in Sections 2.2(a) and 2.2(b) are effective on the date Contributor first distributes or otherwise makes the Modifications available to a third party. - - (d) Notwithstanding Section 2.2(b) above, no patent license is granted: (1) for any code that Contributor has deleted from the Contributor Version; (2) for infringements caused by: (i) third party modifications of Contributor Version, or (ii) the combination of Modifications made by that Contributor with other software (except as part of the Contributor Version) or other devices; or (3) under Patent Claims infringed by Covered Software in the absence of Modifications made by that Contributor. - -3. Distribution Obligations. - - 3.1. Availability of Source Code. - Any Covered Software that You distribute or otherwise make available in Executable form must also be made available in Source Code form and that Source Code form must be distributed only under the terms of this License. You must include a copy of this License with every copy of the Source Code form of the Covered Software You distribute or otherwise make available. You must inform recipients of any such Covered Software in Executable form as to how they can obtain such Covered Software in Source Code form in a reasonable manner on or through a medium customarily used for software exchange. - - 3.2. Modifications. - The Modifications that You create or to which You contribute are governed by the terms of this License. You represent that You believe Your Modifications are Your original creation(s) and/or You have sufficient rights to grant the rights conveyed by this License. - - 3.3. Required Notices. - You must include a notice in each of Your Modifications that identifies You as the Contributor of the Modification. You may not remove or alter any copyright, patent or trademark notices contained within the Covered Software, or any notices of licensing or any descriptive text giving attribution to any Contributor or the Initial Developer. - - 3.4. Application of Additional Terms. - You may not offer or impose any terms on any Covered Software in Source Code form that alters or restricts the applicable version of this License or the recipients. rights hereunder. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, you may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear that any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. - - 3.5. Distribution of Executable Versions. - You may distribute the Executable form of the Covered Software under the terms of this License or under the terms of a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable form does not attempt to limit or alter the recipient.s rights in the Source Code form from the rights set forth in this License. If You distribute the Covered Software in Executable form under a different license, You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. - - 3.6. Larger Works. - You may create a Larger Work by combining Covered Software with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Software. - -4. Versions of the License. - - 4.1. New Versions. - Sun Microsystems, Inc. is the initial license steward and may publish revised and/or new versions of this License from time to time. Each version will be given a distinguishing version number. Except as provided in Section 4.3, no one other than the license steward has the right to modify this License. - - 4.2. Effect of New Versions. - You may always continue to use, distribute or otherwise make the Covered Software available under the terms of the version of the License under which You originally received the Covered Software. If the Initial Developer includes a notice in the Original Software prohibiting it from being distributed or otherwise made available under any subsequent version of the License, You must distribute and make the Covered Software available under the terms of the version of the License under which You originally received the Covered Software. Otherwise, You may also choose to use, distribute or otherwise make the Covered Software available under the terms of any subsequent version of the License published by the license steward. - - 4.3. Modified Versions. - When You are an Initial Developer and You want to create a new license for Your Original Software, You may create and use a modified version of this License if You: (a) rename the license and remove any references to the name of the license steward (except to note that the license differs from this License); and (b) otherwise make it clear that the license contains terms which differ from this License. - -5. DISCLAIMER OF WARRANTY. - - COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN .AS IS. BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. - -6. TERMINATION. - - 6.1. This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. - - 6.2. If You assert a patent infringement claim (excluding declaratory judgment actions) against Initial Developer or a Contributor (the Initial Developer or Contributor against whom You assert such claim is referred to as .Participant.) alleging that the Participant Software (meaning the Contributor Version where the Participant is a Contributor or the Original Software where the Participant is the Initial Developer) directly or indirectly infringes any patent, then any and all rights granted directly or indirectly to You by such Participant, the Initial Developer (if the Initial Developer is not the Participant) and all Contributors under Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively and automatically at the expiration of such 60 day notice period, unless if within such 60 day period You withdraw Your claim with respect to the Participant Software against such Participant either unilaterally or pursuant to a written agreement with Participant. - - 6.3. In the event of termination under Sections 6.1 or 6.2 above, all end user licenses that have been validly granted by You or any distributor hereunder prior to termination (excluding licenses granted to You by any distributor) shall survive termination. - -7. LIMITATION OF LIABILITY. - - UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOST PROFITS, LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY.S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. - -8. U.S. GOVERNMENT END USERS. - - The Covered Software is a .commercial item,. as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of .commercial computer software. (as that term is defined at 48 C.F.R. º 252.227-7014(a)(1)) and .commercial computer software documentation. as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Software with only those rights set forth herein. This U.S. Government Rights clause is in lieu of, and supersedes, any other FAR, DFAR, or other clause or provision that addresses Government rights in computer software under this License. - -9. MISCELLANEOUS. - - This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by the law of the jurisdiction specified in a notice contained within the Original Software (except to the extent applicable law, if any, provides otherwise), excluding such jurisdiction.s conflict-of-law provisions. Any litigation relating to this License shall be subject to the jurisdiction of the courts located in the jurisdiction and venue specified in a notice contained within the Original Software, with the losing party responsible for costs, including, without limitation, court costs and reasonable attorneys. fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. You agree that You alone are responsible for compliance with the United States export administration regulations (and the export control laws and regulation of any other countries) when You use, distribute or otherwise make available any Covered Software. - -10. RESPONSIBILITY FOR CLAIMS. - - As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability. - - NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) - - The code released under the CDDL shall be governed by the laws of the State of California (excluding conflict-of-law provisions). Any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California and the state courts of the State of California, with venue lying in Santa Clara County, California. - - -The GNU General Public License (GPL) Version 2, June 1991 - - -Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - -Preamble - -The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. - -When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. - -To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. - -For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. - -We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. - -Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. - -Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. - -The precise terms and conditions for copying, distribution and modification follow. - - -TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - -0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. - -1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. - -You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. - -2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. - - c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. - -3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. - -If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. - -4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. - -5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. - -6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. - -7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. - -This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. - -8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. - -9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. - -10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - -NO WARRANTY - -11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - -12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -END OF TERMS AND CONDITIONS - - -How to Apply These Terms to Your New Programs - -If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. - -To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. - - One line to give the program's name and a brief idea of what it does. - - Copyright (C) - - This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. - - signature of Ty Coon, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. - - -"CLASSPATH" EXCEPTION TO THE GPL VERSION 2 - -Certain source files distributed by Sun Microsystems, Inc. are subject to the following clarification and special exception to the GPL Version 2, but only where Sun has expressly included in the particular source file's header the words - -"Sun designates this particular file as subject to the "Classpath" exception as provided by Sun in the License file that accompanied this code." - -Linking this library statically or dynamically with other modules is making a combined work based on this library. Thus, the terms and conditions of the GNU General Public License Version 2 cover the whole combination. - -As a special exception, the copyright holders of this library give you permission to link this library with independent modules to produce an executable, regardless of the license terms of these independent modules, and to copy and distribute the resulting executable under terms of your choice, provided that you also meet, for each linked independent module, the terms and conditions of the license of that module.? An independent module is a module which is not derived from or based on this library.? If you modify this library, you may extend this exception to your version of the library, but you are not obligated to do so.? If you do not wish to do so, delete this exception statement from your version. diff --git a/embedded-repo/shoal-jxta/jxta/1.1-20090818/jxta-1.1-20090818.jar b/embedded-repo/shoal-jxta/jxta/1.1-20090818/jxta-1.1-20090818.jar deleted file mode 100644 index 6b539cce4a0f4e4b7f8f9d669cf296f136fe28fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1774884 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�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ü~R&&pcCTDp09czCG( z0lSm)4)0-DEpEBQd53>|x%(IRS9DDE2yjELvw6?zA?9+|V z%d-L!+WdD`J$f)<_mTDvqZ`&$GuLNrII^j{bA8qU^K~ZovTH(@SM3WHIJ)tw)%y=7 z2bS)Q;dz@qXXV2w@wfl68(S7g2k#4Pkp96SXrO%I%92ZmAH1vlRIt=fZ(_ZNRrYJs zC20kF{PIq`3!fQ~bMM);AAFV1HXBv-Z<*YY%h6eOf0m`vGlioPYfcs(G@aF?d+=TN zmi!6NV{9ufg=z(VoBMX}zI};m#n)@9^6p<>oK_!b_cu~2I8Q$yKxI#at+D9W`Fn%s z&&&Dna?0a{Jf77@Ct5DAIEZ2zvc1ws(q60UKcxA_Fq}~O2zNx%p~z2Vf;@PJyq9iuDT@t zz5L4k1yS|g38C`Bzt%7KRdr;cXNkV8gNxPMY2uP!+ybm^oqXb*;}7pqdvCnzf9cn= zQ^h6E)I0auHriKb&VTiOIr9&`gLfRQTDCFozZT3^<>IP3cS_))_7iHodzW;}e4V>Q zUTOKCvZ*)tCfsqT z@sbc1jb@J6CoA>esx02Mr`zbYVq6$|>hIjR+4tXVwYR-G(J=J<<5tgB@OPQAQ>?G{o)dUk@yX`<#od+fe!tLNuYEo@diwL13l_>wd2a5-H|cV= z%)&$|*`?2SX~?I`y*vLUZCcqx@xOwpvL-<{dcR0zSglyl>{e;K@yuPv<<-X48DH{F zP0LT5`zv(&{9|txZT>cS+x%l?7bJIQ*!&XPd`BtqiO{simm=n6o_cuJ#_6%~igk0B z{WAU@{84Y#0*R>_Zpmlsn!+==*l+I2S$^*Aar*-`me15X&ho9YpRmPg*Hc-Ojn7vW zsjIro&{2^sxt1rD^ljOdNM(WNO#5RygC{8Y_1!#gdprC1v$r87L9=QbZavLOo?BC6 zcmG&<#C`S5Rjn&*5Aa+ROAdfMDY34r?*sn}&pO!(Q5So+ z<%##TUuIUd86B(?Dy!);QoMZni;c|vhAr}!xL@p4_#FQt`is)J%}w_fPrvZ_fsJ~@ z_WZ;3#~hcvzffNINJ!4@{^2#vrz$yq?D4RABH??VJ>6PG!q(Ded_j?QDph3Y|@-r z_)^fSKk<3=g_$P>%CAlOTk=nD){1NA!m_)AYI6A|#Fn*awU*>DJ^gH86z}%QI)kyn zc5jt^=-Wk_UB{h{9!~!zoFn!%joDqRS)hC7E&nYug7gxD4n0}Uv6wHY*Vfm5)yn2w zGn5$KPAy^NQOR1(c7&7RMC(Gg16Ph3d`g*7$>tNzyV-TYrqeG=*Zh!-bzRT+$^Q7R zc&4^|r+M2qev&=2ulw8fFYdqQ2Gw(lREy4S7G0k>U9!aV+MabzAAV2s>`Gi=exUW> zQJ(W^SEFCdEZ%=8X4S|0%i^Pt&Cij%ugPxjL^vuC;8-!pknLIvN`iK0n<*Hg48MNAa?tz4yb)rbs<0(ZA@t ztTddP?Yex z+G@(CWgT;8adinTvyfaSapTWq zuHZF?7B8!Me|f%Qwb)bE$o>;T3cHD*h+ob5GuTZD3q0Zh9s9j7amPC+EV}yj8cKJ3jLZI!f;yiOXYLacECdbfs?o!%~^h4^jSk>zvB|u>Td#6|P;f;7P;vd{>tr z<~IL?LuSe^dhX&D-}#mRy?@G{Lyamwm?FOJV2W?}*DM+(l=19N z{n~(ZrnBj+s~=0)PGq^$`(PgPFHeR$nQ1;dTrOPmn-{d2+dHR4nYm>4hs%m=VHPSc zBQ35>{rFX7TfoMBF8Leow;l+c!^Ijq)8joatN8D`3g^rP7cN&iq}#FLd-c5V6Ag^f zf7-5F_{?59$JQy)t#-?q*_v(r86Clo&(^J0)3_7#{;ZA9itZix_0LQpkIo;vKKrlF?~niAG;7H}+i1ggO8U6!r>zWIr@AHP zSTk&8Zrk1C_CYk{MEFIWeY3IxCaisM{?vX2w;O+%VtXIusNeUP|9tifxqXr{`HmOM zw7It2ei`}C=+RZ#FTwjJ-+LPSh4H?x{O7$I#_u2N+&g^ur=r~1_=iP#&pZEgFx~R) zu(~*R$ zLY^8NVY6PBGW}=i`o%s0T_xXg$|nSfJJ~tN*?F+`2=O&UooIilBy!RB#8v5lV_pBI zH|Ht7k~OZ5VJScNDCfn6ekBX{okfD7YB4isO%^|%mZ2m5{M&`7DJSX=o#YN^sj=kd zO5fsD&G8JvXVs>&-U^y=+hihNyKLj622Fk&w<1QqI;**-7yl@E6Vbl!PK--e?x~e4 zteI8|`Y&>Ma`8djiR3DcykPOz{tXp}A5B`EqJOu0^;2={7j7Bv)GpqczG`9D?B%zN zmb^N>`R&3#K|FVuoaGiq3*ITawe#u3Qpg#Pn%W3QMf0i*Yd5qLXodRki$AcJ1p~60FgB zST@MwMcAzu3#`{_F+N%NZ}Q>nx-e-h@_QA9zCvCTzKkC-qBb~H}<=8tNlMM zO8d0WbmH6+ZEH(!uctHBpKaayVaNT}Yp<)=mTzP3$k$5PyLjKSw|_n@Su)qNEZ3&e zME+^k(I;2EG8cupt=`IYYl-iY^BI$0_~javW(L1-&DD~H-4FPIOgTSQ!ZORT)ZNqKD}sWslHag zYk~UvFB`E`cdeJG5={11|WUm%h@v(p+QSf<5OtwH+U=ES$5|_nE-1?alA3 zeZI>pJ@##Kf zQutrTQq?o!3=I9I_~r#pp}kwD_AGaV_;x7%7D+K zdN@7mT$GxUnpcvUnB$XKT#}lXS_GL8=?!}wEDc)oG+|RpWaBbdIoDa+BAgkRw`6&5 zxW$%nQD8%W#@E2@*nJSRI6EgH5LdLFZ` zFmE`$LrJ-BqE!!#)M zF>%_$Ymt|VWB>B#a!$6s_|(+B_tnfbf>(_$W?C;j&SA7>_O9a2g|;z_mwns*6lx!p zloH-`a&lf;<89+tO^%Zi4qXaK4%=F~QJ?GYA>Fx0bLTx;ws^Ih(|OA~Pt2N)@`QS& zv-FO03TwXK@_K{T(OVO?uGQH-_v?>IS<6mdoLP_*85_8mJI1v5;!5V_i?x@$XN_Mh z#pYbhm~|ntq{R1er2BRsqo~8-GHn5-&O*;54iu~lnyIB?^q}=Y^lS0c49?N6GR-!* zJGUJ>UJ`huL14e$qM!?%lew%ubUny3lJWiMdewAJ&_tCp+B;hLRcn?!NUl+OxUI>5 zp;tt}0!7tE?Fg5sLz9?fPxHun?vv8G#hF>%<`k2%`T-vgtK)oNS3C+p}LpL;qvSvr5TZAop#%0I+^o!*sp7h7lvX?k5d)jho(aBYZzq3!?WMcmK z=x5e)vkMJ5yY0&C>b+jHE!nxbdP0ctmE(^e zzN?*V{`SVMnSHVx8x$6=KJk9nD#z)IEaz01{fYRl+jed53m)ycYI8FdIUL;*GkeZ% zTeEpGsR=B(db2rtXROM!anEi)m{!f=V&I{%J9dUTN>=u>(`0C<(n>Phc=Ra`H zyL5HtSDmZjyDTT}Ff=Y}d>1tH1z$sQ>%BL}P8!IqTlMLXruMxJ=VSNHlktyRy5ZXn zDJg}vil-B;Y+Qe<7<+HqszUT9^xU)ei{|=9f19H!ycgfuysdG0 z>Ty2#htlm8H?Cgi}xoVd&q5- z{*lIgi7l!uV0){B+$XkIo&49HFLaSRXm04jmH5j&HcJaWTETZzigO+N-jK=*nOh>>3x3iH*gA1u?uJiW`9uY( z%d#%|&rOyyZ*W|n{M_d3=ZdKr6Ly&WTK-Dumb-{=>3?QWp>~6jbwVWz1H*Pse1)1O z&O!}TgnQJ><ucc`gQNVYkHsl-QQ`xS!MFm z>)-zvKA%(l&hq}xZ%^<1cy;`|oxe-*mB*}KRPraKZ8nMiQzB@7GGn#LbMN9t6LGK4 znwi@qYbMU;vQ*)}&71e_az?dxgp~IzvF7N%CVjV`Cucazf68Q(v;+ghU;pY~xn_m84~K8*F#zW?~iweQmL`IG-?-K^cZ zW}n-Heb@LmT>tsAYM*1m{fHChAJ2ZO@K(HkYP)33?)lF?$+p(0-&Z~RocCYT!SdfP zW%4GaR;O-R-|+0S?WH@~{ogsy{ARtwTy*50(?2Eqj1P?Vy2sT__)nf=Px-Q8Pqm9% z|EU$bC&*8BmKVP>U*OLECy({Hm#EkN5tX-BeK23li0_nSJI}vWa~hb~q zY9nWb^ZeU3zwCqTp>N@TznJV-%Z{7=%=*$E#ZSN2ncV;UdG?=aCi&tED&5`gPk$Dh zS*LK8f9cPO{r82v?oVg4_;=&D{m0M#Khy30?aVl~|HNVaKYzUc9XS49%jKWfGJBE6 zzfrU9i+tGsasTfh+wK0%?XQpbaQ|W7^2c7{&-}W7%KxVy{IA>dd$Pg1`kFuKGyim( z$p8GYp6&lx|KB@KKG^^JWn7+6$A5z#$@aDf_(eW(D!yi!vHpZV`;N2gBQ$S*kagb4 z^Yoi$|NLD$&j!TJH>x?6zJh80r_b&VA)->JMC42*v!*O`lg{E1Hk^5N-~D*l7-K?%Pfq z3$Az_ae7-chu2t&Y0a?^CWTZ_Aq&%}&UGCLB~@%mOZF;9UAz;gXmS38qs(ruNmWWY zZyLYur0!qLx@%lGpDx zDYtjxwHbSKPCsI2Fe_IRN{DgQ5Y6v53D>!N_fv&UR%?>Q<>?zHeax7?;qw-rvf9a_ zyyp%mN=yHF8}_?Qdty#EL$k4Qw9#eJtuGVPX8Vh+sewOl9Pjl$J zV*E)@w&f{vsq=>%zw<_{#@5D{MQ7GV*lT@Ga@{lYWzU&u1$%aGj;-JbeUal=n)Hw> zolE+x%Z}_+@nfbRpLNgN!>JLp$9AprtX*uj?MEBie)-;(3cGeaBwY7)z}|Ivx7$p4 zwWY7GSslq(7{=VaszPTb*U_NaP8a=7w@N%>I&pMjgv!<_D_5svn98l#svLA_;g+Je zw`R^>P!Rgjprp>nS0(LgX;+C^%Qp9|3y;ipzUaHq#bw@H&u|T{dHyF3r9EAjwpv-V zv-{Z2;M|ESmzVrmp47P7rSFS#_Tg(wV?Ult>6@3jY~dWEJ1vQB=Z_tdTQu=mz^N!n zW^SFFdGpS0b+Hl6?{ohexi!p4GHa{Y$wD~}gN@REy>{EzzOXg^Vs!EKhN(WCEDN^p zJan;WWn81F7H6r(OZR-c6;~@1c{2RBC55N3UH+k?x~gqY!qG){+AO98E(ei=A-eA8gT9uu=>Bl_G4CY>rS5UV1*wFleyM#mVKikCK zh&{@-sR!*_&+{@?#-g}+hm``+nuFN#b_W;l1%m|bd8 zw3(y3Qc_Nm&%Kt-`wNdq@HJSsSoY>^4dUH4d$X;7=1GV1_QeMIPk7y<9&SFe>Fcs@ z0jt&~RW1pA)Hv5fR84t$)axiI>ylTd$Lc0Mcynfl)g#YLWrbV$Z(lKN_54xh!hD=z z)0*CusTIa2=E+JNax+-md}Yl+84vs7vOR0U`$UEIoOCJPyKJelU?#t6+5Gf_ug)xK zeWTfPy!+|J%c_hwmzgt}uX!munbXaRxgl6bQYmQZbxXnH_lkaXlrby}nZ5M*qh{C3 zR>_lYq*N?qu3EHNIkk23Z0$W#Mtf!Ph9d;#e3Gvs~%-Gx1AGT zF27}v`uSMft7CUJhGc}BeOsQAxSG3VRe;gd$$l+Tx&?urb#HU8T0DOim+2Gh8EK*T zIyBjaF)h*l-Z}Y0|JYPL)@&>}5a~SQ-IouDL zGM~JW4G{afc5d;tm}SfUt@Mo7GK;xnQ@n#!;Pkr9OJ+{CELta%$y@&D9U`XR$?)%GbZ}z3zU-~@HUoxCr=OsVu zi)q!lCC^{(@Qh!cKjVw>icf1?=x2DKUvXe7dp3P2iC0lNCT-)X} zW9B9;7Hux>2P%(Z11`Nt*zG%Wq0+KjjFPLmuR5(rjNY?Y>z<@HtF8uTi`+cfHO)d> zQVOoV+;mJp@WGbP`qrE%3`iko*%7q3aa`%U)4hPEv8P@ki|R~PCr zmNNTYon`(YU{0!rhs8>PM6on^TLA}7zj-so&*V(5&6#C0PyNfx*07VQoh}*MXUz1p zUm`zqRd8u%+Z&UsdRy;>>`pCNx#B?TtIKV>?u5(_oG%t*m%YlC=k{)=*vwVuSFZLc z-MZ^o$aSycxdvP1CtE2t1sKS9HV8Ui6ib}s@%C4pOX^4ARTnobisJTNBG$8=CHRDY z%JOHQYzlsgxSxsq^2&E>?WBDNL(IAC)YIjI=67_zpLVs0E&L$kA&)$xD`%ZPr#+Fm zdD{Hggqe(mb1rX43Jy>YuUfpzHKKU+uCpQAyEX4Gd}neccG<5zznJD&o^w>yY*%>i z>L|12msV2#jjm-*p22r@+24o$b~th24I{-QEL~z*yOUBZ&PHqU!)utd+vXsBlZ`BPua_M z!6ea_E}mg(#%F4CCazN~)+-O}N@13G#8 zQ>(wQZYU_c_aQQE-Ip)xF1sIbTE<||-2bYf?ftr}W`?yq^SD2qxH|7cee7|u(hInEpJv`yb%<=x$v;okM7{lPcB$?Fa06)%f-We zLTQzu_*S~hn~l||SbLMYk6|e9zKj#qJwA$hRt8pyTaWKvQ}6Y@(QD)0 zT7#!w4jpuhny}JO)@Z)#Mdp`gX2-wgI-m48qGCKL=ftk5$5s5K=SG{K&dqodv{Uoo zyDwiqJ(*LrMXOKY(i@Qvk3XM%{Gp@xZg0lS&6cmF?!+$Af7`{jujRvSr;}FM(;o<5 zj{WsdN&D{P*MbWo=a;^pyj$n*$Me#!UTk{ik*YA9q|^w71Z0-_^>Oe$Ot&PB^nbRN~1gzZq{| zz3};3T)=lmQ0`6h{SvRGlM?rxv51d+5}|)%g?^RasX(^h@6tlfwS+u)=SgReYzo^&|JJq|J4cKp1J==2c&qlULlmnYPT_PGRFZfW0e@%AGg zv1f{}{!BdKS|7!pKc`>!=YyUvr;m8<%-mb{w{741*y~F7)Z34pG2N+Hw>0X8Lfwie zovl{ukL_OY@z>&pic}se>q85tq`rQ_RVz8)&g`u^`@K{B=gsvGY*#;;be(V4#jSok z3k*c#_gSaDj0!TCSNX5#VM6p0)zIXvOITdKE>Ng>>*1~>8~A2U?4fv7_~qs_AFR2s^Qks*GuAvHc2;8=WpZI^?nJ!_moQTY9z4*XA^I zRsLpMJZJTpeZD&lug;52Ien(9>uz9juFcE0x4{nsL!j={s5LdH>Bp=9+z{ORT2OThi@uQSq0S=*5#oKfPO? zufJHltA1YJ>wmAm@ZR0;p#SRM>@T`^_b>VVv`Bf){QbV`U;Q(!iv50nq4@>zlSkLp z)lI&4>F@0?eed@Bzkl`J{=)M)I^ixan7_#F_4l#AmR;BM-N%0E{Dprl)y^sK&vdcb z_=RJq_fLb$B_F+#r-;d@%{O6Py6*53eOtFy-*w6=|Xoz3ZUm>~Nwv}UvR{eG3UH-fKB+e-Y6 zCI5l*i>>b7&Y8D*>J?wM>J!K9q>k3jI-(}(EMi=tbN2D%495QD#RpqL9d^xA&kXYs z5z5?qxWO}o^VlD@6obFgGqPtpaG&_d_=|O^t;yg?*sY%a%;2i*;+?+Vx|L1VUy8lwJ%7T{@`M7j=H;KYZ7nKhmXg4kr=(jsxf>g&o28K+%D0~F`KucC&)mo7%KxS$JcAvoAz9=&5aaDv_Hb z^sV#stgFtm`z}1Q(yI=+?a{E%J33}V{a+SC^RK=>>o3>kcukX+e*9zO+NTA{>_<<$ z%!y+7o)UdQvcUg{bf%2~_Xjbn$=jX&i66|;ThLmgIQRJcMQ3F$)%<4JAnm_=Q9UY=q`a>%G}j2g13E>xpMmaxhOl~$BT0BJ%6!CEj)@{diI?|`;V#lM?MbZ>b!Mx z&n>>kIb|0QZsFf(DWGb;eey}e0MX@MeixMd0(HxSCY4_l-4k7`kdZup**C8rbL}&- z*1Je(l&mnl*c_FyF?>twxAeg1g%|ZtI>k5n1>RVDak{Jf$sz;0jv4L07OgwqZZdUw z?&Y-y&zxrpwlWcCdZ%N?awpTSWPXK3a?4UHy%^T87~ZfL=CBy==O1_j+Gekun6KEK zzjXEwzN&`zUfM3oGMgnjr1h$1n+YUd{Aber?XYP5lE^Lh6DLYEzdX~^WN6SYmiR&9 z?4FHgpA*!~K9^baM6c6~o8ns78gR!-<0x|_=X{&5ibme2Kdf3S{nGvB6}hgET@!mw z__XnF^OAA!sN|UVI?-am@eEUYM)fbMw@$?`eEUbl^+&=i_S+AQ{FtUD?Xtc!<-JGn zzQYS+++0uWipgwGc>m|dy_tu53nv_^XwjW5os<^$#q_9|Ec=RA5^poK?3~1}?|imf zeMdJxhy9{&x8<_tzt_~C%`okVNKK6lW4L{3Lc!G8yZ!e>{wuk8`R@x`x4M5)y^o&@ z*v)r$vEyTBIN$%=^bgacBj%=iy&K&%i#ByGILs{dOliqJ{y)bZgVmbjCf51RVmFm3 zs0diB8J>CS?N|BRuQzHr|2!$-`!MNt>H&tmLTxWKIS(gs2^GmNVOM;*(RZrcNwH&x z*62^%*Dho`WlagYjaBsLMf?^0x2xCLd9Cz1ulP#lweZ*XRr}Vqm%Wl`@7Upe=<++c zT_yVh?G9duX`XuZS-I(S-gQNNo6c6vn$OlbdBUT!6aSxXfA;!bTAAu3$4BOZ-1n9l z{?Yq1RsMp>KgFpZ`wx8ho}s$mfA){#S5DctzW*s1d)9ur{zrX*mv$b@3sXOs2mch= zP^-H2qe+j=7S1}Wj)~Kw7H(MHbdyc>;mKu(EnL6O^WuK0X~*j+mn3GpFnOAG?xb%$ z9IcgX^WSwO@Lpl=Yy9Rl&G2-np3UqRwodcceMvpOvSEF@p8JATIu~l9XB^#L^ze3i z&%qyI_ij9S`+gZStDn#8z?ae{mjBnxdFirMrF7}yS#MALb8-D6uJv$#6LAT4tF?y0qvx0=4XiZ~tlrMx4$X~pu0o+NPHr}{JWZCB#rsE@)@ z%A5W-OFCcgc=a*6q;B?{_!B>0R?f}3{&nfCrv~EoMOVd{-#xy&W%+EqHtrcPXdH!HX)e9}@4t56{hD{!)-@MV8nc1{Xu5Up$UsLJyg;~4A zGUB?uJb$?de)d}X+e+)s^~;UB`RrPzc*>d1Qd?=b#YHsG%Xh))D=NE!e3wOEG1(P6 z*Ry=3(Jue9i~eTu*{*sPw0@Sm{_4#yb4};p3*~-!ebprQ)y2k)auZkR@0C6*S~Jb> z{T~mz`_~!k^5Tyko^-2|WBRV?9%qaB|1OCzK6lmm`n$+U&u-X;Oj_4e_0lTw;gU6- zuV?aIkpP=tYyHBEbulUYeH2e1{PQe|4cev+G z$o8D}VfmZOqO;aZtNt_&x!}CLEZA}BZ;iYAEZyg+FDt(srZTM=7vCyi%i;c?~o^#liOp&|h8Z)zH zo4Z;0IWI`T1~y~_XZe>MSMN< za@VFeh2}r6EHw$MZCkd|cEd^SjJdm{F7535wn93g-~3Wssr22|d5eBuJ$q$s-ooQo z*Irq?k74(o=6RvzmtMcp`?YXawD+^1mZhp3leq&QRle}qk#^GHZi)4$Wv;t)cFRYe zP73jW|>Cr^ys&MA0^Spcu zxN3Qwo=luDPrhgFo@yBbyF8zG#e&SSq`aQs?)kLkl_&lfWn{j9P5+sE{u8#Lwj(r=f> zDrp7=TU&fno@%(J{J_VWskr8q6jefI|5}55^MwLMZ1d9+7?uaDIx41{w3e&6?27I& z-?f~)D|^@amY5&#u1uM6Ffrf{Z{3=bi>-O33%k|Adbt-z*H8JlFR`h^Ebra!_xH-r z?fm}a?~k8PwHsFNnB>HC+B3sK{cu+w_okx2wji$58CF_6ALX9!%P@TMN{@fdIfD(l zk(;(@T*(WQ463;yyib$ntxlD z9bR}U=5F?_bL-x6SN3;BT@b5nyRl39N55pxtk*^LXE*+?^?UmCzSW}J#cR^8-})B4 z=-IX(1*$C<<`n)*NU;7=wJ+rT4gTEI8}Hh_E?azfw&T{C`Ho+uWHtYXPgcCR?f2V@ z2eMYiB+t0{_~5T2_d=GQoxDh1tWtZ8Kzi0~=^wsz-X~NqJzf~Lw5?Gx#%O}esRM=* zR(i%F|F?HE%J@m0cs!*qlv!+=MA~w7zN;r6|GAjMv;2P!AJfAK>qV#E2RZ4zWPCdN zp7Jj(saj44$FOr=kzsw_={zYcmqd(9cC$~7W0L$VJR{PwB}t5bp*&Nv721y_UHN`>j?(V$9|YxUOnNY#NN&sCwz2V zE41fKKcl$kR~^@%GA0@6W^N1N#?>hk-=x|*PyZplzW>JageDDXLCq&ideRG<{9Z0- z`)tv7G#->Br*uq|w`XEt_=5KkHEsM!(mmNZF()S}F*zHOF1Lo?E|+$f{D0Qtn%C;B zlYfM*FO)Vd6}s7{Z0_r%w0zmt$7*H0v5yk2^DbSpv~zFg9;4M;7Z+%6pH{ta3+tq5 zMVbkEoEHSFJuTTSK3tHi`gKJ3d4b>kibpd48XQi4Uz-#;?QKNu14rZgXKFtGt~34| z8&+TYe5*af4)No!KU5hxuj&tLM4k{P1(yE4qF`l z8#(Wsi$TNj#WNa(UBx!vsflS`y_jz&hiRNh@r>s$i`Ps||NFV;AE)g6Bg-q^T~4fN z+c@vahe+AmA1&kl)kwr&_~6RxpIH&*;2pU#vvf=Ng5nc_agTiNZ5H}=CP!`J_PJZ; z26cv93+=pI=C-r*-sE*b{2OoR3T(Mt8NOg=PIQ)<;e#ci`xZ>zSUm5*wS~sl_Dr4e z`HfFfM_PueQI@~uH1p?Ljk2ky-MJq3JoQm++jK6ZoIiKPr!^;eH1jnBia9+)kPt8*&W=k)&esOwP?Y(V_+n%SXO|9Nk zFzMF9oKvTIBG;XL96i}F|JFIq7srEY!_m-EgIG|&A# zB`W;e#Y*Y$Xbbz@IZt=~zx?xhgUmun;}TBr14i+}Rl z)j3DP6&!w>)O5xy%6Qz;ud?BJna!y!+#Z&E4>Nb=yWVDvb#)1JxNj9!d-5rN#i^}( zblg)D?wty-p1t&J(u6~Y_NLZ-w$`6@Z~wEW=6fCc4miIySXHpvZr0r5;C=2~S42#| z87*+M{C=9PEOC3I#VwvKiw_@&Q!%MIdLaCxX=ChE%l5YQ(m&YROl^`M%>FU0EuFVU z`g~@^y#w4o`VM?sl=tS2$;8f`r@U^T3pw*WZmQXb*qZ*{xC;dr4|G>}9{$d|r$=7m zhhm+I!0k6X*y_%lTK_;@sxIq6dW6A;V!QkL6~CtcnA+&QW6i_sY<11|r7A?ZnXFG| zE)8|7JmY=#Ox5$`R&%og*8R#)yK1K9e_hq+s>69Fn6Lia*4h$3(~YU@w;}`67By{{ zq~@k}euc=@j=fV=mx%U!JLTLu$MziOvd6Y6wnY|oH&Pq=ek4Rcy?8O?%9)hq%W~|c zf7z;jzW7-Av44+!MN&n=4~ePgd;J}G)`WOHEm|8J8_T5oaoeN^nn%BSzme~0NUnzi%QEbmQeZ*N8Jx}B+QzUI@s_lYHc7Ch#EHQmuG zW{!Q;o0$5#Yh{+4J^l&bhMO zKKnpvRov364Bs~MIW_F)T=0Wm>Cyfbg6|jj?ctuRz<=S_KPDl*M+OhP&-nZhDxSRW z$Q!18NA@&%Ou7>h^IB(J>BXqVV)I0qgMY6GCI2j+wO&!~uaacWelE+2YknDj->BL$ z=^*PCRp)SleGSuIcf>UAYk9$%qkCd&n`D$z>47!BPOBRKusU?GsYKTF4(FVX?~6R|>hRd#zc- z?$z#X)Yx;t!X-0iU4z6F$w&Sy#o#{4Xzfci-+w zzus@GJ#=Ng;R;kH}wHcEFO}v?_ zQ%w0z>%N$H`+|CQVa&B;7qbK(vm__8#GqLxPNY3a<(@aS{8444c-$1jJv#4?X&15U zoetZhR{n_hW}o>}y*;Ysk8>rD@6Y&?f3tIT(Rz-P)kn=L1FoE|T@-jv{ZY|=3kCje zyP03+ev&Mjmc}(ruBPFRxqstlhN^{+b$`vi>0Z1mL!~pE_l`=sO;_D4?uprUEy*S9 z%0JZm9w*+iZrg6?a&C1Z)BgkPhCK#WZ!OV74k#%Q@>>B9> zFWNYEJ3g1$(d+x6DSi3E`JG+k*ZnqFQ`0h-zR$YtjgBO!7 z==yx&$kpZF>y)&e-Rf6Mpz{Z%Ch@a}ZJkb^arQY8k#|K=FXfjikB5iHjl&8nyKWtR zoh1=wDtU+No0^X5im$F;6P%0>%{tYbb>zuGJ>TbP8SdD zJZZD=)klN;V5`zgb4(pKPvzdNZ4{qoFm-pFu}L=bVYC0KtX7uOE~xMlr*TE?Oj>2TwQF6u)~h@&vlNLtYpza> z=n>wZBjmGH|3+5Z)(L{oI+xDeB@$P-Y`N`4!+iFC;X5v?nM_H22aaniFn5?OjU2hn5%9B~4ysy%N^ykBU07K*wSYSJp8%w&f>7IjdKyJ+{n# zxWr-auA*am(!3^nrte?WZFic_^rX9T$etMEw{I^!?5qB?#qH6utm}>?$0a5eP0Wy7 zz0v;|*N@aGN(zg4v{P9E6(7b){w|!~@;g=LfFmdWi3$OJ&x(j+$`&dQ110+(7PeKE z9V|Kef^S>Yvb2)xM@((c_@44eGoRW&{d9WKM%hFAwrvdj9(uBZ$-nEdrlkMl4L#`v zEst_Lj`VKu-(#=+&{FdJW7f8(H%0x9bz5jWR+UMLF!}dN`o%&Y4vs{o*P9(bZs?hA zsPRx#a($A=j!NHSfeZicx-f6IWzx@}>J#ctin{SrdtdRc@`+y)bIed?Vqr|mdzO1C z8fU9cWUP-p@!;CIxOGuHPj8;R#wy+TW_G{8@1s9NQu$?$5`0Url_M zcPeCqW@-1*-Kp8f*R=%{+w!vdUT%6>8~j~!)v4r-OGQOZoK*i^;{0rTal_tU&tqGT z|F%5asr~e9wPCKJ8wfqNy2Eq^B$i&D_a3H#XMlspj1` zR}bZ7sFlqV^|UoS^U+^ag)>}yZRM-2-9K~Zx2RuLH-4nKyXUKqrqE}DYx1f8j$L~5 zy*p>S^YLZVo&|hP`&Do2XQ{cHXY1wX)maOK<1)-$*j!G&dEssJ@W!!QTkQ7D<+#;7 z$+e_7<-ohRTbJKPzCV7lF)k_hdH?si?Aa0inTuRfa(+cU>AG}FdD-pBW@aK&lQhEo z{}s&qlxy(xGK1)so7;J|a6WXJ7;*ngYlMo~j@rvY>i4u3$!aXWzvcY#`tVEg8L!tb ztkw;5E_r@ouR?*CPJkJcd%{DGIgL}53t0E86MVAAIYxb*sL=`58^;Sa78h*x4>(|V zH0PV-o;Nn@l>gnDqPoUeG$EKtaT%W5p z6)Kxu@a(wh-lEi>=l_5w=DpJNY4;^9`V-F@EODIDtCTPCPQ|7E! z=jkDlSd;s+C%0U$JoVbDeOsVT#Pr9dy^mIDWlE?vN920zZZVzaUr=tkQ~BW|nR!PR zDSZk~u#VG7`r?(op`~L^V9aE}&xIZ=$DZ1_&NQ5G!0yb_oKCN;34Ez9ibXc*Z)mCQ z5vDL0qEysyBaCu;Vl!?IfS4Ls=i_9joZC)vG(vst; zfK;Jz=rzY(i?(flz_vSG_R2-s9rLu}-OFwFKsLv`SyiV0kClPp2i_AC4e)pD;FU~J zYI1&23Z!>8HyASN&_C0tA^GQpB>OFkaz)wRL_9vU#Miu6&1I3Np-#_i_B~VF+ZXZ~ zv(;1Jn_B(BYOV2ckLwn25ow5CX=X2V=e-*#^4v1|FGT1P! zrLR=fj3>r_VaFt{X^lqBWg2cg(x%}*%F169M}O;+sn)o=Er)aW)$c8LpRwE*U!2Q! zcOvtA#o*VU((mxqyu4xR^ulkG9)HX`_IU;Yi8FS;{v{_kJM_Bfy?KY(nGF+m*k0XX zY`XpG=GSr2VRyGltZNs!z1v0Z{={`($|c{4qzhT;uD_!2vik3~1dr=WwB=a#F8d(& zahbEnx@-A`%MaSFTz7oIyKQg`bJbA$PYPM3hw3?8|ERTmhjlOKzW!*eC)WQlbA4wH?adg(S!vPk#j{{WK?)meb zUGiF*!R(g#bsD_ySej&(^m{MQ=kA!uxWzU!GL_-QT>gtZCaX4|2(0a!;CxEz>6Wi- zXSC)kq=ot|*sJ1kxU$PqspXsCu5X;4Z;hXA)sIlvBd}Gm-&JAF6$`PjtOOqKklDg2 z&K@d>GdGCFELp+wMp$U^o~VBeeuSyg?PlM6YbB$z;KEMUpolvS^w}P3Q3%6VQ0MUn^~zpnZ3nf!UjGLp-lp2j?9Y$ zws~-PNAPr5s5l!UP>FPFMG>JLUbe#vx613RK|okMut!Quc@KzkkyI5!pR|^N-5z_zBC! zeg7@(`R{cse$$WZmwrl5j{kPar0(dG`%!;Zom}6U6F2>|wAlX4PtluJZ`Z9m{^&mE z^8MR?@W;(MTR-LW{3oB*3Do*`{JZ&Rf5e}CN9(u#U|v{v;>rHXOv(F?pYs1)T=H** z{Y2eAu_yj3_m+LO_x*Rpd-adB$^V}&z53^U$-f@^>8Hhue)h-w)84#ageyMskG8e45p@pvgL>H-nDPd{v?Uw&6g?#Od!sgI)G~ z_s(7wO)swG>^x(5HAdfbwb0HvI@2qc zX??v^r{QxpJat)=!d!0Otsd{xXJu_%dMfp^w?gICBSGG-9H%c`EqZEvRWq*2G4#X- zF2U1Y-g8%N*P0ZWy7IElR;jW@e%q(q56adF)$|Wt#>L>8wRY($*FUDyxT3P=maLub zy>{s<21n5*%@rG#zIs~Mwp2-J-ioD3%d$SK;$0Os&wN(a8-2T( zr#|!$og6E~#j134>%R;Wfz+b&Tt}5=yqFst`DXpv*vIQ*&R^MV^PoTE+LjWDrQFX9 zcr{|5-+!Q=)4`g}oqhP~)q?@0iJI>kPl%{#OLVa+N&ngEQ)4t)TZ;So;+;*JwzD26 z3J5AKbXZexciD{n1`*-$(Gij167tM~n=i#j3eT`?Ub*1x7T<#bp&N_>I(%8UuCrw` zPdp^)t<-oRC-c;&t5dzRlo;*HX1v@G`I^1jPyX2DRodcgOcPa&y%eWRshz@}WE3U0 zhVN%G??i^nE3PdLj+R)--srS2$f)>~Nu{<%&-9LF8zCY@wCF>M+Kn{H+b8aQh7_W5A3V=T^pwp^KyOcvwoJRmiK0| zb-FVZA3o&k-=1I)qw$GR{oSuus}z>xyB&IX!zWWyaqi`*Q_|1P*t*gvK%TqJdBK4h z^R7m1df2almj8{|US-wNns$WadQ*WLSD#mNVB<`6A@f6ePvf4tZ%KUg%vh6@ypUJ1;hWctz+Iak8P(@Dw|$#9?W(Y=+1EskE2|mxy!y6n zoAtBq;^d8X49DE$CcfCy@L`(RjS%@BmPH2xggg$UpKJ=5Q2AQu;>j4o6Q~=tcrVZN4)d2G?YYj={{PQzj$LE8sM*x&Q2vH2;YSy4yvvFIQ{g@B z!L_@d8`TspK4NWFe()uj&3nSkAA+)mVHYo2%Qn8OE>e}&w>NUBXSllZu0Xo@tqt0T zzs~k{+PL9NvebPso#0&+)1G*^haE2s_iW&FF3whdXthG|*^bNIyL$J_Kg!-Uvp3W1 z;gqyjH_HD^WM0FvbX&B%uHxk{?T;)sZggvUa3N*Qtc{jpGvqpdnCoYBTs1$kpu1te zpUz&dXS^QggynAe1Uhn@3SAw#;T5~#b=}05ycMcXeOczD-t{weE8prc+sH{eG1P?Z zw`l{f&DxLQQ_rMGy(!S0GEGlU^S(^iPxGy(l$s~Wd2X6<*DFSKVMylAMF)*t;~GEQ zYB=)o$eBp)wBQ!>%st{Yr70QlL zuN}owrOH}(;=}EOo+irff4n2+p9f3c-t(vWf-1vv6R7h@K7Iy8Jw`G3i4#l9Aul+Qq2ph>LpT1F}wSH5j zrvB!a@n7<1^WICioc?8}Z~TS&oL{r{CBC|Q=t4~W7B;`L%kp1Z&z>oI!h2(k0DnPQ zmMD8*k6>ftDyz#O={H~Hl=iJWxAkh}tD5NChl_K*DsK&K(?1}m^?FI^LJ47wTd$N# zH?GwS6h9oem7}20Swn0Mx60I`B_Yu-&t-623-f$vw_(S*@R$6phYaIYeYC|sEL_yW z*{VFdcH6FySheY=XMWn}{xI)y_!s-=zY(#CtF=>^?E}MazRF7cDwVjkK0Tdv({}Bg zU;4F~tFm)TW&a)zxqkZ+- zD^ZVl%6b!6hYkM7KY(RY{SrAu8_I_8nEwqn+y zr4ROOy2dZ;HSL@(cY?J&>key;^%rk%N{ab#v}51iprBJ8Dmp@m)6YiU5jWGktvfwS zg6qpv{dtj(W(U71KIc@EeOORl<@~@e%>Y{BI z$eCPqHuDeWzr82Swuw9ZcFa*`;YF9imN;*EtWx7%RCMUKU+~*aSMwBa$%}toQRQ>( zM)K!0yUSs|t0WK1e#>sR+U40r2Nlq9;UPrP>=4c&LNF~V6z z<*r%#)%Ai4YyFG_dX4`|f8De;E^z5Cam6`qOo}G z@6A_lzmkpq>&JGyX8#*mr=b1r>n7ZZSsuOVXH4Qdex^oyE|#jyd0VoYLN}yF|LqiP zyHvB;FEV0N#Wf#|#mmogUJ0CUuV!2!bEu~({J_o2?=@~H2B~PZ&zt+C*x~1|gxbA5 zVd1}C{h9dnK!}3j`uZY+c^|e8IY-g=u-$W~}OWiIuvxiAU-l=}^MBqx{g>R3WSFC1&7yhyqymkOEG;^et9kZ^EtmK z#eO<(KD?57Hhp`|trH%51k5dc-p#$d%Y9pUiQj8~1zGNc!Z%pfOI$sw=q2lax9Z83 ziZ4H2zh+i^uz11e!_&W6ewt$T`SI?TS^Ff9J~M0AT6!x=Q6@EE`_a0TwFkZG-#XQ= zaoabaHK}OI+Z}y@cdd1&GHJ!=v(7s1DHS~V8xsA=P*Ka5eQI-&mFlAGa|s!_64uvqrk;;7%l@d7qjJ&U z15&!(cI`Pt1u?7UfTBe%Smwtyj~i!I^4x!AmYYEtWR zJ6M;L*KODq<`?!v;X#VU|1kB!TpMqu*8%sM-p$S5YMcM+k@SrQzrJ^0uWy^Tmfz}u zwbtQ|Lk9yw_;inC>P6h<+^l*j{?bBbqosO!-1%45G0y((vXp0%l1=(ko=CIWWEBZ+ zmA;$1c0SLmtDnre*W=N&7VkMd+x@k!J-yv|Z|B;tduo0?+B9jCWrF3+qQv0SQJOyW z%M2&{Fp$08sIsdp%5x!4mhPHu1?RFN*IP*DE-n&KyVUB{0aJpXa`vC7UD0{)U0 z=W`2lx~$$@voIm^cKoiCvPGRDq6XJ}Ese`!o*C7C>+zA>)!90^bTZGY;$M&J9=La< z#?Fsky2CHznWcN#=Fa?opXTl|5m+S_`}InK*UI;OUJ8ru{;c{xhmZXWyJTlZl+UiE zOQ&2t-i&(PIN3UOz!(& zx#_H;HSc2QFM@`(K4Q7kgA0{{iq!gk^H_=#rF+g z4Cg)Vk$L;?NYSm%)zZxI6WRZF&Oe!}7M>Sh^j^{U`VHqWz4r^Z-1+-tZN{=Mwkgk_ zyQK1wX;^NmveF#3pW0$U37BspVZw( z{aMTYvHs95dd*j!wyo|&nfb+rw3EYKH++Gil6Be z$Jd(OSts44Ggan#E`A|%YH@KU&s_K5Ozx={`d^6bn(*pHQcqmd^3xyw7u|9Uzo@sX z?c2qzUvy&q^)K^&5xeX1{*vw&&bwR;_l~jMJ@>MN{rke*l`3}+Ki$GFWBRFR*YxHR zdGia+58f!=bK?KJ^$W*+zulGWwx{?nB=4F1t-#py^W`rVvmg8j@j4vGv(18cPyeHu zZ%l{SDt=qt3wM_*=v8cbv1X@vVB~2v_73X>;Tv~eZM1RxGLSOi}VtIqS)%D@&fwH_f~~Q$XFe=Xde8&zlMjpIqTzWxZjx zSkB_ss37jGOVYMYoDwiSR$pkPXL6wv-_so;9?6|QM5aFuo|W;kE^1nVdF98Qtel>@ z`bNKZe!rwSS+`JG)b-x-!tI-5f3I+wSf+b3O?a(_*LlDCX-1naf4_9<_=_t_yC=T+ zyM;@|U)w3!bWXhe>Y0A}uO{ZEf4|{g$C^Ly;g;(S0m{4wo9otuY*?rDWou8`?P|?{ zmeaRR+HUr(e6*G~{>D}S+L)yAs55p9>x z**K>ZI4Sp9Jem`ma!KsmV}X#F=U;!dJrcMx*z%WoFvnl%C+p_tFMa&=^V(b795L$_ z3hwyF{o;@LROLUe0)Nbu-{d;3*v<4}C+ENCVJzE!8~zU5_ClfhW%vj8{9^xK9CiALN?SJ&P zV&7Ev&u{0P-hJR0ON~fA2EBanGzTXRyiM?ULQ|ZT=;#CmWMaX7n=Kn)e^~w(GIn zJ%gc7_TI&=Vxx&i3T01EPS|DOC03sCaBbBzjr&stcgnv0XfwCts&-e*O}SnJ;qN)0 z8x|bDt68P==^W=xz2keznoh@9^({+ytN9_Y$b7|&G-lPl;FGHQKZMWtEPZIxTlCY# zYMTF|qiy`jJIc7-?SZm*wJ&hqUg!XYt`OAc2*@gpB7&G_)*wVohDbIb&vowq>EIC(QR0_`I_|qUJp5-@fSwYaH&i(en z({(JqZZUsZ}WSIKnqUH$)Kbd)%)#lTrNnNii z_f38g9~HKtUoZK{-P1E4%n-O+e`ZVXGf!^ErwXx}uBYsNb#7U&^(m#=;nl0$pp9=9 zXD|62^}}$o@QxGb_vmqUzn12IpS9#+s+0tCaKlAyz8+~Vp&c_OZtC}peW0{oR%cG^ z)9zpXE|cowgZ^&jg zx9J;(KQQN&d*P-QxNJrLaj_#?w?~!SaxwRHYPdP=gxvP+r{(gmWj;(U;jW3ECjB+^ z+1g$c1;eW7nlEK3m!j_UU8tY6I=*vx$@KJ{+b_HR{J73~N%pq5;+Rvjl!LGBF-|>u zX7??@(xSs!zK^zu2z3X0+?nfisB-tjW3SCW1>gIybWfrGZ}WZCnc+s?d=|$Ee3Fq` z@$6DTsgZBU=M|1qFRErS-d!MeX>XR`-W8`_=5C#07k1hrcI|_MS*qeIFaKcK8kL+X zWnv`r^LNpbj6A81BVIxB;*+L&N+~wAW!7++`0omB6nlM*OQlFRqabanO1iJdnIx}8 ziK-V0w1Py~d4)H0y-9jqcdPNPnbNs?(T$Vd?c3CJM{U>sPC1Pe-M7y-^Cbl7)P-Dn z6t2vcvU_Wf+@$g)yjSh-RQxEt@mjgypmq7V>tWUgN3&#S$IaNu{aF2jpKQ(v$f|9!7i#s}Z5%Ub8) zyYadw&(UAs6#3`q_a0Z@+3Pt^$A8*yKdo!ZuFvXj#ZSyNyDVJ&@?`Uukcp~)+0~Z6 zyma!_bhV|yRdHoihm`KPK4X>3v-#6<=J(7Hb-lISj+(npbi95fIdk!9;qc`LE2qy> zzJ22Q?FJ72rK?|BF(fM8bu7Pp`PaXipo!8M1}-IxB9)4jSC3u^j&=HbHFd-E)0*+I zjI(!kEnAtLF>lv2vDL3%hLkFcR0$uwVrJ!?+pc@pDSY+qmsX|PIj^dAx!z?gFSNhA z_T3WMS9-Trzgrgn;AiDl=55zJ_J@DJ)c%T*w?%uUx`++i(@rLpB$J5e{$gEU>P~F3 zYoET4rAwsRd%1Li;Oh$8XS%KT*Sp^MdcaJ3C!gx{Zn4Wue2dTb&M=(v`X|qqy&cmW z+>1`1FA4Hq@Ym3NOKa6jXI^#IN*RZTV%{fp=SB*bs9irG{mAm^(FH07a~>SIHUIee z$90UleEM%qH0)+CU+sD@gH3BS_an`ve%)8&I%?%pS1@03xAm*NDqPZ2HR;&u=96DG z>3_H{?C5@Pz5u_Kj(uj~j3x)2g)ZBV3pWH+G(A^gteBTsS9eD;y+QhyBED+RS`)WO>8sJ)6>*KuKXrYc zg{}%;9~iRNFMW0S3!ATObJyQnl6@t*WcIJvOY!|nCvRykxTv9ZG4Ni4LU^|MVucMe z`d;`vKd!us<9nI=j*~3s7H;(1y>v$3y#qaej7;LV_I3+alt#_o-CuWBrRe&mxOvk* z?Ed`FD*u+-(HB2>CvSUoQZsDsbfM#M(_%E_tm6xBoqVxp%f}CWccxXnl89hk`Tb;w zJcC7hM#HZOZ7cf~Hut}*_{zEHyZuV9+EuBFh3O1yTy;Dq><;s8WtefbMl9vv$-7p` z!jqEI)ni{;-uSw+ChiVfU-xZ?^Lw|HohaQt@nx3E^p6RzjSaq5o|264kDao3(qjEd z3*K^TB~3Nuw{6{J_Tu%E zBR@mgYxPbXbaziayI9e2=l2CNE%UfF=BFttsGj+ha;0j?zP6J6j6(du{D&9#9CrQ7 zW6o<}V{*hm^SH-y8|B_ly*#rrzARhmrgqk-Z_!RSc`d_Vm%Nm_SM~lodCE-q-kX|V zY?n?PzqdVO&(tLf>(w%^*?W1tkUnWp@V%>L+vT}Zw#mU4jFnhz*IPzz)l^@+etFoY zOwpx9eiNVZ?3<|mY0mubK6X!L#_gJZFX~>!k8?}pXDqvJp_R&8%kq8Ogses7DPIcK zq<$&r?fK{TxL7pkqnp*;i-&fI==PM{;&iL$fA;N?{Hz!KeA5@ru0EN!WMb;~NxL5~ z?3wgK>F?fUTet5#zmOd+zrY zli6zXL@tLP^YJrIQ(s%e`sw&ujhLBoi#lr*zhAn!z`U=;WM7AVpSu3v4c-wp@{9ei zaR>Qb3-&kqry_8}{k@lwguUnUAQj8ZnYP~2n#$%+S5Hf^KkxPQea)Fk`|lhv*ZUjG zUFrP)=cT#p_h)rVOK;%a>L9!~JWN6JS+Hj1`CU2T)6)0M5o54f9DKmoqII{u_pH2S zSJo`h^$eNGo%5pzCw#?1guwcAe$8zJonT#9O*YQ>6kx&K#NPB5GocX58(jAs|){yKUz zz7yD|)HgBti#yk;4L`j8dEU|Hzf{-4k-2bVaP_2V?**49KMP%9Fn8wWFM{$f^_{9c zx5^YARaa;1(yZAUd}TptFNjzxVyaLndrG7|MbJ{cW8R%TdynMWx6heZ6!47ERlWZE z5zVNYTBE&ElJ{Nu?Mha3{@XU)u4YP4Y;Kt_!$;{aLgtt5Z>=v?-XyokUt@OIM*4izL$)ttNSx9RovBJm^#58dmFc3cU{m@l$BKlTrkuMrc+$5T=3(%h_$ z_f6RI@sP)E@!7ctSE>2@Uzqe}rf$u$x2*4(O8)R)_`3bQ`6tP$-AlfMSH>LJV!vQ5 z0|NsyBfj8pB{evlahwReH0*Y;bg0Dtxf3?2tZ}%kbRlVX?#8xkp*2yQ+mag0q?p9G za`#?IE#~kx-~BR8*dhA9wN-6_Tlx>?Id;8iO;u1RkWnzPVw;cT0k=g$;Xd(Ab?P@S;B z^WmzV?F+nSOkJp`+IV_~bJU?dJhI$8Z$0;|nDR#B)-uJ`ZlO~<*qq(i)DBNPyX92S z!cFOtVw;TC9iBF^Sy@qkaf7R*cSM>+z`}_}_t>6(;k(46o*Z`1Lvz_vjm$=ws}G}_ zJtL#+9v>@aHkUm2&p*baOgcsyNdZJIvUH`O`$-?m2W}m*kejrI(iodx>Z^ z=YRV1`aZVY_304Hzi+)ApZoH1il4@@=!$;hNKQE#{pEg` zXSBzJqStwlgMuGDy(V|(YR8I}^1gK^*ttTr)@B6TmNxnw-jemCyktSh`J!_Z3+$c0 zP0XLxm9BAX=X8gg_4_~6Kc4tEe~!k)`ncjxPm*?Q*<#w&-kH0W^=tj2Tg$WG$MnDJ zN%lGa!EoNCt1F-Cn0oFqnYP2iv}#sge(QqmobKJc_c-P&%H0WmY9H=Y#((L|h1L|C z%DzLlo@8;f@@%|YxKp?*I&9gq-0VPy*&jGt_nEZ6u(am6c10zQ@z=X62bASlqe3&v zy3*tp{ag3W|KZDB?Xz~9e10I&yH$m`ru(tUDZTf{Ip?%gD9m@-kkP35AxVC1t;mP6 z^@;bTvcf<7(^?|BWzFI|(S4>r!UOzk7S!<;U044QBlkN>K&bwWw#k~sg>F7Kt!Aao zcyMjw|70GnbtciS4~%6#IC$JS`0tnh*xrvGR z`LDvg|KjCu)_ITk?;MK%AyB`2YT${(rkCEhh!=*m2lcXC@0D9+lVKjR>bpUuXwcT! zyWbCJU60cA%DJ`Db%xdP7`>*t?aBVTXD$Dra*?4h_sjb?3b(vPd`tg>OTx^Q`t{RU z7#MDI;VTJ^NGu5<)xzGroHZh@-z@&Udhzny5@7|!0}c%j`8*XGP6_fo)QFN*L~j^_quA$>QB|{cP(G8KC|V; z_y0fN*R5E$a$QyE*LUAnS=oL4UCYmOpdi81bXh#ReuKmYm;Z8r({|NBwJudn>S!w(z$`f4Wn{>7hIeV#}EzdY*yzT#=E{_TVI z9uMU|^#}bp{zq8<|CIW)59eS0WHqh#Jp141NBEUbThHzPcqs6XU~|3q`S&Y+Y(Kc) z{6{^aG4?<(~XgIqskI|G8bx5gZGeDj#YeEWGXX z!l^1z?VHf74*?5<69v-h7e#T2#_8`4S+a~PcuD2WsY-VRWO*(Ms*B9!nK)6)$TdCd z{Gupv8LeHH&gZp#kX&S4`g)?)CRcywFPB{Noqy~NX!RDYJ(AhZC+oDQV_)1w|1aOW z82_lp@~9Xz?@@B+x#qeq{7Gj`EYHQG0s1a3jG~8m4DSdimlU>$U+YvB(UsmjyOwd{k}IaP{iA`6a7Q@!6%#X9S*pnUmh}bIVTFT@f!@b(1D4Y6Trl+UO#F z{8I5s@pZzdUz{!6WpPh{v1yA<%sqxSCK+BsTC2~9i?p%{uwtCI)r%(C+YcJJE|G?BV^93CRsn@BQG@{ z=|AGhvJ4iN<}I8i&i7&Z27&a;JBmB1zqVR`KA7})R(Zp;@8QmKvO7MP6z)^hGdR*} z@=wV*Ca1%jr*NgB-r|kZgU@TP*byWiUU~Ft(q!>_P7jhc-&oYWHm)K(Cb=VN|J}kzan5hdT!L5KQ2zExhI31Q#7DdJH~iPXGe5$-We+>=M}d!D zzP44|5a@sLC{X{h&OiHxPfp!6J@fj53oi)xOFVktR&hzdKk)G7wu-iS=c|quKdMY> z5Z_Z^-|1!lQEBZT)me{Io%bYlg!6usI(g=G$exK>_eAmoKk{qcGdp74R&ib6zsZqm zlkdMnY8p5WE=~Aoz3`c{mffO9$y#;`_2vtGD|z)v_^RFFZRb0U_bsTc_w@KBe)Zmk zqt{pFEcww^SL5CN>zu%Uvm@Wze(>kbxbRc+e`naYrQv@XK6lC&i0Rl}JlY@UR>gd< zdc_B+N9xXhd}{w^cf@zx`fq$>{g*#y1@=on64*Csfp^=HX?G?x)p_gB);4vn+T#4} zKhH|(O9v8-j!uYkUKVuKBxRQ3W!{?yC&=>NJgIG*vP>^9nP4;^w8g@@-&fMe}@N=ent>+U`beQ*QiLB(k!XlZXxA9jf`-j>}lcu{LYNu~n zH0kE&uD;pE^_SK>`ta5Zvt;ykX*mU8krp{M^G19zI+ITtaZ!=s4R2e` z?R6-W_v*n%&*low6Xd+szWTb5>aU~h$E3JVz459v*kl$Wd4w_UPDSX4BU>M`EqS5v zeL{pW-=bGcYj(9=Wyzk#uKabiQz_@+M`u}8{Y>q2wpztVu25qUQ5M~$lH{(qtb(h| zJMiwItyiTdyy%uJ;R{*MowH(oyu1$gwa|7g<}1RIEA6D#t>zB9$S|9+P*^r*i!Q%V zP|zu7?QG_YZ5)d#LLS{N{HPkz`bzt7$828K;H0e*(fxBBVgzO<$0byjPRNjNH?a-a zujO_2M!w&sZ-shsJ%(Ywm%oeHsTHxa&8+v!JkfPA&NFzfxW5%+W1eKt`PZn?)<>%K zjcuJnu0t2>Tl{WaI+bu` z>$Nv?4i<8J4LjfTL&!S#{j^`J=2uT?KJ={ThA8`V*6c$U6Anqoe7!MeTGs9zslk){ znlIX%uv#jaQsON8PC-@RX!&XBMG@DpO*(jBo5rWazpDyNH>E%DKY!Kk=2Fp2b&~{P z=6G(6$x=>NL%TA2S1nLI3=7G>6R1>->%o0({W;Zq~Y?LZpT!^e=d2lOTk;i;H+hmli%(P zqZ_87fx4SwRRnljvpv;C)~@HdcCo)|(a-;^w{{%4TBR>CD@Ic0bv?ieY0x z#Em6fK^Nj91*29@34O1kEH?E_QKshkE{0#uCtlUY{?_E3ZXU8uYgL$o?45-7B}e@x zUu8M9?uluzqHg8Ump=PK8;*U+Z2wWc)>q{EIu7OZYio~)m1te`Vqe`6Zf$m)XQ9Y* z_sRauS1s$>*+moBO#a zY`RotDl+4Y=vCgYt7m=An4U7L<-}4&zYK3HJ6-ku$;`7Z3UP5o`|Y-HP@kohek`t7 zBPPJ+_TIGo2_DU13&f`Dt?CH+dnYl5nFMvSu8(es_YwhLr~FP~AKoUl1|#m5OV1naC7{6pAY zzYYw)y70#1Lq)~60#Y~TEji14d=JCA-kdtJN^8!p zx;00wzIvUKT<4?^C0r?TcjX7G+fRL5`TBMT8VPiMIo_(Dxqjw^s|RoWJ2K<%)Zby5 z`bvr|8Kp}*ZXVX^yzy+KG5@tm-*3!XHEoCgoEs~6*E!3D{d1YUTO%r4QzWicDQDM( z1_!SH`dWKJ|H>~vu*P7M>Q~d;wAtA=uQ}#^Y)m%s{Cp-O{QS2K+)S4@UJLL&rD3Yq z{IzA4u+WYjqEahgo=A%LCn(jNz|h;`JoH7 zne*io1Y$iC*Yp01U!bEF9UdJbtr~dY&2sB7J)G5kGCks4;a0TqcEM9&T@fqBud7dK9QbgBoq3|yluwVo z?L2(6JDS7cw1BHSyPk|=a$cg_oPAtx)ZL6JpOI86jEX(%&k4*?9Bx^?YGkTGt|Mg?;i@ z2T#t<2^BsxF(r7iajg5fNcHNrqAlscZ-1mDZH~|slT*RD>+w zzV-2N^Hd0F>G+*;F6rslz{RcK)=V=Ajs234b7sXg$t}ElgeRAEJP+&Ekyk%%8r^+l z_2u(LT)Epb9Co`c$QO!D&8?busv~8E&!a!Pw7xu;`)1+7Ct4ke%7T`K8Uyc*$-pWD`Dnn#JBLfTKi zw&o|TG$5Q?$#m~&)zn#5F{zkuAb<^LwDgK+H?z zO!d7K{SD&2--N1frmWu(?)yzjbp7V=zz4#{kDeY}aq?b5ev-jlmC(FR+izO)SeaeF zwW425__J8Vo!9vj?|%zUlew-jefFFATlRdv@muY8!`=K%{F$2a8~c5~asIxNGJoTF z-*2qHFQwey^xo%NzSh3<|A_{B?ppLO^~~JoHJSOk?>CO>D^o&^R-6`H7IQN0>Qk-Y zwkKJ!>kL!3t~nTR((=ZM@7LS@THM}MkkV@(lin`=wQkK?4)?64&}D0m_MR|U7jy08 zRi3tEeuaNlGkvwNdKJF2H(_eMv%#$Q;hnbjYb^v;a)t4lKIJU3tSVWXB74zp;;*A@ z*(vtHZYj2+C3+8zoBp`y_QQ8u|6O<96~Z5Ko0nW>T7PQwuj9%6Q$(hQ9o?mOeP+>K z749o~>fzJXXMIws+@$Hhuy&r;(abNOOMZ$6&r>|_(tML^0n7HN>C(QHV!d|J^O8^P zKUM5oDfib#zOm3bZoz48-^z)5ZcLee!dtRLajDPm==O?F>^XbBIx9cmzxs=lar(l! zt5(XdI(^!=lC^htP+aP%)lb!e^QJ{}oC!1e#hDP}uqcuBiBxP{_NmuTzKShc{BGv2 zZ6{Xv^sLG8@Hl4p!ft<=Z*E2GTKkE|*B&uzQu*Gy!hMR-Psu+%vG)>A<$iLDz1Q-t zYBxWx@6OnJYfeY|+|G5)AB4A(|5j| zZ?E2DJ>(x4S^YmpDRN=bzuy;`4}9zFGO1hAd*4^))n^9J7tNm(pG^9c!O*(kRDYe@ zid+5fyi{KBUtPS%;@7!l^EBnB^&6bXE_L`5V`%pzuyVm##lriVc25j{S~M^I-|s## zMVwFR)T$M?vtuFZ`NNJ0W#EP~0GlUhT1@0PDie|B%PBeZR{3(;^ zbC2fysppUOq$V}Zay0*PVb$s>wg(yx%bWjORui{x!D(^dpF&*X`?+^cyYIW^_okYo zQ`QUp-{qyAd2fRMtWUl_r)mCIyl?i@`co{M^O|B-p-pYKJPK6b zT0JV?@FZT4^ST9#OY|52Z_2B-q!_Oht_j)pe&(mzpNyjNvpy;RG~6`*)Wpdl3qLAG zKjvQ_@QeTFbK#$w%`<~nGW#{p+G_VIe&4~WXq&YqWsw)BEd1A1(7b;cGdjU!=<&sv5ZC$F_KDz8e=O`rq^J3^QK)d*+`zQ{q23 z?l`~lUG1w+-ogL8>rzjxe`;>HNImVx#L{I^?hJKP*DqXnc0s-Ne&eV6pMF=9KY#JQ z_Ka5(vQ-P!cYgXeqiK7GsK=d?7p5uSlDqKR;5f@kN4I9v(h_kE%@ZcSA2=*z>-;Al z6nd%u9)DCuePg`l-imd>FIQZdawD>3|Ai^`9x1<0%E&fm)~HFnl`zr`U!f!6;O{Zr ze&(n2onh1en?BY5RG+6Mr#9dB(ogMXyN|ts9@7Oo=6nf?T9>w)K zWnX$#t_GQ2zH+HU_)pm)m55YH?$%&)uao&lFShQQmX{^FrLVnxesb2_Ej+QOUD%|3 zo}IP7X(SVIYww9l1+U{Ljxp~M(%sX&=iD2)qgOdp@2*;~Dnu{V>5j3X5T^#u%&7ER zp>CcFZgnx_IArK;)k)!9+r30v;cVPvoy&)w#3t2<&$kS7ttnMqz$9A|{JPC&-A|vj zyRRL-vT5tQW!Jo4_wsFT<4c)w`RAmg>$S8x@&$8yj5z9^&iuLdOk&Qrcb;)qU8S-L zYnNSXpLRF=_44e$zPSvBpB;W0YULZTz3eQWST#TUy*TUDx=hZgoBQ6aV(%?jr(#)h zf$d_7WyXUo2Q#*AiP8GBr6yR~>1e>(16SGtZx@8@xyA98BiLGKZ{=H!+$HOJy%ahp zE2&MnShZ0;YhtjV;8L#ZPqfX#!)za~pCWzp&)&!9*`sEN$4Z|~xRBU1cZb%=4SMHx zv`W35T)g(EQRV68e^VzWG^{BSspb0LdC=p=m16?WjQ^Gio!+>-Rm3sl#EN5E5=^`p zd~?^B^)+tSk;v`15)~{__q(MtrEbq{lcSq=uW&ToVt#X*Ta4eqWw|%6EYp4crPJ)* zmA++LOFo$U|M}LTdvNKEsaD628qE;c)NA6lAj4|WG{a6a=d4K!m-1e{dNkPQtwgR; zv*FvOM-oCZavK;GvX5PRUYDCSnd6;<^t`i|PhL7&7b9%-BQIE@lt;TL(1>HBh>`0P zZvkiTi|azzoU=Xkul_oHdYQ;?&Bb1sZn3j-vVuLHux~r$ziv*-#$7=d565vIbMvYV zw7Q<3o>98?#Fb@PmrHW1g2Y$2HeJ5b^)xDY_CYzboo+`}zR7aUGMl`nQYA##A#$$d zod?HrUwHq`UK4dHX#Z5#4N()TLXy3GbEkzl-3iM2l>5gm>SRvv?8RqQCx@hEJ$-RF z>+^{`iDIdwri3Fqq!TAT7Uxyif6o2j^V?fkQv{OvI`^NGTP*P6NmFI!j0S~IFZZs~ zHQDOAq~h|lUA`7kZK~?L)~T9OA~AUzCjD8tNt64JmUZ{1l1m?gg@Pi&%3`l;`Q&cg zcH~N*>V&;9LOGfj(yWy2-`&0)`?gM3R3P*0p3bW!M~j@3VvJKd_M5!Xj~DM+lyz*u za*WOn?%9Azr>uq_z^aYc}br;Pu8!jD;^jvtMA$3{VoHCo{#IA*J7=NDF z82T^bfCEpAzs;ImH^LVdD%Y;LdMrjOT|4Xc!~#>xCqK`nW&fShxGhfY{+obc?u^r= zyu79RWD9?2Gg~x9`PwubeAaS6wXx;e-_YRImtH*U)xNNN>uvqQ+uA<4s{0RK37c4T zT4Q@~$&uuZ-WzT2?&jVhCV%^;Jg2R%?vjNJ86s%`R&lLT5rSHq?RVV0e&_C^yT5u) zBzJZf=S^GPl99V0D)PlkG1a?X8ZQ-H|5WT;zIrk5#1F3+UQM5J_E)sb>pKy?+25*P z$a6hv-yJ;t;EY)v>;>xr)U;3T)SY{d=l|l!YMIN5A>D@@jchh<g}&PS>}|%PPza)Hyi2;#^Y{hv@DtRzD`qJrdBr(ZW5u-6Z3e^Vg8A>k8AJ zZ{cb=C-<}~K=+%`)lFi4I@-E=bK72-$3=?=__555TKwT+YOmr+gB!<0Z@!uHXj`20 z#ez3e78LuP?n@RvFKni8`|1L_&8$s1*`6zQ%{sS6@VoJ(S-ZrxCkv+38oV-zex7aQ ze)reqk7r#<59B7~HkN+AapcvWA5W8GZ|=FN{o+%?p?i92z)`PNOITcW$*ck;oE$|aX}otbmfzfW<%=!7FU1X5VylEKl`>GEIqr;*l=c9M2OL8I{~j<9VzpheYUb( zvNG9_df=Cu>sci7oVn()q}5!-Cbdgztpt|Z_%!Z5AK~2)yWEUJK>C@x(~3qB`wQtd zvblz#S_gu5zI?ZA+T^WQWU@BBnR7I^bL#P3sr`8?E@_=*$!e%>GutPyB-&qh-&5tq z52Wg5od0LF`seIg*Bd-X674MB2zwGVqLXL$iMB8T=AvV&1>grsNVVXW=+MGn>#~{r)9qtI(cT>+=2X}h)Toxw>>KhC3a2Ui6g=#nonne+L% zuk74E#;aP+m2^*Jxp`7nZtfWYbw1Cu?$|sBu2}xrG8qeWitGG}CT2bro?_A+@i{A} z*=*t48HsTPwO2}=^*r}H+gdcgEFx51q3TRVe9MJ>=Vw1^x_|AsmDr@mC%^C6RwjCT z;$ywkg}bkOGHvcUJo(g4>)g3P+wM<)J(XwM;~w1&2CrFS=jxcKFL_XFnY&}>jr}M7 zR(ghAnwPO5ob{FWp@|D@i}&sd++~;bKji+8>+7~WEpRegeCb^DTP-$WZOwe64+e?t z$`4+Ka;nccyRS3*t+sOM>wSAN90MZ-KklAuyG|B0h@hyy8T;nv7ETpy!`kN@uQ%B*cyd?%#FpsG%58^Sj`?v~ z-TcM3eeSx`JlzM=E$_eomO1y&(~a+KII@eGq*on&WwQ8eu;c2@#XGL)Haf;sPQ7t= zPTJcOb|%wH3oML1ZtgY>Irnq2%|x5EOYb!H32HwT;I&%)cJ`aw(%;#2P0n5STIaJ< z!gJbA3r_Z>D;mytxqr#Od$W{Z^7^SQYwP|`S&_fz9H*1yr@%L!nKe^(2u%iN{xy<6;;}j`!Qhe>DhrX zn-wB5BhU1my}jnjr7s1(7d}i>EUj z%Xred;=d&3DOOb@Uy=U(g*6rt({KDC@ zYX9+j;ph1aV!!;kAopMJcZ98d;`~+5)87<-{nJ#ta^C->_?6GEzmfj>XIky@dH=V~ zzrXqa17rT@e;WUGJoRVLkykOuxjSh$dy3v|UMW#Itr9IBt)LYjf+o(=E^GF5jaqky z_vOyt3!RV3z1Sgbm1xSmdgkth#$lVajCQ?gT(^6nH1Fr9pYC3m+xB(A{F@W^&_t4gR8Tlb^PqjA5Z)td&N9m2Z~#$FJ9 z*S2p1H`~Fz6Zm&0TD)nTSYYqd;+`NT)4)~1GwtBx08ak{S`|WB4>UUtT;9MpuXXZ6 z%OBh}{OO0g3l#UTgdcdlLGoVO|D!j3xUJuaf3vUombib@eVsE0d8CW)7QJt6^mkyt z^JM|oktDu#GiSXkyEd2ai};H=X4$%SA2z)mcXM|1{5{8avw-^p@7~J-9dhiC7P>9l z&6d6Kpv>+Y&CV8`?DI2sR^D{3G4f9KHK=emR*)5$z!~N)&2h~_{bzt_m7+Lj{jLtg9x&-6~@Htm^cweIenCY@saCHZXs^-kR9i7juu!RkCK z;YFIq(JD7bVV={M$`j-tbG|aRxt8v-=e(eAfy%c)2B{bZr{51(aQ$izIVW+IW%1@O zY7&zJJxqJEk~ePSK9;Jy=Az`|jTudx)el}cC7*D7@z~g?@1PosY1Kl1xt6{g27>iJ zRJJ}av18u-_|vyTO9GG8&FH!8qxt36o}0b_Pd-1|vC>Yzbl$Vimr5?z&TF2~DE)HI z()X=N^Otj`>D=KrF1)ekP)NMizJtqzLLHl?tn$hdKJ#tquRXp7%Q>I@3d&?pt@PiJ zQ!~AGLh425w+ttJGiKai(8$KcT4St8H%^#yE$(8crDbKYWS>-b``VP)on!IA#vCDzGC7eF--B@;5yT;^whuGPM@(RZH zM~n}2TmP2~pTN0t&*r6aZ+~uHac=jAbsn5S{rewO{E9v%U7caxc<-^4$8G*lQOSe0 z8y+dT{(KxWMZf&@jH%P?US5ouf8tN`g@fu-?M|w{H9Ydm)^J(8$83*o^`h!0{3jz+ zZ^&`HZM|A}bsl%zlm1}E*12up9`Z;WIM*WiMn@wxeX-9!(P<0UZ=N-mpZASY>u2Rc zeq#myhjUCmxw*IJheV{Va*KGn$}K{4kMy;ZNwOPk_})36DS2*Nz}q4DPj=tsLec)` z&nEIWL`OR39hlI*aFz|D`+u8V(GGzsCj(M>~_Vt$7l<)g*RHd68RQ>Wf=ykf(Ulq5@B8y|U37@oK zid@3tw;}S4m_*N!y==yCu~&M^E^g*DO?~ zeI~8mdFmGCoA3Q1PQG*dcANG2hUy1OW%@C#X>X!Zp3J_OyN`YD>*hCt6G) zki7fc`Gw8vH}B81pDUKLI`{bIBI8^!s`$UNZU3PblJ0HXBW;}1|;bd`dpYi;&;xz5U?a^9Ix?3v$6+NnK zp7?erYnA%ziTYkNBC3@PX3@-(-`)cZ%fn*(@iDQ9Q|j9o_DsFGdSdV_=Q?` zEn~C6F3p7a!v$A<3g7r{Ai7v$OL&3Jx41qQ{>AS5`u_4gU&LOk`MkjL`vI{pKKYMV z7O+Px_+24obJF_I@;%%&jn^J|ZxP=A@tjU;d1~aH>)g{+TfI|h0xvZ8v)IeCGXIc}IClJyVU3K> zBX?&_d$wsGI}2>|o3_?y%{i5RAhJd+=0LjQ)Mp1mYxHuSrWP>kx6l4*vt#c0~c^cKz9HYxvzPdA)YchF)_i$*WGX-%KxAs5sP% zGwu>R_Rjf<`K`R8bw%2bUT7~7=#=kY!QF6Bd!g`pClR)ZTf+`0?BhE2L10lf@0Cwk z7LDx>ed5@~KWgMW%9h=HpZnPd<-o<9JSEFNE`Bp1XY*r*oM*~!74kMeO*neiZc(m? zeD316VmZbi&i*yr^3;~;d%l}~c8zk$pn;X;I%w7A-*)CV# zCec!Qu27~!*gF@VTjyOvlM*WoH}QO!EO>aiLfiQUzCS)M&X_Arp4aMA#rNgubH!!) zEsKA+8Z^fD?AXKN_ayw_%|B8W)8l!cfA&2wBl>~WKGAI-vjgYfZO}@Qe)HU1lk1A3 zR*6&isiN3wtF4>{=awA}ebLnSu=T{6=gPUq7oGa>fa~|C!i>`$zVFL5O80L{;F)?? zO!}0{QpSv(m2)4ypZjp7T7}xV^th_y`G=?8c_*ZN zoRj_Xteui?IJYTV@c(3*TXs!*qH)j>kHvyUy4O4=emT6j*QCQTXS@F0=NlzbjIZp< zn0<+(wKYyv=cZob%Z%t5>6#4p)_MGwnP_*Ft8?O)mHa=0I=)yLwugVMSXjwF#Ux4O zXwR;sW2|~ug6JOi#RyFDPbltKuMpKOcb8TGdw>5m@3nk6IYToR+H7Xr;-@d=B ztb6tGm*0_>7Bl#aCw@QYz_*8C-u8|A#eOpV@OyGF_C)h{MgDi~I(7CbpV=qy%Q?CJ z)Y$c|U-`HV=jET?29xbsRsUpK^w~3C{bLz%Jig)bkM07tdeO>H@+%DDopnE0o%%fc z#N_;gW&g}fK9wh^*Yk@$`hDiKeX8xx^sY;@7ci&Xh{<%wU%u_!vr{2oIQoNPUb-$8 z%HGXk`86Ztdfc7!8@qyo3*7gLum^cuIBi(5H)r0`TP`NYW3H+ha>;#qP`z}f%?9CS zhwL{DKh|$;Vu_pGQi}bQ^7HR+=})7Nd^5d*VFrE74v56b*B%@EHo{B zUpkuDEQ0K7f&kKptH_si6ldKQlQrT+U6rFN-ZfiknRC-+9r_z62um7B7y}9?? z%584j!h9wy|M=4E$>Q8{$Ma{M`+uEHOK4^2pRn%jYrcrN;)`8Vxo-GabDMKbywAxP za>S)v-)C0Kq#g42Ryo}Je_XDjT7S=CrmcTJK`FSGmK&<)J@o`k!R~_EU|n z)VulW?WDEeb#MM!zvovemZL ze(Sd4%go4^%3RhztbPQ&*?Lyv&58nplda6BTO|c&|E^zh#LDF0dfyMyD>vPry?&qa zy1HbmY?~6_+0_o@ zJ;c4s!*#imtj|QoTGwz1rK*Dl7kS+}-Wj-lY1p|)eM+ZcfGXF+5<|Ijg2E4!3VCvb zgcEnqVENvm`C-BgF8{8XA9`l6o$q}4VV*|YdKbhs8bDNIVn8oNMxp%SV zEQvUwbwp^Jo6PBT0*u={LpI%ZonWgLwkiE6=Ns0IU3*oW-Y9RJRW9myFZjx5Cc&rO zEl<<;GDT)g4gRSkTHohzexb|FkIxruU$yj*ZNLfdK<_07%4RHGa_g|0lRb}MnzL3l zXIIEt3945 zz8cNB?$t9QT_|0~3wpFM5AVw0WO_f(^0H~I@x_WP(kl9YOC$d|Kq`Q(Xm+vaDAR?k=- z5cKTc;}>?zj+f3q_562_?HPr;<|{4)Y`S_`HG1xvDmCwg#SL$h*tLwF-Q}A5a^@~k zpRZT8-EJ4V8{_P|Cf!K5nW1`jckFH5(tL%pMNT3bpPY>%cU61KdMx-D>;84snLtyy~*nRZs%`92kkNN4la$<}|}l$Ndkx@)TKn%Pki3$qiQ z?{a@WI$bcBG1jI~HsSs1s}JwSa)&QB=zM)Hv^!MxO1BPk>~C8EtT?@XII=^*% zd8KwmjzV6_6T54Z9TQIpyng9g+qsYH*35-=@9nP5KIoM7Qg*YUW_V2Xi}_!Uoo|SH zu=wMJV&^x)qTagGc08N^V%~m#?yRr2JdGV}&IQ@+&gJ_LFT8Cz`{tt)0sFXT+~-|W zFEiuut~Be{Wyy2TO%8gg-Hb<2nWtOe1=)0>jFa3O{_(g_2XY2&le=zwdC9e_peDP7~nuQhZ^7{9l zu0B$2qjc}NdKdps)9JAcfG*S34Uy+i*;+(*^_fiQN5U^D*G=DL^5K8nOs&hQ?$3Fi z3f+DnQNY~BnUcoyQIaQQxu)7X(^Y=KL7wxEZCUpwBRh7LX7EAwP5Kq0--J6hueIqg z?UcxVp#8(kL`uDD^%TXA8yNO?uMg_``SDGj+@sYOYh#b*J)smN}(3779L+9=Fzypf-ccZ2CemWX#M?Zy1kEp_wN<$tc|e7eHxxSCl+ zsL?EmUA4}$BIccMzG!>eJx(%cg{Ey=S;h)~XZIZt^cX_0J%huYt>w zl(!i=I`1Xdt4;1SCBQkrEFc6Sm25@!Bnj?;bn2nc?D|rjJdni%Suwe zJBi$8Hx+zw_;ux#ZRdjp7K#2|Y&>&&zwE)p#LXKVgbm zwHjHo9P)~Vt&8NXyBt0Dt@Zi)a~fZ&viIkJ%Y8`&+)JL^e)UEO9P5n0T#jc5KuWH|?~5BWOJXq(Y=zgy8V3FLr9J`(=+zESPI3}mEemX7mWO}mfKZ`?sM@%h_ zt$b)T*Y?rZ}Q5Gf|u6DKYk%@8JqFqSaO8q>X%+C z)ZZk#D_8&eq9-($|Fyf1poHDxbYbgb=@Vl7kF?)AqV_g@^2euB4vEBf?J_>t72>Md zAae1@vR_lY&D58%?b^95YiHc$Bqe_}JI5R69oU#6JCCe(dc-=hLVIFG_JoS71~F}k z(`*<|rLu^f&|rCD6`^{4@rL;v*-te$IL_mfemb*Y;vJ6JPi}6AoyTnbbZ5bQ8+o~D z;s=C3IaT<@@vJ}X{m`~jvPMt8J^zX5hxkfS@2TON&lPchKE1X}@q(lJAxqDxc7~6V z&#Kv7>v-aHb5PN_n_j6L6%<=tzxDEd zw%^6S7H^(5Ppl*MMaP%vV$YY{>ic}xcH0W!xsx|N*=i`|uPzmw@a}8nw~O@`h4+4| zWGtwV_hI$265k=a-1wpR?`IB_FfZu>!gks#EN@ z$x17G-{uh(d9yfX1N-j8>8n^0&g?vsviY&!wz_hi1qMe>Oj#qc`*v@Es&jqtc_+Eq z%@b{AdrO{kuerB(O^*{#$(k1|cU;z)>8{%^y3FiQlJ)e7Cf78=IoYOq`hKqD_+(?M zw^#6&*s{A^a`CsETVI}ezV!P&HM9AB*R3BI<$2$q(NtKwL3XyuquDV6_m>o!XRMj9 zHsPwoIq^*bxBF_s&u&}!ysT_?)xFc-6y4=Eq;fuYirmFrQfV%Au391Z9(U|hyA#vC zA5{3s@Z>am;8lC3#ZMLo=UaQ4(paKi@b`>FeDi(EQzL%7V>5Zc6w)KUn%l=7=+wXP@w<(>K;~ zulaj*S81c^*%O>1S{8rG>g`%iJb+4|(b?LRhaB>PyR_hwy)-h6Lv zzv8~90x=C~@15!<);{v+3^ls{JaW>S@-*)EC#*S&KPMeGz5Hnn&rZ=K-J-%1I_B*m zH_XE(&Aav`SM^eC&qO`n7jw=mVBh|P?|8zh*}AjXOMKfybVX}san^1zv2gNkUmB&( zkuA9)?lq5kcI;f`b#~tpxpuNXw^aLNQ)+T3{C;@NE);0K{E%tK4a-~F%u~2? zS&D?Lw%^h?aly?wJeTLoC9Z|@&G^_djyudV<2;r%IkC%(RV>4`V3(P&-i2p}j^5JQ z5u)8VdrQ!bm1i68MoGT8{>*y1uaz}>W!-YKqYn>xFWg@{p`1~~g1yq;%BAX(os|T` z?YA3$%bruIbyS(s<^JDh=ZimE?^xFB`q|XSzFu@S%X}?UuG|5+zt1~EHSVf!Jo1vq zul4hTLupT}#7=G%IVtK;r0ZT3sqZTo@c5b zY`qnwa?|R@vbF8Iw+KI!dz-Su-+HTWk#Eb#Z=7$A^6fn59C}Z#=;@)a-*#%xy%rfD zv42W@+V5LzLfz*Ma=mp~cIV=>&y!D1Gv9rA>PaoxEys-~h5ET|DzWDdLUD zhD+D{tc`A-Qq+>{toynuNXO~-jjY#F^JG`X`k9KZTD$PTOgXtz{}b+K&3_&j=Ir`b zKdxI+bq3vS5{D{hZc6g=R}Ko;&fswVAOdmZ^KoX~hP;=&5C_EL*h`=az})TroR% z^H!Ke{BE(bjO&W_cNorR-hN>F*3HaicPsB@shb&Z!;bHaYsoX1S<2|xQ|x_Z>)h%G zE_IgsnRX_z|7ndsx!!5r4z6tzD{}g-D|M{WbzNvfH zl)N+j6LtGSK-xT?5ckqp=@)M0W|K-|ZK6W1|1&L_WKuF|OYFMKj_R$=f^S1w&V;OO ziC?aC>-A6Gb234$8L>q(UtBzL?YU8=tx469^ivCL752ZpRXbtbTX*Z?{o23YKRR=* zl|NKGL*;LwU$o@k1`EY^?<7xO`Lbo5bmXJnOM4dvnC)5@XR=XP^nB#Mucb$J`yKPY zrIpBUy;8uuX4BKeH%ZsNo=(2=r*zdNU&DHl=RPM>mM1=#d(zK;*@heO9Wy^^Jgsp1 zbHHfjI;-H9tK2j~xo5nKI$-gg>BY0O*_YEcZJu-T<*Jh&J9uZRPuo1F(S!Z1!lFN% z23yh(T$$(k^qb9-Z2f~CZ%t<`-phG<>-Gm#Z*zC}R?AC%m)#LuEiQNMU+0!@NZ_Ifc?7GURM6has)o#zF?e9wX<~}>HvWxenSCW6bXLV7YC0oSi_kqd19oiR+ z|DS7mR53~H&RdS_Rqk8u{-o7)pJn1MluJ5oKC%A1-1;wvBBsY_c&xj##(T}oH!`nJ zT=3hTdOuH9Y}##3wl7l>xBSiD^f!Oi-~4rd^X2|UJMpw_dv(NZ#&wS3m(v6G8|2N( zxoaZhZq6&Mc|Va*Wd}RbpNmCQMcrUH5TD!QSP}cb>fD*j{0jxPH0u zo`)}=O?qlB`?6}X`KRcK8d7@>aiYz|Nya* z_mj-M6QW)mTz>xZ1;0BdBrNzc%angSkTIE4!u>hv>yyH~?_b!~ALo~~sa-gEx&03t z=7bID3OrwVnv`uU3#O>^AFF6P12#&lNq@t8e$*joB`#8xreuUGim8TE9en;D2?2`rkK~diADmI{j_K>GH{p zeqC?0b=3DicVucN#<*?1=gdOQ@Jzu6AU^$%5%; zpQbn-+00>9q4l8Te3HfS%`AE!bXvV_k1HQ$pKx&cVc~gR6_)+b&*C{s^olwv*TJk12`sIXAvvj*YPvzUN z!lO!UcV}$&-H_7whFsq0>szN=9dvoMA#KUc^Xs z619*DvqN6zBRzI*e#mqFXTiGXOgoMgE5^Lt$#M0H>V~t$mUmw56q5U%)AZeD_Cw?I zVn2>;o@#jB^vvs>jj7e!HZsne{b))Gv#wW}$q&DMr^_riiS{=7>|CH967lDa{JBH( zzJI8WjuVO4BVDmsU-Y5QcUQ)Jw|8n>II@qat>N2;y`GF4zcK%EW4v|zz4xc5DcY|$ z?w_;ephQi5PwPbiPu7YGwd|ax``vocA}hnr>2yx##gw zH2%G3Vs?u7KDnA4@!dgk&pm(EgD(Afb4t~z(4K+e;RJje`pp>_81hm}^s_2T67@54 z3v%@Fob-}cl3J9On4AjP)xR|SY`Ao&$bNm!mX^%SD6gYRLBA83rc4Zr&eiB*^)lGP zF(vHvb(P8q3l$~P)il5I7d$^V_w=q$k7X>~7awnZ7gN#qu4Jip>`SlkU4idwKTEW+ zHwN&lm%poifA9X@_vP=ajcb0NpB~S6z~D}=v-lpV=EWbPWa8S*JtS0$R6eP2saSNX z3Y}KzQt=VeR(Ur;V`7AApjx0};=~GLt}>B18asHDo~;T^GMJ)U93CH8%sW@@OVi6I z+NOE;FCRDGQki%CjLrE6MY9}VcSM@q4P-lf^6$=NVumlKdNmrqI58`=ZtbpFkH0ld z)P8v8VUBA46fxf0OE%8w+2MLQv0&d%i`412z1`*|&zlwfr1*}8uE^O>MtswEzScK> z;knE#Q1*QEbd48xJg-S)uW5L(?&XKjIJa|tYWe+M|a}3 zX@`2xcYUjs`SQRzuBtSfz3N7S5}OM2_wHsk?vU~`Bppc+HbDSVpl$;=p+)r{C0x#k-h1O8zpBQ@4}6N_PS{>jJJ)vVR>r24UxMz1Ts8In|Z6;)BQv zzh-TNbq7^qt|~BJmfGW>#2k4k;LL?rJTaFO`nFikP~Yf~6xckwz`J=m!(^#@-?iEF zubuUZIluOU&0dAFWJje3mV$k0uIFREpI2x;_;-)*$L5C`b@~auAHJymh2>X=p1C6?F>AY)p@gVU)x62`a{tbETEUli)n5EV{^!5v4?MnP z-@KpW>{{)!M?$6CWBnF8kL9_a9R-r#PsbK$99@?f8+g6fmU zZ4T|~N5a~UPUA>+NO(Wt*6l`H!+QT4`!9XuyS4Sv=4K1Y7nZkWEpG+2cg#9z&6IY< z_^a{DhUG5bmc+I!cbzBuf#+OnYZ>R(jtiG|+)`rdKXIU3v8$e;)8WCpYgSuUEW9te zaJfygeaRvIxgVU>|6Jg-FL7#9d%Nid!(!v^Z?>C$pI9|_l7(HxHomo4!F$A4saGFyXz05QjNxh-!`WY{G2sO=a_2uL5Yf)CzE_v8YanWo2)fI zB7dXl{EM=j7OC*S{TWiC>!UlXA{BSVvi_|KpQL%vEnpVc*Ryf~#=NKN9ds|1NBny~ zThD%yfx`Zk?Qa8f6Sm7LBIaS;kB#`3_1e% zY6M-(8X-TqG&eP`MBl~VH^SG)1*1>BS&So;Q6$Nj5bqtI7(YTH~#-Q@tJM>clHK>ecabu-9PY!2CFAc_I8}%^81Ix z`$bxrUJK7`dJyg>u|8Bud+ur-v1c($_1s!oh1x{T4@btusd(?#e>2^Hn^WOO^ir3- zlVY+Layp()owT~=t$(WrPvSpuzF_Xx4~%2AZ#-L&e%bNt__PVzU?Ann|*rP+YU2}mT4a@@&~i@6b-|ZRi91CNMteJ4^^pAj9siNAF8b3T{{k~MAb5>m| z?6Sw>%Ocl;G*U7mLN?Aj)Xa14p|Pl{=={|h#w)(nCEtH4+qOD7wY~dKp8t!VVYgr0 zx+D0rEAul~{>)u5Th1)F`TOX+2Y$zMtYt+*KTVm_cR@Ds)uOjQgWIdKr`>z$ap~m2 zS6%ORE!%uJKu&DA-kx=eyX5jknXd236L|RVP2sPb2GW{d>t^(6zB4{jTrACVDr)yp z$#c_v+rxK%Gy5*}Yn$u5oSnHZuC=|JStMs6`f;tN)_WOEqulFOlR{U7nrT0+SDkyo zY2otn9V^OXx4-4QH)$r9k>%{!-IGqweEgyG@+0?|sVn%NOW6Ah^Znnq|JVZl`={n= zZrHQ>{mV-4^0Jf=Pa|u;h%s1uqn@N8jnzOEcf%p{tt6zjUSdoz{QjZN!P^Y z?=Br*w!FT#EqD-8bC#h^J=rvVi_6`(Y3kp~^_T5+@7igbmfbJ%=~-PnkDom`u;j+8>6=RtM~)1bxzkl z-k!mGpqnwGvh7B`;v4?s8%{A)^S+;R?AYNO^6g3MmBkahm#F!j?{wBU+baErq0``~ zzunQN|28!^^*u9qzkmJ#raS?sOZRv(q+3E$9@xG0edOC#S^ur_`R~_kdu}y^b5}gg znCMn$?=;WmaO>)a4EyJ3{t>$yn;h|}`0$5y@(<3{vw5^K|B+HWP_53iq@X-Nzduv0 zes!n)guG+(FW!#~wp@}}rnFl2!O~yFM_ydrnf7Ob&o`S;x0;s>lmBVGOep#!^KtpV zd0vr{_OWxiE-$?Jd*7YvinIR3OyVC{_0%qxT;J!Qs-ypkOYc%f*B{YO^_tt0jK1=N zN{RhCIvfX>85pi{<0~b!i7h3d1w%x2LP+}5|8rA}%8hn%Dmoncz@zGL&zVESBg3m9 zU_oVw5EJ7s3AO1dFKjMVI%I5|TKYO`cWG(t>aex1S8aIvtKpWKZ!q`PTUohpclm!` z`@3%I>sPCGua5pc=l#8%Gd=ZEn*JExulZg*=d<(7pIao5}qt z&q6czJ$1E@(|&UA^`)BI-R2*DU#fARWk2B=|K1{O5HzUOZ9ppWCeWq7Q%nh~~fd_~`wI?@j+Si+g|Qzw~EvTm82r%YUvM|5mrv zU;gkuF65D~e%M1@-v19>Me7t+{0pwKpYqH%@#|tGmXGm9ACvX#n&x}G_vQWn_Nd*T ze(~NP@h|`S96rDIM#KNf&vJS9e@GHO=8DIreYlkLsWOvO_iDyWx6^xHq}}fYS!wOG34Yu3*dlhS(KviDl_$Y*TvTb$LK#i8(`dU2rgK4TdV zm7bPgJ}S%?Q#2;@9DTZZ_xAOBcjxC<$Dgn3eZ{e~_E?5dbzpS*6^~#3J!;JV4n`P= z8ZPpz&o`RKr50S6Trk~qi?zU$tIJm}d!Mgbp|r5$VtLgOg*8PBt{&YSdn`di!MkE- zb+m?**EYd#A?J7P`t0%`<$ye&OFK)DhSd{;pv(RRZ+m!+epk+2xZ>j6E*axTwT;P% za+e(iTV^lzerP2v&Ze_I}0Q({}k zdrYZXSvm30sdEuEC+b&Op4g%MFV;5JDCfj02P2X0Pq&oBG)@YYXvcVOx*k16w^qc> zsWU;R%ErVc;yuF?v#NcEtg|D z_M2Nx^7<5~ED%_Iw=+UZF6GD4ZXODs)pgdaD>U*-boyEqbY|lnwM0Mpp7u#z z`)ra;xC{N4dAK^eZ93ie@ambgZyI_}ZFf5-E>1SdbP@JxZ~PFje(9VplWUT%3Xk`? zXq}1p+9D|Xrh94mk5zAZb-cDc{gm7pJTqdX-F_p+Hd!vw z@oS0Lp}kt#TMl*3WW0YiGwNGXRk8fzoq?Z*KLcrvY*9Rot87- zjc>c`InjccKJrDG-u;dZh`%cS~`PFnQcXSa{<>o;C+J6&`#(n>mA+go;L zubYu$5gGBx?Yj46mm3A8u9o@lcch6F?ef2vd2V9mw{_okTJ`v*ceVY0b?(iE$LF%O z)QYUcSI-KOIw5`6VaCz9M%x75?X>%PR>sjxxG(mxqNTdu_Va&jW((Jz-{K^>H0zpT)%GziQ*MHq%Gtkn z0`~UlCx#p^d;=6oy!K4co+kaiSmGCS0j)mMahfneyd{PGs8oH~0Cu}t5NW1pKX?a!X^4XcY z{oZbIUOd<8?IOP3vezZtZyy?;KRDlKHTTiIm)<;HrLcLOQMlILQ(x9vl?I6?ew>=6 zAGXK&=c3286&~NpjkA_Na`*W-sn7pW;oPbvU~ z%r&|7_~U_>Jb@)vKJG2217F@fr@AQkuHn%Sfsxhh*VWA~UitW#ExRV`jD|2D)UKxh7y{}8H+#C<_ZoaN$#XD)?#lpF5E20-C&UGqrIxZgJU$T9L zqK{zjBCDerDr>L2u~OEZFLihRqt$UoPHZ^5XQgMT;cJU_^__OJ=j}4t<-XiP)gJt?z220R;I*C^?`e5_moqoGISzmdi3@jdE}YA;nR(mr`C9_ z2)s};arL&CrrFmo?cMb7^QAe@KbvhAnOfT%H~F&Kx}WQ2_5GMPExGQ>3%f(x;-6hR zcYAg59+7i8#VV5F&#P`ezU_L&BK6a>-Qjyf+n!eh&N(l>GEeWjkaFXKi*;HGC+~;W zMkt7U4za&}x@Knh^~FZdjC=WJtBIGLNx!-1jS~g;F}{;Y6V|?GJooO(Gx3(*Pm|-se*v>w~eVU z(-qsFPD=gZzwgEtH=Dm9q0`!Iza|~FJjhvfZSuKGt9>@_yLy;U{0*Pyi!Q5`mUBYO zW_FqGb-fxsiNnZrJzMl$D25pH=*FLvp=o0B803=$_3Dmdh2^918r>{QmNZW`8|(hVMW2o%rv) z^Z0hpdA5uJ=3EaRUW{L1MjzN=cqDYE;*qN~5|q^f?k%Vqi;Q^B_Mx#9Yy2|}sN`F1V*r^Ac+rFoXGvvv`2d-{gxVA5n{w(?MZcnE9_Xf@#A7#2e*m!+p5_@Rm z{XuDc4d>M#Qh$C}MSbLYUp=+Fj(PjT*%m$53)th_S@Iv~>}xg%w&c@aAAdGEaN3Rj z)Q-d!&Fw~4s|DJRS?~2wIJsF+$AwFM=kcn8nmtUb)PE^oweGE!T>RzT<2bv;T@QHf zaZbPV_V2R1js5#S|GXa@9e)1Q+5IclC`_un`tH5q_4nE(Q=eJQo__q<(~T9JciDG{ z&i-m>)cgFL&-TdJn~w~C?2?Xie5o>x=SqKaX7_6wuPg3{Ev9YVab!)7bLusw)N4$J zt7qq0bUtOayKWKIlel!#qb{-Sn-)c{(fAvBNB%JH+g3bt)56(%Z*7@AdwM4QXxNB4!uWE*jFT zwd$~1)cLA4?%bvu%9QtXG>&uP)y* z>G;3>v6-s&&e|&dO4HK2`HnVgs|T7I^qJ1xTACbjdVlGk)%z}JDqZh9()CJdiuT&B z6z?NmTSVouTn%#%*JM3bDKOT`*e%N`H|<~IAFKCk9Tepb{uZ6;#jSr*xV!c6`Ts`h zoUXeQ+NVdeW%etrn9cp>to)YNjE7f^!heZmsRf)q`a$B=JlDS^R<@EQUb$BLJNYB^ zKG|uXnO#}$tbTQ_Gh?iPgO=3pSMdk;c$)BSNc;0RqTccA>*E(xyQ`c|J5xu~9Owx_hRU)~^)~L_T zD@l3jhN*s!)U1{oY~LuPE%Dv`L*P@x+-=vl7KYUI6ozf|pRqYEXUn6_6Gi_@^zYoH z^2@?5apt>*r}f=Np?00RO6RX>E}ho7SeV`1_CUh@qh7V!nL_jOwuwe&X-<0LdfsbO z^vqV3DecR3GUrF>#;n^qEqC?--=8%yTT4H0EHhqsH1xlbSIxR#oH^$YS5En5aeG^T zV*9UeJ71}7Fy`M=CcgfujLwsqb(|$n9zUpD^D?hOaC;5UytdOjo(g^cKI5gdC;-ce)ZFa4jzhv6D%->pkEbGmK;*Y^PRkH2J^B-ScbD&wKcYpKw4YQnbTHQZH zK5gZ{T~;G8KiQje(`LT7iaycATWhXvni&@Do_xdF_SC#H8+y`&uYcHG;S~8yX5JPK z+x(-^C5+z+1MXV2ojV?2+PSXLv!vMUl_7h+^kM5$--?af?iGHCUG(ex!p`kitaDeE z-wBE?pLzXrJ`ek{57WF2F1q@~`)@pL-~3j`uOWNkN`c;6KNgGCz5FZp{nHec`P;c$ zm{jwBs{CTl(*2%fZaIV9E_+$_i`9}+TH7tBJm#MEe%@hm-Cg{f+Ek93r%rq$#v5W1 zk^FU)h_Sc+(S3^DOC_!DKl)L}%l)Es&0=$r-%*n{oZWXaNq_I}DPO&Bbnk27Uc(`- z_ehibQkr(Kc>1)u%c_6!+?MH@MNZkaIVOHvM~T73n#--PHv25vwpvRix5-Dm>Xy@r z!opJ=q9-@@I6H{EnkM{ag0XAx)4bV>ZZBE!q9?vS<9wWYhH&47W$gDt7uY5`S08Hn zHb;0%)5+(l|Iufz z?q(&rIp?f4C$8Lg>bhod_Ufxr3o?Y-Esf=V8fCSJrf!%d{2;sQ@AZ$He$}_WXFR|* zZ+~;c~F9FgsEQ}6RL zFob?%9uq42?_G-8WS_X(B~H^XOk2k4W#!#INy$`q zs!42v-y|omj0he5lg4w6W^!)c!l{(kv1zBam}sC*>B&(0952ZKR=;+9EJeqyzVf3cYxsq}`kE|7S z1kLy#?pCbf=V$*|yR%rO!@cEM28aEDy`?`AIkZ147MR94UEcgbjLhVR>YJPm3j+=M z+*@BJA9`NF?Dt@~(I1_T<4@mkCR!^V_LTHH`C$dmWJepxBbluAdb4#kVkVr4Xg$)n zu?f`1T_)^&^WdY7shTR=zLvaw>y=kLZMI00^UaCx-b`33;Fnf>xYIeed5`U+3AS?A z^ZZhST6MW*M?XJNWHo(j?UmKRrz0l#q^^1Q=tRTR+sS-Oa#uE|?K*#EY0BH2U);Zg zD_c!Bci)+}O-A{T_bmj-#&Z!N3QOtzNxoUKJSV;yl-03bFLcO zm1VOn^+clX_vW3t!d6^zKL?v*7;)ooua zH%~Z~#Pm5-mcJE5TF&&ZOl*@*b)8046 zZ`pdL*p``njpHK2#d}T7y??YUpRDoa+}w-5L(g+wnR)edddZ2ly-mBz-_5z#T(|X_ zuB-9cn3yN2|4O+QZk+h#TTsGJ7wh;gdi;D-gtdU3!T4_?`F72*cq>N2L5Ms z)^5O- z?s-bf&qd#NU20US^}8op>zm*GFKmYdf609^yfRz&8QWS}&AZmx=dO1KFu$!hb%4E~ zv$6Nbg2uNmOg1>T{qBA4*kv_I$l6SJbOF<$D&)Hiz@#CiWj zeTzGEn$5>R`P}U8M~g12F|X&CoVRDy1ryQ9vODKk>K&9hlF#!;jM?$exdZP%vYXAx z66K9)l@^`m|F(SD*_wTq&xmj9=Z#t{bc5|*hdt}Z^foVVwdjnK;_mL7cQ%<`F*3Lp zbnV-<&Y=2*T2CvVzp9pwGyV|1Cof_4jcV?D1|Q7#NFIr1`=@8{hxvcXjI%=j4*knz z4o{kX<4&?dryg@O>#t+49xU+O?8?47Xmv|ja_Pw}(mT(*ncg#HzU<1FeGhE-yp~^@ zVLCa^dTr|Yl^t8ZWjiU_6@ULw^ZAUp-I=rZt~ktMe==p8(c#v=QGBnXVimI|2js`S zwVblCXz7u_h^VU!r-HKP{npv!8*};9#|2+r$$i%DRu)aPPP{+s*1I#yF1O4MJd|`R z!8g=-+O=y-uJ4VE+PFux^oL=a)~bekPg+?+qeFGKv=q)aE6mG1dm{YG6Ygi%6f_en zOAoKjG5C7zL`LErH{FaD4Q@xyY1`OtDc<%?o8O)P?cO&B zwf;T2$INk1T z*;XmLqw#U?isS8u^1nBzTT-QIf+D)LR-Q6}Wrn#K1xRmMrLT~@E1UAAM}T({W& zo>$a!{S;f*-QbRhm7eX={K)_I&%kp$t(<3ePuu*{#=h#=+gUGI#B5p`tj>8pp7Q4E zpQ}7IU5{lWdd>@+w-$W*C+W`F&($lA*Xo^1{Ks)`rQuSszP8dUZ;N6Uu1yx4%Xang zhfwLN{pulWcJqDIE!or&q0gqacyh#v=igZlwO_1|^8I_rs7feZwp@I2#1aMT(2GvR zKVRGQv~Lu0-*VxoS+aWugQ2YQBJJ$`%601Rf0Sqh)r2JPxzV1z+{tiBzkD)>oPKhY zT+?n#;bq|uv*vMLcGvKkv;C{dvgB5ISCTeI3lpOfo^|^uZ%g1kSy>)7D z)b~2~?-M84FFK!mGf`sVi{c2g#-}9*y6V&=IxkxaN1U9&y}clzWA2ev>9HrCWj~I0 z6j;A#;`;WN`zG8h-ElAUA=}zRy?tE%!ge1s`kCXWbH|teVU2mzZ~bAebnojsvktsE z93i8fC|SO-CtGKC|GY}oXN^y#T^{*reG_|BV;6Jm=hO;!ZRv$S478^wXfFG*BkTJH ziMN*}-d$Po>r}wqm4RO^)$Sg#wLA94AXxVfXVL#}9#alJw0A3*E$6V{nZ(81OW#V5 zTWtCL_-tLR;yU4lH`m*{KUpSXc<s9oi$T)H!NYWMlKXV?l~D=jfNVJp8;?$P`QH=N$+ocpt9GoQR- zALFB|r@Z#`|NC&-`^Mr0S3*QZwjSENK<2<%zK?4~R4)n(hRjc%;Pc2vewVlQv+F-i zS9JO(oOR}rJ0vuJ(gNjhRSDDA8)IUhur>Fn3M>0@oX|Ntvp?kYOtaq}+Epnsw#Rl( zdyuK^Iqv{#)YNsGc>is`#dUO=#_O4=c=~ron8(Id zR$Dzh~P5V}8 zF2D4~jXQZy&)Dt0diG5Jr+>LWW;|YYU8d$&OwFz&eXr*#3Wn?xd^ZXy1hVtY4S9Zs z#lQH$4z_2NrcY0DY;E-tp2`z=a#7$@iKNP^tsQ2i0=utB?Ap2A{q8csn@(%XE=Jw{ z^?BnpN0l>obRS-Le#~LM@DxQQwT>TB))8m(zE_-9StVU^{Y%ZIBl7kCkKFyy;#{-x za@^~sy(Yd74hhfWdGjvd{jA`A|4&mFozUv^uYR$yZk^kmkN?)U z@5tplk~iaC=lNIfpZ^2TUfnp=7o^9iXD4-?zZ_8D51Qas zJiDn&KiDHtwezY;Z>!3+Nfir{Y&(;r7XR=%dR?nTG?ne@&Gm1q_na-Lj4t1K;oGi5 z7o>bQKQ0K*P(A%n_1*>^$&%@cuiuF8YTBK<`sKFJ8s~Y7Zi}^P>o}W4|GV^bt?2EH z?W!*$?02P9%zOII=tc9V5ZBeoU4Gr>Va(TOB?>+K_a*SxOVAXzPUJe(cZNqk8PDc9 z<+b^sq+99fr%(GfAC5LnKCb5Pmp`j*Z{`-AoqTh;e%w@=x}8rnvM*i!)Fs`6+r576 zpA{$Uyi>hw=ZZ3$^*4p~D0+)dDYCK`UOHp4`@`&MXZgKP2gsc=#}`s>x|o6dpf|rbrEl#Nrm>V85<2I zZ7V#vrTLv#cDem&acl2*tlpJLcpzNtd|y>U$EwGg50ioT(dpHw zCo(6gFXd`Qc*fnIy2sBwvd#&7u3tSbcV?T;EVsNiV|Uv+4d;)&rDCx*u`~ZLz2Y%% z-{HREQ@i`tO`DJVE__tow)C>clvIw1a^-jBzAcnI_WSwfOZJm^x}9T{O1#(aU)ZO% z%KEUGW}?01qPZMqe$hW4XC>zTTo|W4C0uLu(ND~~j{J#U{7HDP-=~Xu^FNsGuwW=x z^5L3gee~EPsangP=2;TTGp4-tnlCnaQ*x%yr1`sMym5`nG%=ETyqP`0Kf|a=a}($N z%tt~ubMzUee^l)K^6aoXV}&Avw!h)0YL0B#gIcw3L~Ckfq`8y#Hr}vFV|rs%nQXFb zzVpiSv9=C2XFl9WpYh6-m8Zz8+w%W^lXXe+1SXX#Cak?=tYwl`wdOOsM@we?$ISHV z#M)av^UZ`WoSNyjdB*$)Qk86{!Vdr0KTqSgRi413W$_YLckKSJ{r||n?Pq=Wf&D+E z>V@WiJAX=U?UVIu_BpJQtM=0G*){3(pT?Z6a_9Fx?eDyEyQrpZ;t%egYsu$NJ~{TH z=188*1D>PbW!~g3dGbp#$^XyUxt}(lK9zgn>kbK`%@T5VTY%5`pG%jZs!+S~IE zS5LTqjO*Ox{ply;J(t8W26(e`C>wA3b&{EZ!4dClw+_+egDDIk&r&IsW zKa=tAK;_cKO##TPuP6fb)iFZ$(mOxe*3s7$Gy4g9yc{jfBN`- z%!-5BpDZ38+W$C|b${t2Q*pJ2r3-(~72ZGnyR@H7!9)8G%Y^^GJQD4<=k1Yt%a46) z{vPbK*ZMJ;=YDD8HiLJE>a~B!v(}d-+T9EOATBQUX#J-j@vQH6Z;;UEzWD#-3+Bo_ z+7WhVjx+duVmj#RVrjHVGbLQ(x+`B$%#$TH>N{g1x~|WiqW^l8)8q)-SvsHYg=TQA zc4F1Laxp}5=UkJsu9sI{@O1T?r6}`!N5bMqHg#vtIGdlHbUcU6zqqAf-Gnp2D~_~& zHHnww7KwV{WIgrNC#AG&yzbqxTUt)FtiR(aS6S_v);i;%sAOo@60OP*?U2Vymg>c* zZF{+_IJIczINxk?{Os9rf{ism|)`W9??N+&i=OXUCgYpdY}KiS=p-KEEB_Dau~ z>{>qe<)4``OF5@?Mkr{oFHBn`T~JdfA@T6UKChO9tPU+F0ls33ic{xW)KwchVjh1H zNLzBk*FG#Og!`xUVK)WgWm6+d(sEAkEaaJanl(ARQg@Lnd$XZ;P}1o~OH}NvUb5d6 z>*F&_zoMdh%15)L=*62!t1d5CD)Z7t?W=hk`_nB?+<(^|d@$>vtTjvaxovLSWTj77 zOx80ye(Q+)>mL%{QzosA++}mM^(XVg43h($`!t_Cx4EUUtCd~ZcF$z1E8=`={3f}n zD%HQ5b*`Lvzcc2Y(w>CNEms8vI|G&HtJItn)lIhZEH8I;o0YP0>Z4gsab;|uL@sR= zww; z6*l=T5CHZlRORHwFYHbag?etcw^nz+li1(HN{~PB8!u208pR3=-{W>;hZRqFgWhP~1v6n&) z6~@08+UEZ$Bh*w{e{ZkBrJK@600g-s(oegB>8w1or|)9vN94J?n$%uFR9M= zjM5Kz)IF`hI@nd?d{fbOlNF&%@B9ueTH_RWW`SzLX31-BdNX+^cI4-GT@AVAxYy~1 z`eKIgbvzFbo(s=d?zQ_x(xE#%ESVpZ#H&Q@4=8J~c9wGlMjYiY+}ox8!;!gUX-Cxh zpq3qaXU>FZ3h$FT^q0x+SBN+FUWu%KDxABE1MXCszYEOR?&ZA2U1_qk>#FdVTDzi_ zW=k-|YFpIx3#&_p<{q z!Dn;KW@>$jJhZC6=&5SX>0f;o597kDb~5^jE;=!3jdZko0Qc8pzrF}9xi4^&k@wQH zsavO*s~Jr#JXhKJb<#6$UYG4(HmcYz=E_aBEVpZ&ne{%+c}l})UY-}Z0jbBNYG0lH zzsERcn*{&&V3{Q~2QNI-J(tBi&1QDv{Iti#K~Ez%Bd))kv#CdRyH2H%e(E;gJbwe3 zRNgc%>-ip4nb(i4aGD?df+0OIdsVOQ%JhfdHhsz!{>7_iD&c+n)au|DpO@QhSt*;A zykoz;jMiNdZWhbzr?cK?u4z`?Y$+qCF8FPF?Hqyg6(7&Nc;2*euHKaj0LAe-OA zN<*gnbk0q!Srz_;={84C-Vl`O`L=Y$%pI<`pZcx1y*$w9noV6g(^Q*dUJbif*veY_ zO{N%ZOX2eZp^ZCE*W**!xy!Aum9S_-CQ=9E9i&|&u$-XJN z`uw~3H$#_eO0!(AO7?4=W?EG3)#UWYx-r==qH>#O(w#Gw@;3q zv$`@QN#K!G4EGCVL62WAF7NPL{%rMh#ToWR3mKk#5wPXE&GAO=eBhI+J?;-b^f9g(O zn)%6lw9lMRdK|k!t8eDXmrYfVH(y#ZYwEF-HJgGq@9v6hv{arUeSA-%&&txCq`L5p z$t>J`wg<{8nd=Y!&T&7yZ+>z)HLS*KP-#wTLW#*hU|YZGyTW? z%@vIQn}jR+1pmx3+;c=D?f`qmM3Fyk-`}!*`;>HSv;6g9hnfTX{_~tJ@AxnD@7ctc z`EoP=J-e7*nUb9IeS@9hGucDa3mTpmea-k`6YM$T?)m#=b>{Q!qOkFPt;~ zNQBDr)>R7vOi#Ut(OI5)!$mu2(c;^O?&Ky-yQnDl^u>$!1{bf-PAk|bdF)+ML{e#& zYRt3{@$?C=eZ22vp2|uL*;M{dBdn~jQsN+Ma_d^(#u@pXr_EbWzL+pi0Px~CKImc4$d98%mWyk$1J(sfVo3}G+@0^`(fyvi|oW3p>M} z$~a@WySy^3K^yL5_Y^!y<^TMo@Mu=f^F!OdDR}KQ3an)Db-$3a=i1Hf#|s57S8>M_ zZmHN~wrsz}%sVzb0wt>2f~l%WbDYYOCEp&++9j3!QYyyry3^uXj!XZhsNBh~+&Z88 zL3xCtcvXpM@dhc=7=ibm-iKP=7jhbk)J=H4WXF|dnl`B-uT^hv-Nx_z{y=iyb+dP3 zw|4KyD7kXWHfYxACxxCuf0_J>7clqyb91W~PP=qgW2yeauDplN720|WZkJs7DkEqt zaq+w4YTxrwoPV~?F_63P@%oG(-ZvZBVnvUiYqr_6JR@oP{BU017nObvLQJAD);Vt$ z`^z0|TWMKgvia>_L9N%K-!q4wBoPyb!v(6gU*CB0eiVVCoaN1h4&$<>$2 zr*C$5C|8*O?g>+wx%<7nGhE}3$L!+g&XAb;CHKmO?*Z=L7tfVzm@jukK=x>FjQqPr z?H^;SSokk$_+2pEjy@aZ;3F1=ZCCBN{}o8}KM=37M{dVS4Dy!fS`{4wQ~DQCaE z&66*`bo*^x_d?B$z2_$U&^WVKynAowdJB`i{`1%Qzqr&|`{T*xX(h}VP4ho?v|PRS z#Qb!`LJ=*U=K^A)A>vx)iFuB-3yZe5>{X2jPr3WSv#qwG=W{)$v@J9HU#`n9BiGG2 zU-+t0PWy$c$z|^wKKjYpdk?LA&hqW@>K&8oy5C=ZT`{Y!Km3L79_Rdr&Q-J3E?b9q z)h|%}qHfiHZ|T%8&t3d|CU0!1e(C;ow$I$Bf2{r}f8VvFU+%Esv6RJA@67am{$j!B zC)bP1{+7J6n)e`3PkHvSzrSp&`nA_ixdHS09J+F5>x?$Kh^YphJectJH zpB5X)+gCrk{lQoPGVD3-f->SYSI>@YaoU-%Kv#ZC`LV&*`_TT1M?nXW>r2Ka=vO zw9RR?>b;Gp;EU1ckc_R7L z)E`pE{msLQKCiwcHt&7;lZ#7jUOjr`xTUvx(;mp&|MxjZKfMuPVEC$uZ`9S4;3x`o z@?Rx6Be5tbF)tmu-*#?TY`(Osi0$jGkNb1%3Os^dZBa2{O`m(rOjpE1=2n{sk6-j8 zlP}H+X5UWTe6Z&3SE*2iMwUH|E~*n0e3y!Kz3`S}aMWsa_|S4hdcDHOV1e)F{HCd9 zu4-eyKeM|0*&O5V_auLA-@pGqr-Pin>V;+}nM9vWl~!Gk1Lt@sG&%7E+t?jWvuc}c zXmk4VbD=HkW*kryd7LsY{WH^Xubi|+7NSQpStl;bwphosbcKWI+peZ8_RJ+3g(`?6_x7ipA!(*rgM~ zw&Y%(xk~cvGSB&+RBxATK0Q5FIeV>1)=jUyccKh)&7(KPe7@t8xhrjx^&91$$tOxS zo`|}2##?u>o5J3gmo|OeHF535rZ+E-rfz=I*B`ThwN1r0@4w%wSzkqi^*W}%*5*BI z`200j-;(mRnJt$@i(eP7OTHP(`hB@OQ%l?wj^wAi-bzio`=?$;e38Xr6SvSVyPEY1 zv!h*tigw?1N%ax0OrIj`mbz@_)fj`UFxL`R^<8PVLd!jO9F=|L`0>J1nWa_dR^4j5 zUG#!QeEWKCmt`)#J0`1@&0Xs`Y3_{G+vjYmy!0sS&CmCj43}Npz|NoX!gYRI-51x7 zi<;i(%@p~Pulu!gTIlK-e0LXhOQjhePn)+V@Ymioi7dO?4qGgGsKaKev!RlwKf8h@ zll5-2vD4d<Gtg(znzwxqab_h3^HD7T5VM6bMS0 z%)+WOajU>_Bdd>6Y#NIyZ*SmlW~$+zST*5!=JHq0%Or{(@J-;|G@av;;)!JqGGDfN zdd%Bc)Zeys^QHCzhf903Ge1>5^L9D(dS<-9zOIg4^L|P`l>8gr;`Xwf*>lz^lhAwx zseP>*cD>`i*=@Ed|AO^DwM7-(Eqi+N_Bd~O&&u+&*0GZ3@dA$*406jPxEH;f)D(7- z|6+td)0NU`6Bgco-qBL?oO{}-t`mXg`#IceI6I^ldojMByo2B4PWzOt+9BurKPcEO z3#o4ktntde_CaM`qRjQy2X_7q`a2X-F8zIQTQT+AsjlVq4p08%Zc$w<-LY{G?~%!z z`RhLInfpxo!oE+UTRUsFGd=bH{q+0<)Gfuj(eP+Y#IL9AH=I3g6 z9RJ|^KxbFI*j;;Xw#bvA6Jspd{8H)t){n;-lFy}|5lr?odZzj~ z@}$KR!(~C)FVc5i@qJaEXy8L;S(n25xA+S7v#+}F zFud`eHD{4qSY>_3)mV4y{u0)d!-X4!>b}Nb@w@n{KH&F%&$-{i8EW^p->aPy^>>Af z{t2BUrTcQEJ@TfO>lNJEQGd%~p1^narOTdv^$&df$->e1?0Kh-c`eB%@1{)leKhTT087+LRuyT5 zgWI;4HEf%qB^9MBc-wC0gsFOYW;1eRe)Ye&B7VH^g1Fo(pQXlS$1aBdmyQ23>y>4B z{`4vQ>{gEr<`lo%`+VO0_ceFUuJ^C|!+Ag?Z~25{bNbAKIui6aWy2$4QVrKX_PwXK zX~(k1Yej-)B!4Vp;$Cw<@nc?Bjko8g$dtmld%gFRJ0GvMx+m^oQnUKq^tGmqPhQ2Y zuDkr{S`K6K!Ow4g?a4NkDsxU)_2gzp8qIjy14O-k?i^FS}a%Mifn#YZQhl1{q(giZ|m5l zw^lvXi!N=yo)!H0z10!rhtb(xiT^sL%)6)HHosriy7&Kort3<1^|!XfoYJ=qi`s6t zxkyj;Y2KPOw^!FG7PrgjOf9|suh^<|uKyd?+13%O^CC)j#|T@LUr9O4lq#m-v^Z?5 zXqc1hYK{)pb+x%C*IUbN-IT6#`H=Dr-4opN@-5>Y@4TRS_Ve+4f%xoVsiUvj>iy@Q z;#{12H&Z8iU9jbnHB*98jQutBEwkr6HGe(j)7-yxy4IgJ$=OUWK7KZ@@6_a|Ri>|3 ze=}`o-}O84yr-LC0oU@1w>let@2R+$u(6qmk zF@Z(!qfwjcJ54Lj3o*OaPJA~pBl4JJdP^sBlD*>j`Uy({a+}h^TvBq3cdSp^d^D0P zvv8hZX5q3q;=a?I{x$h6TGE~NE&9low{P?>?03=GHTSRNuSGuvZdv?&uTUtTo+-LG z)MwqLEnSzj^ul+2lil*7%wwy3;VFa884Kdg3Y%7JTj*S(q`OP??m`BWCDBJDj9fH* zm2)n|wd6>}xE2LZl$ols__mL>cBX3j;^ufovlG!D*Q89ob9&MI2p)m%%OPtNzjPXZ zk!X*O=xNh&GjtRao%&C0;$)o{o|Nc4Sx6TtjH{8m;FBRyw}u+5BM*hl$`vFt@fas_;c@9uWPUJ zU(oa1a!(;?#^WugCKjI8zSDK+Ec*_%hh?kl*mtnZy2olOvhhaK41U4SEjRQ9^#!UL zb}Y%7$tfV|WgPA9ZOkvdmLY57(kU}HOc8f(=odZE^B^I5#{sKtt(@0B>h`eQU2MY6 z6tl^S`OLe+2B&pr7&E3F7nQo~%~c#W)iCqZ=P~?PyVUOF20PC^YU%b}r!Vby zI2d{Uk?W;cqZhAVC@0MQ5-IVY2~?D^zPrtl$-={W8(h#_uuz_2?^i3>ies^ z>sNjLvX5Pkts(G{k@%YDc3I z<7Zdw?c87ZkhenFKJU@Q*)x}&_T6*z$W@>7Qtbb(9f^)L;0gcqJ6CUy?DbE{b0?pO zdEa8Vqfx%xqEI<6spt9U$7#avO*YO=tb4xb;p-irzw0&aJl$AceBRckOuzj8@qYUc zk8SF5o?ZMbv*Rf1)Ey?w+aLYqyK_t=zdV8c^7g~6)*qvU%XcOytxM@(H!3iRDSqvSs~4lC3@IX=JQ?eU#o)7dJUKH9!KwERP+@cf7O(|!MN_y4(i=s;cknsZY1t^XN$UM^o{AefcwfEbGkw=#@YFM_=drqW9Hm`|=;f z3ELZdbQb=9{7ApgpBqQ&XZ+x7uFHC4@B3$Z=lq#Jc6P?k_@SEo>(r6;Gmqr^{JD1I zz0aR}N9t$)XzsM1^<#49|HQjL+HU^X-1)oWSX~vzgKM!{);ZL1Oj>fmN6~lT>_Y~v z&DK737C#>rb@Dtc>+lIqF|08UPWfzfS5~RrOt)&rqUD-4%U+~*-LqNPueoR0i_;ta z&d|PYRHFCM@k@CJqu!3$UrT!=R=7B-aLL>EC9QD$V=+skfpFkq2s|izV_yctCl&KNcAXLNQ<#4eVY(wTq@*rf0k>bYU8495i3@% zSebgTDWJkJkoPZ}aw^B)DCUU{J5;YkTovkTTeLA@M`GpGLkWj(va~jA7Bs3<5#u4tZ8iym(Mt; z9C=^1yhoR3BA>5q%_J-1?cH)}hk4kf#KI<~P4WvBo>#CS@?rslL1(S!g3cSlF?Yl= zl%i}ZH64Oqi?d26r5^UwRc-8bDqvX~yIeo*uwsgd;6dR>3O4B`(*E78ybIIsebCFy zNSb?L`i5h|eXIv>tkl)r;$YV(zwMND<}H)x*X{ow9a(ZO{lcDAElE|6MYQhD7Fgyv zk>RzF&z=AP8_=R2Bx?S%e5eS2N2($e{%WFu>s^y-Wy3w4v;o>!PL zx!I-5vv;Q0Z6l_&YY!GIzQwiqok8HHT^31&CjZtQsSjw&NH^v+=Bqz9@q=RTlpT5U zQ$&;#@?%=qCeK@XAoRGzs#e(vf}C!*XC=+`u={e$-D%V8C5Fm7bo3_1Rc=l%U-^C= zhc(aa2Z8M`(}fz_O6R`4-Df3vYPH*2^W~{Ov!32-e=v=A-pyM=y=@+q%eS*hy}0XY zJwqT*LH*i^cbY<3YO<@-`PaR<9?&v*_KBJDT`tL6bsz3(by;e=)0*|@xmxvq_jg8p zz0cY#()Lm7Tv$@w8nYuVN9V?@Sh_;bX|hu4)y-374L+Zk_Sk1FpSf0X@iAucw=w-u z(y!+)QF3%h?Xd{EFP1Dgb791lYs|f8ChhQi5iK-PzjM|OsZAd(lpKvdW=z<4gh}vK zp>M=Bft=8dXB0o>@@{746D&U4SS7>1J+`GwIrVnpuM1aV4%qHrs(Z&nWRv8D?1Z`= z=LLUfO_u33X+M-Rb&2V!&C?h%5_WCPO|p3E62@S>IQQ$eZM#;??9g-DvQ+obqzfGO zg*r*uTcZ5d8aMwozVe%;bsDqs?t-f(O=a`7rFdMV#Qb`;m>3`JoyNU%;fur+ZuX+L z9DmkH^672Oy(&24Uf6oGM?GdNhrYFyE=pt5^xf|8c+s|up2vNcSfx&`UiVDZ=vDKS z#2}_^3no=4y*eqMZpL=ALH&Z&+MHv@n{VcLbjzGbJ5IrCl%3HRaLrF-f~ri!gnA)ouEggF+?EUs3*A?$}UL!QeuW!)-Q z^Yxk$9kQ`#=Bt3PBXRSry7}H&?%ELfP3XA18;kvkD|stLt`_Lsz2-XQ=l{f(WmC@> zo;Oy$!spu5yL`*mBNjFWv)^n}76~^F`^EC|Ov~X@#=E<6s**QoiYW+1&63J}|9rtR zRf+KEDGPGmtoeO8Irp>Ydbg*tlXk``E$Y?T>Y%fHhSR?lddmyJ>;$ z)f4l~S!*1^_xOGFOuFfz70l1*vT(ikl#?I##4BjF&iT@$5a>SRDX(wYUbjE$tI}jS zu9~LjX!W%`U-wdLf)7t2*L`K#1eV36hd)b{9uEGnMfx8{ebHgz4=RT`ls9`vvBVW{ z@7E~kb}~Gq*mWmq$%08)0Y&LoeSHtIHZD7Lf@y2Wq4i2U8>fFRR2Bbf%0BJ)Azj0G zXKxEJj@DW&_0B#8nI^7v_t*>Pgt$)Gebn$##H6CYR_Skt*z@M}s0Y`#MvHU{z0%iL zN@?F}Y~J=D*}TTF`@rlE)1+Bz9Qc;+vAJ{Y%90mr6h5Zje7|bj>Jq0>9GKNwWJSLo9yhT>h-f<05MQs`=oC{+P%O z6D>aS*t`}Gf&6)mh(lyU8P}~la8vyEsdD-MC@wPrsz33 zYLnU2Y&}v{gd)y0o>t7dlf<>hRc_VhoVy=1|Fj=U-4s99H#AUdUc!v%D_tx3413SS z8*1IUcI(!m=cfC9J>56uQ+Z4D93{Wfj+c3c%+hxsnZ)=cx%L+RxvZGB%T=~~zTe#> zG3`$|hR1cEbs67zF7>SMQZL`T7W|e@TY_fr zxlI$$-j{0orcJH+cRvW&yb<_( zH>ok=g@EGr2$gfo5^Q6i)*P|F|7Ti9zJTQ?N1cSJF2A0A&{Gro%KF89cJ`ySDc83B zu+aSC`=n)(+68OL?fLuuX04To_mh4y+xg)HwGYwP6ykMrUCy47Hr*3^Jmb|1vqs_I z_&aAZ`?4qar*7OABtQA`8H0yzM+I6ZCI0g3-r^E{Qo3y#i>Tq+#sC$+CJC1`Rj*E- z_bXSedvI5Xd2wdTtE~HZGCj^3j@ucdJA}15Kk*iI8(jLfOEbu`_!W2ZwRssy3T_fU z_b&zXSa_bDvr6pJzXY8bT-Wy+_nzV3rd<>l;%YW|tI&k4H8G!-@|YA@sUCW`qvMfk zM37hBMWrat%v5FZ4!#Vo#O7NIsMG_iZ7o&X`EKlU3_F`%@k4X;>Vg5TC5kHm&o{> zMy3jRr%Vx`(@Rf^p~EB<>B#O^NIUn!<ED6_>PTy{^f^@KWI43f6}J?Sbe3i(!^;U(J>l&kB%SB`J#RIhQmDuyGI%y z_POEqI@?{&YXK=NN9}!y>vS3!+&Ca4c z?a!;)!;h**&g*w$;x+6mc^42O>wM$tt~0A2nVh>Enq@ILTeh^UEui8<^TKuADzBf+ z-qg6~mGbPFQ)Ole1?rSzp)%~~9m+!4uvO46(WFCo7-6uTKZ-g$c z%!=icPf^J%?X7(@PtfO@xyYeUS-YZM2&CtwnFOZt+wMt@`jlnj^0U-u?~avG3i*Ml z+$QGhyLr_t)m}$SO)s{beJXRF_1r8OuWP$kiA>roTXSMl&a0ZVCyg;7Hs>FFUj51< zBFt*Phl)tk8sTu!M9n1uT&%@l&Pn>LR^&T>?z9)(=(QFM6CAnONsbf zu}g&Yp~?YG-HAUgR!@0dFl&NMXMfwdhm(auGpjG%oa3=;F7K1Q%o7#lEo7>nJeTvz zUfh!qF{|a0f6L{-XOklTE$UV2J9WZpTG3&nTBF-`oKnI1x29~}v24D{)^}?s3GU(!A)Ps^h1nyLcbIeRZkN@zkS#8@hkn91`j(x@`6L{8{T4N^h#a{9I^oUeo4B z;ZH}A>E{KVmsHK?&Ecng7D(mi?zXwqDty!|SHu`qcUHl$7~*nvzy~W=ZgdtzLY6g)94S_D{WB zzn3`A72lx4_j_K?*AC~dr|mm7y*+h&*}a5YfnWA-7Dzf}=&rZhNTPQ|b1d z8s}0&qOa`I>R$b!BYp?h%aT@J_eSwDrbBuLiM;C9849#*nEHe6CtnfUz@GQOXy&ce zJLU!N4>7#_{%DNz>iAXXIR5E#{ab&t*5c!WZwV7(R4<>n|6=XDV?X}wPXEVupym#r z(*6CiTmCe?RoK2_rv9bP;x8B~EIn+*=Txw!Je+!gd41FLj5FzH+oy|)-bvaOuyux# z$1_^;-VK98EwlP{BL<% z&snp8Ywh(ve{vP94ji_>#b{g|X>7fqT$cIC7f;z0-bTqLJ2I8c8>RCZ_1Cp2?qKU$ z5!~t-_S#*pwPAq;s2T{lV8Q z?a}!G-izZ_{my+>x>zvn-ldxVa~GVh{?p%B&imq)?LYT})~frNe+liaH814f`(^R; zI@t-U6((%o!nsL@@5_o@_Q?*vt_%7659(|!cVeqr8Z~w1o$fd@$FhafQzq_~lG!A? zq|CpG^|8Y26FbFA_VCN>X#J9?oih1TMFIPd0(G84cMXK(TQ2^PnDR(&Mniqm$sa5} zhnFYt+3}`7h!^qJIJcAp$u%J(yR&$l0&`(U-k zg+N|>^L+pP-)sLNqN5VKB-G9cS{pq0Vnu^I0AI)YSvtAy=c@80X(qiA=8d{ju@<%CD|Y&&~^qr6qlCToTxRhpqK?Ld%@+ zd-@;4O4xtQY`&eKa`V`VjXR%YTyvQJX3?Fk6DG$_+|AchRTL#s?fwo)cIkEA&;N%Vc~T}JUhSXKh!>YF|B$t^FpzG zYPAW9wUcketUB_$RA`pO-K7`yy)7#Ge{S;WU2}Y%?lFz5;_UPBeC?if-#mV&$Z1je z!|NpeE^+xdFFEvlW7osyavM)SoBK8R4x{Sojp0(!-JU9&HZu3E-t3sZvhQuclvCd} z?p(sdS&z0U9UoA4s;jZ+DW?XGRb^%Lia_cOnF$8CL_@m@Wbj=NlK z9J|c_XD^pfqGfyC^oT1>a zZchUrpEjjJBg>|l0h+H)FwWugO%hupQ2daqQ0) zP255v?)h!?(H|pTi}xSDQq>-{g6S}SSwe=I`oX*$k*A7}!<((=Uz+ey)*$h7-V6!< zGbfsTUNuahP1hRM=~WWy^|OD+`La&0F_TAf&t9^F_ad!ym(mFOD3Z(~#wr zUAOG6r-s_oo9w?s1!m8`@v+8Q_yhA)=d5GtnF~Lyzq0Arj-@}ERHXLFY`XhjW2z;S z#V6BSe!0&XK9qPd6x_&AjdzN;yfw~6YPsojxf5a0>$aMid#m2OeI@Ab>i3J@^i}Mf z6TLj*jLD57d)*Eldz-c~^~qAcwMV|pIP*AI(Ck3Q`Y$tfC+u3VGudnIrPp7qtP+k{ zy*S7mcU;fHx7lj_<|`XdsmT9d5?(Z4b>7r%roxki=7y_$oF)}_SnPvFo+f9%X6X^z z7*jt$$KrI*W&ZZ-RIX__2T)pcEPTrj=PM`F1}~x zkhk!-!t~SD!4o}?sx-f-J>L}JKl4#q|Ka2{=>f+X7x1kr{&q=9u6>Dv@vbXhW_fPi zE!;NwOPuP~>fS5wVuN;n_k5~xP~?Au@DcTbWk1ACy3ap|`N$fhwXfy%(eMJ{uXnZf zwOSu7|4{ug|At;&)AS?t4}>@J@4L)Wc3q{)MD};4pUi@t1uLE%tI-wizqo0G&*@`Y zYpwmRR3&YFc2H_9|GZ_D8~sinHQxHqB3`;9@oand*2RX)c#kc;We~G6@}wX8lLI?1 z@TKIOc5SR&(~8fCVX zM~3V32J5XdJA_Q49+XB|=4FZbTDnY*Vy-TzJ!qaW?e)bQA~)UE*{|rG;^i2b8o$=% z`-`2@3wDR6Sz9kymp9e#)rXzoaub#;S;nz#-$yP*j24lqou=6XlTkK`@>v8|x-QpHbbaf-`eQ!7>w>>Y7X)rEDPsA%Bh{K|`Sq9ICH`7J z(Am^%QO+~lr2Y899mzND6l%PaV1MGG$(d|b-eXbD(`_9s^zD+PsdC2g=9RsTGHZo? zWrjYutahLvSE*;w{l{BQ7PN&if4wCVvBbA|g_*40<+KC3QL=Z|&E+f4*!<8gmoI1W zefBMz9|Y<$^k;wl(6fzU-es|ar=x`TENx9(e~l?VV{MAR;Em;57cSF1$dfCXmZ`m= zzf6wrn%)7Yw@xxE*B&ywwKQU3Y~SQ9+67vF=PirveV%pwQR}VJik;u2|7Y*KRDe^!(3$vp_%i?A`V?ry27PmV8Ny z-?YT5+LrwelYN5yr5f4e2VTzb4olt;roQHN)f<1Y=2fNvsT_AcO^h+!^loW|$k_>< zRc8-Pbrv)2NakW)y7*)k+hYOkO%~#p<2GsXto7eKt8&`a6`vObMXuPh<9^XPHdfBH zM><(+J_RrEtJ9IyFXZgsCl(_&w{~S{FUt-o!5oK>vlI6(J?2*M$-lFawY+I!uzjkw z$(puPYcK2&ZIU&pHx&uCj$_g3nEz8}NqhSm~e>l0`5m7BZe+EyvEU&Whl zw)g9v6qwgj`XIRbyI-VD^DWD>CP%f+*Pn9mck8_U_?tv|z@#^Yn?IlblA`tezV+@C zlXr@3+N}NK_|8+lVINlApL{T2@$!~a3vD^lOR+$Oe5IC__+ifZ4tzukW=_g0*{A!N?2a9T+txZ+Os!tF=z~0Q#Fr8>;ws4)Gu9xl+r?g*ef&muCmp;&WnG$`kr=`%6Z&_Ylep_nrOdaQk-%>v5OwI}l zGgvHJACi%_Y{ASqO=*#HUOd%|K5f}9n5q__HqFQV?52flQ%<>^^WQ8o@1kZ!+p-6i z=6&g`k577i(7zvlApiN)GV3Q_K3_iZW?D+Ux$8&P)rqrb#m_UUPdW96`|)S}uJh-2 zTFe!QTN$yo)Px(-%U~O@VWZZ@KFT6TC4ZvjmxAQ z_oN)MKb+*HWEL#6v2{{M?i81t_Qe`UrPc*{u6Wy|^phhD`qP{yC=O@U1^7%Q7=fvJkj&<77U+sz()@|W=d9-L^oc`>uX_D9UC+PmN zE!wy**zJpYich_x-qrX?&tI%RQT+A$6RyA6mHQT+=I)vJN$IgfWv8KIT$<0c>C)*Z zwRl=g@7L~r3$a((o*$}2ZT#_G@O&%L$?JVTCN&edDX(0G{ zhrdsIkc{72pBlDr8WxYV<~0A@;${A5R`l5uQ=~tJzgYfA)%%?**Ub+qC67bY=XnKQ z3idcDwCWni>v`=_t|rYvnva8|DkcRjTinC_liSN{N}KfQAI4r@C*&^Q4?Wt=%++Hi z<9TvAr>h%_d*Er#&|@<#W<}|(b*||;e&LklExC_;a;L8Z{|fC<{lfr>YmY-eVU(X@5Yu z$lAv5;qTO+3VXEWTm7FVf0%iPIsSzG!SkP19b3ViOq{gNZIjmFBJZ%IC8gV1wfV|+9{l}!J7du#RiV8nbx&$diu*kI zYU=*40T-Sse(5N^p#1cUZF$_Sm)5@ClCl$L7nRLwTcpG58p+kQDMTc7ZorhK3pHN1 zEVAHrEtKkdBqDNjrAC+aLJdFXz&S3CQ}yOEt}5ELH zu8LE=Aa(n{-?r0IxBqY2*(t~@w%_*wxR_jF{-7LD-T($Du`L7<9=T`^!>@73zng8@^`GL}w7VIbSDO9yL*TjmNq0p%-#y>!c8*uJ;BnTA4^mdnGv+Y! zX_bD6T?D|e8Cb;2^R52E zw8K@NQ~FEb22Xk3{g=BFSJ%ndtdZyUf4TI-qByqoub+NcXD4QNQTu`SUzQ(n_JV=y zU4rG?BdbKeT|EBSpjN2wivOXYy;8?tP5$VzSIqy~@<%0qL*}gZKmPL<56{cxiIeTP zr@t=#;8d#@w~qaT)?c1IQTE*V*PcI=+AEiTSv+C4+@arJTyHGg{y^_<&YiX9j~`b_ z%)b)-QPQ?e|8?$S?{AuGM*c9m z`TFuH1NFxzzg_$j_WRr}H|cCinV#*uJu)-q>u9C(#@ntFs`~x!`wEq9ZohsNN4~6I z&5*a1A?5c!_o;7fCh%k^Ys_T)Yc%PH=z~k^Tju==HE{SZ%5!b~vK3XlBCoF>;`~)= z;J9DT?^?dk&!**Sf(x=9SugyM@s?$y+CNK%IM2LR=3BqN@j9Gc`2ODI^?85UuTH5RKS%=guzwU4HoO=0}>I3tRUXJk>F^3`*;r za@4)-K-6oog$8m#$F{wXf9b#bU0`NYo%M`gRwu4qcaH!2J;k|P*!+E?*I&CC3;#2| z`l4$vTWGHFm$wCGOBJ-g&MjEFk9*xU`IhHjkDu`Sb|CuKe4+CEso&Zeq}H@p&2h?P z@_tww&84=dZ|kes9f=!mPjmXyVk z>&GroF)*szelTx_|FWq9RcYcM6Qk0~SpRDno|xjVP;|}k#|@!a*_}IWt=4aq`*P^) znPh%dx2~IVcX#dVzd!FprCe)5 zBQz-EN$002d><=wWas5&pW3}eY&l2uu3vSJ{eF9t?)`OOvBJMyjq!iAa>Bm+*X8-} z-T!~Yd%mw5=WW|x`=5Pf+=4~*tHe99J?g_8Cp88g+_$7@(kG@M$INP`-jENPr{?{L zc3fp>HM@SL9@i%J(gVk~CZzE%HnFb`;MAOTe1Xk8x3-mn-D`Y(#GX4^mcMJ5Cv))c zwWaartX@y&U-;_9c7?a0;r~(#=EU&5?|kocW%gIzL#~Co*L1%p{g28D*Wx$46?Z*z zL&Nmv#aAstY8r|b9}_Zu+br@(Tb=j#a+$CLzDukVO4u)-Xp}k3ytg+lB%msB#YJ&9 zslN-)NH7TZHX8KaGVZm>F!+?X@nQStUZ))gB^b@67bo-@O63`MCC&|G+TCOLVND=k zzGSjzwx*v{=!a%Qxr;Lz{F0T@q$h9aHuSf2GUt*Z2 zaX6MT4FfybmE79|J5I!zx1P-)kfC*fBd1?qRXmVJPpJq zZ*%d8KG)cIj7!7hT(jXZ)_~*~j^N&@1*HRQa zBj-Go-rpB~*w&=oaSf~G|7P~?=)PmMDJP>pSR`vtle#T*T*^LRrew%*DSxN#zduh& zZE_L*Ho3+8kgvu4UlUkQ=lWVqJ9UZm)e7ahcoVoT>z8_+4 znOb|L`N6+<(6Yb{!YhjQsWUJX2jg27XpMV?b3jgFW?o2YMG5>S94yDJW ztH|kTv9oshaxq42XW1~>tj)=O!NP!~<%Sl1QL~$tA8uEA&yt#Q(&KePeBtr;3*WY; zzYux%Gms};^{QX)`6Gs3kJib&uROPUb9LCS=lAXZGks8eWp(aBn9%1RE@tzycC2+i zx+}--a)El|`O=IZPKWQRl+>(DRBl|V=)*+? z7ew6_zMM5ztlTB>cGkz-ds}#RzA$s%byd5RwY=tZX$`OFrYW-V5`7zZ9#$Q^^6*|; z?vH&f=lH|&rQdFQ`o=g!?dVF*^~qg*$7dfsu_bc`%Nt$!qx$`qJOXR(7U>kWJDz+h zZ?r->Z?f^6brF2)%c839td_1ei!>6wZt|wRE&XI=O32akVk`GphNNu0^)2Aqy4(oA zx#dT>L-kKCe8K%Y=8DzZZLc}+O*z>$Y3H2N{*%uwUHoqLw6pCeQ&;$odN*=`T9YwMIsw-R+>+oLb3Hr%%D0iy}J1rtq|R2dg+Ou6NmBWh^&kp=tNE{|oEh zUD#l)@~l1caa7*IH(RWmGVWyf%4@vaE$jd8*dZ6b=D1h0_UIlex}BCW$KfJ#p2<%0 zy)%9W`rkTMdb#hF_j=Z#r<$n|GOK$`U(P-@yF$Bnv&HmdOw%NaE{je3vgTA;`@Z+2O~;q}gTv6GT1O&gN`-CTD1@0!P5Yviv5Uz=1p4 z)H^dzV%L%Fae+I9vlPv5)~$>CweDZ?#x0fKXM61pxqCx%+UoC2Cm%m}yv5_*E6z#n z{4b`~vXxv{Y*UTY{o)rtiPgEb=}m~sm3_XOnZEY?+BwzkMzYkAg2r1F34i3oSNgVd zPdKXj>ZNU8xzh8kCn9T`ZpbU|dnOoP`e1iY`SIGRf%ls`_q~7k_e6R38m_Ouj92tt z)vi6$D^$nHakC)QWx`^aPY3^7g>CSXn^dK`=-La(&{x5VU$f*t2IiO_Sl4oz?Zy>` z*vit?R?cH}Rv{|fH+;y(8Xl?)XEM8NCIdW3Z4vG5s z&2y@h$$8nTuD(e=pS8 z`2YVJU;iz0{=YZ;w~N!-Zl+2eN~)>YQT+Uz<@?I_JD<;~{`U6!xqW;I=KpjSGlog7 zb82f(wz+dOd$Z896qds6KHBr2-Lw_5JAD4J&gYv&G0o>cZm&+g(|-Q*8*ZU}8jrnq z#2;g>2skud)kYmN%C$)&PH?Puvfd86%k z%=>%iOPKx>g6Qpq}l@=(|kShqJx-WkdT{$`+bho}KdLNy(O<3mg`lpP`g2>Rc5heNsiu zv^ZvN&t8mPZpG&QJ3Tq-)TLe(&M8ZC zFJ9z1d8NXr@88;Gd6_jqPcP3heIt8~&uHtn!q7?Q8sx73O4rq$sg}$noxE&WR8)OT zGH>JS!nEXSx(vu zw*LxT&%C4Oj&IhiSpq9!yIAesrf5B`Q_$2jTRbbXw?@C(@xae{*Cqu&J~pW?_D1mX z9VcEEznCiZa`%e@TSk4irp)l&$Kq#(TArBkqRw~jr4=n9PX$Y_Es~RDk62(8lhK{| zW&QQWdGDv~UYk-T&cB=0uIAz7Sl9jOdkddEd}3gwH;2tmYT>$wJGyO46U*Fh&aj&s zvhxF%jJ{QtUc`aV+R@<`C)_>aCueMw=JWW;@{EW;wcC}OxpsYEW}Vxi^+T~r^bd#q zv#s+3R6lDw{W%-(A$ZS{2dNSwVs=k`4!Rd?ZrZ!U@1RXwph1ryXC&+TN2aX54g4CT zD~<`B(~3B9Ugb~B!Pgbe3l!Cp;yY@yZhi6zC=ylrlJ@0?h_TJ_WA~5fvq(u#Zo4|; z+>)TS%*^24$;G{=z2dF&pHFA9?k-u~60iBgv~IIY-?qEf>6y06R-SvRx})iHMfbw` z)0?-mzWQrq`251{${(_GC$i77EOJ@A`Fy93wgpqsrT3zL8t=vxSomGql%N0jp#uMQ zj+odtQ*UnBvy?-8^>qDRZg0GPEOxklbc+^~c}sUb)1Uk|L6;Ut%?$FL{kKZ%x2|~V zo%w!|UCXX@$Svl%yJ^t@KDkY^dm`?5T>f6QFLIhw<;~uC(?0aIlxwcuvoz6k>Zacl zCl-8uSZdnwQ!ZcYNVnGyVbN2ee^zfai#Apt zmRC7yTCH@SZSAHFUxG{3HDl5ZukqDU`n}ll4|j{=U#tF(%>$t&UrBdD$;q^*i=`rP|Ex>%VDt8_AT~9AfP+ zlUlIj)zW5O`FE+aP3r`7E^PARf9zj-`4f-AALWleRc#5^1m&5o@4KHNB=P3})5KNY z7b~0IetEos@yg!?ETuKYm-HV9?VI*8()D%hj(NxOs=OCW`PXn-X;CSolG3>aDngdc zL2^tJ#j0#GweLG5+x}H!lUw>Ramr)EkVl2TI)AgQweOUE>Aje_RqhMZw;o@v>TB(@ zIa+SA_mzh;&&zLBvG3@=^= zuV;IE+20=BY_{ML#}0!p&4+KhEq@!c;FHLd>l-H4JxJU5GBiZw(Vm&@!7m?P`1=4$2fhjVpRNryr9gl!I@t}BV7)=EO{#P@`C-*z`kPMLWX+> z-S%{s{b}9tUsUVgH1XBTwzFTp%Y2^i!kQ!Z&N`Nx-xX2alYZ0CZD!Dmnfsqtx_t{s zz2hbLyyBUec=m;_K0BMQ?&{gZ{H@=n>#1DCPVQryne(iC9|+ja^(oWXR`??%cHYrz z3#WZv5p`r6XIJYnoo)ILx_&MV|MZWq?mJKT&7YtBlm6)E9NJ%K`ET;}#b(o6dSoqf zCjYS5%lbm|@_+S$-QJHx)^0p+Z7Xzm?eoBm9m_b2ZneAlB`mgG?i+8psbjA2lphbz zIV|Z5S~s)ZL+|nW1vZTTyv6P*yZv|GE07_?xTRa+8wcn0&IxBX%$^hGz3!LFyA86} zURti1>{os1*^bj`u}x~X`jxNyc?v9!Ot|T{Y{AauTduDYo}$&AvC(#0!?mVlp{bQ8 zmsFf|nY;CMuk>AI&Yh;J+s)T032dEkWNBp_U*#F+BY*m8^uxaeu$n>MVHkAJp>+o*vKI!ok2$AjZHD z;LXe;!ob16!C=(=%!&aC;JE-4-t$4(616m(vm)fG=)e3lwft$*S(rH4ntE2uIHTfn zVHNKpHy)wZ4Q3)+uDE~VX`VdOVy0t(w%*otxo^|9&feO4#Y=RpXU~=gLA!Ts$y$2# z*43=7*YwKb*L<-rkGrSCV_5h1)6=~7^Zw5Hf2Z=zTJ~=YGnTJvHu(5d!O9@x!8ZjP z37!ur?TzbM0_WYmqj)$xbw_a9T(*5`A?2)r-Mdq_diTBOd=yu6_dsnO4{KoWLjkvf z{f&V;KQ=VpW!op{BFpA_!@T*1GS90G*ZbL1>ohu?4RRhlRNyltA3u{e6&mZ$8PhZk8Gc; zG0?2mp4@jddfG9z7Q2k4m9@!gx%?U-Piy1TzIOYm9~0X6#gj|j+~>{|=F-eJicd=bpcPbGB3rA&J6%UhXPvUQo% z%y%VfsozD|=eMNax-GJ7(mEHNzklwf9yKoUZ8$CJx5`EOp68|(kDVvZw(TI!*)dUgn%=zrX+=LAOFzs}|HrYW@2i?l z;Y_FNM_&5R*^s2Js}Yo=6Uw(LV&~Ht_N!f5xNYS&tbONu?(ND-9_veo^kxd>X;v!; z`-?}K?-P1|W|xC~90m#D$G>Y8# ztWDxj6;Dir-(|j62Kqo)Y&L~p9hQF}aV@#JftrH+|yQCaP9XrDs0>%ykcOViqy?EB_o zb@Yv?wGgNER*gJfo)d+>iU;Ht=65#hyv^OuqWHRE{v4hi97{BJ&3JE>dZs2b>Zj1L ze)%2F-jZ|TSEokzhs`iNr>f@e*>Soyze1YhO!I!HE5!@HJ!0lRuD`Q9NaAsYN7V$A z<5y4mthya1Gr2D$_)OBe7io*Q(@%e>epX(%!e`B)tk#n|KdW9lpvHFZh}53rM`lK3 zC0T~ei0BmMa`z1=7p{F_`q3`OVB&vHctEAv{zSq?koyg z5i{FMt?F>HpaAndgAeJ#^#|Jwoj+YVd8G1$#+B#iO1<$mf>RhnlW!wHo z`E3949?Abu57wXKvFtGO%zytN;odkeDuUDt%Q^>WowCnbg)D{<@57)r5s-n1b&tGB4E2 z6Wu1WE2MR$R_N4~Y7=MA^3n5X@)SCpCTzRmX;Hpo#HOPT@qP0TCvW21DSP^}($mZd zLhDby+^TUhExTrddYtLVJmbiIG=uf_KMm6<|?yD=D9wGZ;yTb z#BzQ1sYB1)IQBb;vF7ESFV7MEspGvYM?LiD$Id@z)@pc2{|$KIou_!%lD(cy^w9F< z_LKEqO-t6WGGwcZE-KyXt2ddu=E!1JR;gFk%logpnlAJE(kqvewxdtur{8;_w=w4{ zXE^^^nDJ?Qie$ayyo2{w#WjZiTk)04rf8m)$Li-(tMr5mt{HEf@!90wn?q3=d#3L; z-toEMoBJZ)ES6VtwZ*c>719%wc}kLP!ymq}owIc539lzwdxbhvXT874cR#!G_GwEY zNyo?(bDP(04`iGAPZ#O+Do(U$aafYcanR$lfRp9P_8>J5$+%N%m5#q;>4?11quk-t z+mW5C6!~tQnPB+rj>Wxejxfv3+tg}NwfCI9-8pHci?<(se%E8i@>%SMjrC&wLos4I z`5V>#@t^Wckr4I$Bk%T9_uRf!li5Sp#$Bzkc3O3Ab>xa?jx3v`&!2l{rT_kYNv@^n zWDCB4v{_-X4PH4~1{ zPcAb2>mj%I{?hl_3xC#fhzY;f)U*klWD(-?C&M$T%(=b7__2nijryq!*AlO=H*Q~d zz0y>kvCCXa@{r0#O{=b1Mr+Pq^;>&xvbw;b$!B_(M_Btm_OMyJ^lF;rE=!Yk%PT9V z+VDUBJp07k#@ApMAcHe{wlr?0VkWYx(-L+UGqU_3c&$368WPg7*6?L)c*3vgRr=Q3cx9scs z4Xff(x9({R?%+-iHEZYC**f)=tLd{%QQI?%Z^d4{ZMsijs%NF*#I0uxA1MWWXq;l| zboWH8<@xWGeV?yYyv}zH-LflDqBp$iYTw^{7uESYk{w;5_AV+4ITIzgR&AfjuHRvi zrrmRkqiX|?|1RB^xTWKL|1*Wzm78YH=Ve)0{-)j{s+LFm;;Up!t&{s4TaKSd)n<8r zN>D*yYVKnnt7%fQ*I%vvY$+w9q`kILa_#qd&Rvho-_&bP&s%*Xt-)OIf%n#~VqWlT7W?8)pGu{w>^>L)B zH+z!k-Pef>dPmt`oZvG_ux`B6u4vYDy0G~ zIW#yum)7dfsW)pP~?FW0>^skd|Z3uOl7j zbv^f_FdZq$7yGxbm7Dnd%0ef|+q`Jf)uyl!>A(agflz)&KIuX&B<{3ql& z1?T+S-26P1(2~rYV(2Jhh_AnJpor~yS*zTY4Gu^1T~=*-n#>~DDAb|k;uLKvB2@Tw z#=Zj+Ui!@4ClxX4hx(me6V~P_Tx{vJuA5SIe~XBK(2)yAYm5EgAFq6VZ|2|l``;OO z5{x?FA7);#T~ z*}6q*4^#YB&dl?>)V5FGnXb8?FRSS8DgzT;&(q6{&E8uan!T}dsnQAAQ&vt=(z7Q? zhpo(!cD=r4T8naT(~T+TU!UuV*4pWJX#Ir57ZJimWx-s_lXjk)^ZMzUNf!*CTwmw$ z&ZFD=`enm27p`@j{#bOg=$eF`%6++SIa{Kq#9f^d>Mz1S>s;aFRXM7C*L?oO>J@uw zx~i*piRtG|byb^s_rd#}iN)!@rh%3`XPaif=5@=Nrx>%UQpNL|($AHrj<^RVzObCE z>wIJjYq^M5@pqS{S>C2Mg7pMrOIFX*e5Paiblv37QX!UxCd$Vy)Ve*EkV|wqYPU>v z_Plvv|1x;|MJ(D1WrcZ;S(>*lt3UDU>8mz_rF@TUzwLizbSC~rLWfN5M?+o-tI5mr zylpClLfe@*TLkKaAw z9S+kvo~(SUt@1(YuSNoscST$38KHd*qVr#HOw2rPvF5n;D_d=Cwj384RQOEn~EHFItFDiOh0+-qd>Tm;4h`)g`yL|2M1+LeJ?VbiGg81 zE56jPk9+VOGxbB#z4h1p>vn8xY|dyKF4o15GF>uYb+nK;qWSbwXF z{pv+3f%eAR72NGvSGmatGb=YUcy!nKCB^O9S05CXRm7>>Y6M?Z+7uq1_p)~4ETI*fZ_Ahyp)3c%)AnPr=0xc z?99A$-_+vb)V%c6A{9f3*Ly>v{e>Mx{;_$9Pjj7M%@rlMb;{{&U5mu@FNm!Ob9D5m zFg#tBBR=hJn*NLUhj)*pcZ4PN99t3iGw_(P_s$g)Hq4%DS)6vRd|&a+n?L_P6mDRd zcV(gA^c0han|iu;D7CF<`Db;+KtZgzRN~ME9?_3cDo1KU)h1^r<+~g!y)(f;>!F(S z4Q;8s_&JKxHt$%zZqFx^s}b5WwYGm!y}iMv^w5^Cp@+3>9<4jQmZ^MFifLLzTlw@v zjjE!}|5)1sPMs@mJ2ofrCgM|LgZ;Vj}w2-r03=-eqQ z1tl`s{NHTVcPv>gdw-Fkmc*4`)7JfLU3C1ywCIc1Os`&9(_|H2@@D!WZQ1G1bM9aK zxkS-o%YSxDoi!S5JxgbAlYUd-YOVipT9eqFumY*GPOkzd9GTH%{UR~L^3c?l-CXY; z?rSRa@$k^}P*zS1Iw-PCa?yD$ALZX-f`_|y+^L!PY~8ybyUf?`Tzy!OHPR;FLx9EU zhZ9?lbEO%0o7z@R`zG;gUgE0H$7X5t?DkUe<2qIn9PGH9Bd9;Lc@5CGVVPlr3~%xpL>-nE-op+s!{} z^fphZoRyf660-iKRpU3+M}@CGyvwM6r*Q1>Ge`e&nT^MJrZ(qK9u~9+kTvm|bl0N&A73t4y+P|Ds-W{>Ta833!J*FGyot>U6e7fF-Wvkl1 z-v28!o~qv0{IGx_(&fdkj76v0O-(!hsjckVC${C%`I~N+IM%kh_3`du?%wNuHLYOT z++zku?EeVLs%Sg4_4v&Z&3NJF&-&2RiP6dGo7kG3SG*=~ycU{ssQ|I<7Xyy1JbLzkw|3>ql?5FW{WthexS76XlYU0B{e_eJ z7IoJiX87F~_)R$Zjd)Ow`h%N(Ww93S?|(9A$0o-3&J-w&bHNSMdJl zx5uY78{8`b99UOZ-dOQWb9Z9G*<-%U*K+P`+IVim<8Sv*sYty4ymGbcBR@Z(cc&Jw zENbOjKJiND?!}89^j=w9YdD+JR%qjH?YM3Wv4>?7PIwqcw9B^L30tsa+R5U!kj0e; zCgiy;Oo({rrTgdS#egHsb|FWm><&C|m9c;6!Sp4neiGMq3D=#mJ^J;;=f(eQB;I>2 zJX9v*{?WM2$$r-H#v7BDEhu^z%kOJwn)BMhb@NeQqdq6;@|-)R4<5~Hw&CJ?xA@(H zMm6WR@Bhl=EIPNrGx+0~5F2CB_t!)AbO%?SVPIRncxy*=m#}TJ#^1~f(ta)z3{3P^ zpZM_P(%JLtmsHFCEt9>eyF^L|Cx8Klhxho z_AjSd&j_8-c~Bj(q*!+Ki3MG}MUHJVlr&R%`@YJao)X@%`cmYf(5|odBe_z$#MVt@ znsAKk=GZORiQgif@ zLARi64a)@`c~_^$!t_!|KtrF^J33>wc*X)P)|DamqM9GN1_wsv>{gkcnz-4!e0qoR ztMwnc|MJ$YFqX2idK{kqC$R5%&NLN=4J%)?X5_qomUuk+5%umAhYy20?t?2EnZ zieDZq7MK*lbMag9vml>oGju-RM^v5F&4 z3@7t$`;aQ&-&CP>;YHr-a~D=P=%jj?Z!CVWiqm#`y2_H7cQ=<@_B|sNmKJWlRrRIC zr7KHpU8BlNgUgq*?(4s@E^L|(r|yq4K4#gIV_Hwlo3bq}`ge6_=p#9U>2v0Ly_e83&Slt*Kx8uTeC(a!}sN~n0x1Qy?!s;m3hIl`qZfv$7W@{-t(QGc@A^q zykNcaxvQ6H@-nJ=uC`5IQQ|nM*p%J2L`+Tft0Rrs#TdK!ZE4#^a=6rQy#SS zBwB6>)>xr)d|6geWP(|cD%byA+aB2}aa+0zzxd6r^69uGmuF#LW!%dPZ|WZkuu4Z+ zoH$|Yw^R6tabw*nzf+e=UM;D7xntMLPq8Z}U01$1D@$_I)%7(Jt0uoYCG)*aZ8MX& zvgo`uIqw1v+WJQsxpqFf__69&Qiy+a)~?51)<>uOnl@{-67TPIc`BFgY&X*74SMMQ zU?KP82=7pFmHn5m?VCICdug3@>~g6;V!M|t5T7pc#gR8D*pV%o%fv^!BRS$AN1mpK z!OgaH3GBPM+zgi`$drpnC@6==&vs-LbP+u=Q9UPZE9c!D~@;=M%4$`7C9tOdtI>{in3`nAgz|W64{*z5RV`8{^l``zLc^ z@4+Sg^OEhVo-Nzc9wXyuvax*S%BR=F`uFb9;oU4fQR`y3biu<(>+Dt3R%Kl4xElTS zt-7XHW%NvFd+_tg?}FK3j@iL)(mR->>U3`AJSi6Z{6@o7@_yfgi_c#7%U{pe`7M)V ze?+3`QCVoukw}SylO=>(3?oIGkFD(A==iUwXKs&RKd(4PZpD&@XG~7&$+Nz0NOJud z^v+6C{C&lbxl^vMn10l6k9&;m+)HPc32*!ICdXUcuWFuCdqh=ow(t@57kQKF-Y1{x z|DYM#x0J0bGAQVy{R;WGe{IvgTFAD(yk6C@ZMyobG+EzAh9VmqH&i^@c`3BzV{GOk zwY}cHhgE+tT;8{lc~as^k2MY3;}RxJ`zF6a`DWQ0QLBpoi}t+NVXx~IP}~$^YAk9n%L}T3qZm_C53?{ZEaJge zZn{!bZU&bmmZU;T&81=Y^M&07{+aDO^087_<~e)rEfMBM3%(~l4WE=76XrPFm70Am zOzBfo-)A8{z4B{6?=1W8^Phc{S!dKre_fB-?E9ybYxO)7;sVoUf7b{o-&FA4Y`oe0 zzWHWz>*x0I|367L1Z%V!_B_@~n!%^sC@JcB#_Mg%6+bUS^;R`kucaN8E9Xvoo*QT$vd*)R~ZmK)`k++M-TfSlfPoexl{<`0SsvGsr ze~URDbNbP`g4n=3xfd7g+^vF7iGA8`+*(to8l1G_LZ$njPS?2;UYJa|w_#dm4Y zXCC{KLe+cLduQ@%=v=Z``pBzp=hWYtGk?d3?_7U=&GtplQ%fq|#|6Y>KQ8G?^WHUE zbK>gnd1sAv*QVs1VhpU^a3SZV`CXF^p1Wo(q5GFNmYnmr_BwXsw)f$+&U~$EZ*G3q zIdnW?RP#i}2l3qQo#?pz4p2+$CWBI0BRlab|)(uyz&c=)UEN5u{ZSk@E;g_w4f3_FQ+j7+M&Eq-w z4^{}d-*o+NH)T1;`=fu+OneUbUa5(ekN@q1>HTlW> z=wC5UvFo|ZcP96bLd6xL3$E3?T5Pw~Z`z&N_YU{kw0$b@f7)-TwKd+bLfdRhGxP2a zHjU#idjmHGM9M4WFeK~rJk}9fFgx$U*MwDi{SSkql9%vamT&XV@V!v=^3)OVyzsi` zf6_9U85kyV;LF>#q~vXv)U?#1qSO?}ZMN<#zlyJKzHhl`>lw|!Ej#S5-Cp@;`pGrY-A6x=7;MwP$pmJ%{Cmz>t!tDAlOQmpru z65|gm6L*&Ioys}9S-1S^C)txC7c~!M6-!z>x^51WdC2mar!{zr&eX7#Ru!)==mjmi zEEIO(^GI_~tHIbfjo&`6^4fmr3w zCA$;mUo7vqq3*<^oFbff#=UEsq14m!3-tfYI_W6+zv+jfNaTgN-XV7^ zvp1#vu)TLroP+Fq30sGx_wrA*UMj!cA^WUHvC}%Ge@ekD7rU$Z0oOKVyC2YHug-ucKN;O>E+QRh3#n z@h7`hI329z(e3%e2CBDOcq*S2GBGe1;O#kLuIa=*I0H${Ya_W6CSNc8_wKLi-${Rx zdwLl^iX=Epo4<$WhJeAbhL!Rx(miwaTu#_;Ytpf-V#wUJBsb$yTaNekCE6yw)3)@^ zZb@srvWz!2^YFEj$lXhFUdz?Kx%lR4S*rK+t=`kqp5OUDT_=a}7%%7dd;jkhpR;{m zysqMDxPBe$0k4a%9j*WMwC7i4{t)A@KR18y6_n$o!;;%n=IR4XzaGRR;_Wj=$ zao0a~)c-fl{=eVx^1U+}-+w&*edaCxl0SRJm;RV1ZvI$)PC$KKiFEy6<@x_7_sLfo z%CG^Qd|7dFe?5h8dFZO$WXzIQG;V=9DsjKC^3m=Wm|K0B9 z+H=z3|6vFF^2g#<|E@QGtvKBs|LA|op0$s|^Y%CwFzph^Q`{S&Z^9(V=OpMCyQ5>v zg}paa?#R6nmD8_kou1LfB*$Yn_nBa8(k^$APRY1H9j`k{YUh{o7=x)v1*uf%R7prsas1PHEgzm-}Gc&r{CV3ib8l-2N$l1wse%(HEi{R_! ziyH+TU0Bn6EnfMw1})Q@#wC(x%s;cU<>qw>Ki5ZwjBB?hw;#B3?Y6VKlj+M4l_=rf z@85-se6`P}Epj|Cvx{dIXQQO0L+l>c^wx(af!#}gtP0q#X|UcjZCO^H{WPwtGdAv9 zSfMg))kgl}1J-AcO!Sy>pj&s=MS<8GGrcbCWl6meu-m!w!UBhhe{Y&j=#b}??GcK~ zhqm$5x+e%9w=V|!(j?*aQ`cPC`3{i@ubX1+FuBW+{; zoHnzbhc0aGi;|Ok1B!1>J(YU(X#cT@(w#|VGJEdwEPt^N}^!tVgv+K7R>I+G}fDF`+fcO((Cn-T7keLYJ2PZ++df6r6fk z)O8g*7xAk7*7Tb!xx9!kvhVRNiB8ubbIvy$G3Vb^KFQf8-dkJCxogeBaL&u_--IHp zI4iED^)<5I@ie}g_|rKvVUe@J&q;O0M>))T*ZsJsa`Lj!j4A8Xk52A>R${VrM)0dm z%{_PRT-eQ2imfO3eVzD!QXTV|+1e@WE!LCHxJb+m=sBytPBYr&#H=$lDq=|obe5(z zp4|A1$2jz8OgTQQPD7+~nJ~+nN1~h4 z+k;i&E?=6+{pxI;%KAO){@(pid8y-d-#Xk-xRq|)8g-(6Yrq>nC0Rbfrxq{!l+P^Qa@WZuv`qH1Qub+S&uw2^-xkNmE#J!M z{LmnA+SP08ger1A9WwWc_1)j*^<-m|Tv*@7y_0^f+sC-C`evr_jnxv?pEvHB)?t2+ zVdbaQQ#SA%H1#Ps&MUYl%zdKb?y{~LzYN7=9FxSp-R*e$`Qq+-x}|5nJ-D*P@ad)b zJ8NX)@0qE74}11DrDF5to}dqrm)`AObo3OzN!kCZefFO>HrjJ-;yV-nnfdAUSKgZs zXiM%;F*x{{hq5i6t6vM(R;QdBe%a?DX}hMKobqJlO{UkIihe44?hg%J z{a07hUbG>?=Ba(gughDW`XBu}=f~gXur`lPId;|E8elmXv*=z;Y|= z_fo8v1imhE6qn}R=sAJ?tgLW>ztyqzi)7fA_sg0^Pf5?;E+uqSAX4q{WJR-XU8d9O zad#&AeLbElEtK$C@M>%Rt3}fy6#X6lWraB`R@~Ob#@zp~&}&lgcaPoPhAxwD94nd4 zyD|2S!4bbAW1h{+ZG4+E64&2I?f9PHAilOOL-_5k7Y0Z23XP|#rv8c0$dX)e>;4Rz zIfuVr^vF6O-<|$rz1b1DZTB~Oq}x0`6_eHBw{KIouk?&HDZ6fDchtVQcQ>j2SV?ka zbJR6Xjkctt$ep;c9OY6uK%Go{VJY^ z*V?Q)e(chLluu=aR%U{wmHW~vYM!r)+H-8#x@mpinBU62J;O*q*qo{j-kQ+i>l?ye-c1?Lx;zM#cg2-hXe4 zojkE<)A_rTHhN#Ze9C8|((=@};4&X+k-Ei5INDo0*!Hmj(Ge5!8*JrD*zN-L3SA}A@TAeR^*Y60kM!6o+MkGiadhQz z;gAVVUoL%&sJkJt^y?g*`8(H&ofWw^*V=j)e~H;-KFvMp&ofWG=yX?!krasEcdR$@ zL__hqYnNAwOX;tj-}H=qotMkrjgz-LdA?6weVvV9)q|U_=X9;9GgIBEX|~qq!N$1y zSC?MZ1eUHnRvaeRa_>`Z-_ZXcuG*>;3`2M z?k>R{=QOq~HaXWMEFj+$e206zMc>Ouhi7QMJ8Wph9mP_hes6hQgZ|OjBRc|Ce-}O- zw6<Qz13@0w=(OsR_a7l^0n41JlA}%xwJk&y3xEs?6P~n0cqERpJ!YYwrPJP zXz}yH;h5k>9CaW4r-baBsg8m8W6EjqQ{XS}5=upGW z`BAH{EB|@MlZY_o<5N0YqG}oBL!>O*_$OLMD1U#nBe!Svif`Q-+N-?X zzwX8PO$#=Ci9PjX%BPQslMXEUT05!jzv~iRi>}JIiymqIaD5v5A>^uc+s1!3&%TF* z_9ii|tW$ii^Zano)>y~i-EZE$yw=D1wAf~TYNn;lkxQvbFL{eP=1+9q(;4)UdyT+; zm!%cb=7R0JmpE_S&7K#uq3yS43Hzx{tJ~gm-8jQ_dD$Gd6<6J-{I=LAEU#+O%QN-h zj866w0n=6-&z0xfApd2{-jtoq^Y`{YFK7pn>6|-OQ{NdZVz;*SpWlvQYr`g)`?X+UQ zIn(vujna_KHK$hH^jUS&Y1K`yRhddxbJVZCQMtM$#@%$kH>bOi`w|!S-F)|gWUgAz zRQ>zfEBIcp$oH;;qKDuAsgSt*D)xEcy<)zD+%;7~m(ML;w0y>#i4p5otg&j(;@;Et zRPlewBp24NR%h+*ik*6{u+nAku)8lwyxBiM5;F zZxMU_ZE>uE_s)mQU1Szi>VKPT_AU6;^Pe1hx6fPflhbBtn)i491WsMeo)q!4lY2j$ zmeZMfH$v_EVy}Bmrl0nT6tG{^Ih--I_J*?W9kt(yrx<0X1s+M^aZiycKdmS;z5Kyq zqsI1BsrggfKW^D0eE#I_52`=w_Gs8QOn<`uk+)JmZu0SuvX%063h$4<{=^tFP5ndh z&jhmt(=Xn?fB5i|_LS2(ANEZ>`!_$e_)@OD5V)S#Z(z%C{%wC?JG5fgkoIa~| z|LwUeH|u)KstazjJ?uGeqI2KfMO}9vrG}>G%wM2&WZCoDZF}D;9M(8f$nl$tKmOs) z2Nq}Dm#&*UqgL*9wU)?AUYA!gui774b+a8?X!5{8&@9Q=bGzj2D>V%Lk3DD2U()_@ za^!3ICmK`uohSECV6S0v{iITPP_t`~d!U|uYt&DPS5F?_P?&#!?`P(xhVu{7enys@ zUS8;6*If5gr}9AN9o6}V|9+~h@tJpYaS_Y;6Q3<~^(QRV*INDV3CHoJYjpKfb1OBo zPkV3EHQm$YAN03qLTy}NSZUCgdddDv^SX6@tju9s#UR3K76QL70riS!9Qag2|$!O!J z>1Q7szbY@*`mtz@p4dd&HC+2NR(HE@(^L6>C^df8Chdy1kvR)jORb(C`XXXs-bNF{ z`*HfJ@^`I#e9v2&^uFHm#6Li-zN=wR57$q&tS7TAe{MB99lCaIyz2j3X~i3^KU*+m ziEhSO6MwJP+git3bki80-Yz&*o{%wRjp@W<*JU${Cv~T-lQ=gcaXdG_gezrNF94+CR+Sfzi|D_O%mCmUsrT3 zIuZST#jY2{Pr{b?Jl&*p-YMg>m_h#D&7T&XuXN=s4%!vdy0wDeEYaMm^Ri#bYD=%Z zhYLf+>=&hZi*HXdTQJq(dfK7oQdOXk&Y zTN{39(c0J5o2n<(3++y0%%7XZczxT1DZLt3Ry1UX9N3zxl4%^4aeIB}0a-p9XPL%l z=~quH&R&!G+@#dD=2PXXh=3=@ihnrI{>~;Uqrkr6g{r!Yc;<_fJA;mY-sb<>;&8ao z!p#+lObaVrPE=Q2YGD&us2|fh;kg@UZ$gPvu$!pX{)Cy!d?qSBDgKcpmr`4FBK}Z! z<%HPD&UXHtmh)ZLHO=$?=j`>*{!sX*f`@Zt#Kk{^O7EbA_%b2~I64%S=x7 z%q_@)FD2&nF0t+WtC;?j zqx=8N8I?)w^IujS+|6M7pZUvQ*I*y3htXmJ|LnT>84`zj=Zl9V?wX#Wxfh9rIIec0979l$noj^+aU_#;oII zG3gWJk~&P77Yj;Evhtj6;r)1BWWia%Nzfv7% zE5=k2w>O^SLABSlpA2zd9xr8x<6FddKiu2?!{c_ZAN^Clg){9~V6x}c@$9-idJkrs z=!P#)vr0W9^>9g|>Y>ArgN>e*aoiC%PMU0Fr*SzmQ+0{*2JI|QbDPq0riU(d`QLuR z`+WP!z=wXbUhZAX^gEpM?3I$Dsk`*eC8nNRBRN?xPix=dWvRR7GSze6D8o}F0Tkovx=vSmk>+1C)a zv?nWeI$TvcGu^{Yi0*)SJ|kr@YRX_VL6rTY3=*? zloQu!ul!{)i&h%WE;w@MP0#P;KYEUO{C05sV6&yFXUpw!J+_*5(Gy21_<`ZrXOGSWMto=3&Dirh|K8)M5*+oU<^z znZGJ!t?r~uU9U;Ul0P)a=V$ydy!YktqPF=DmP_6GV9cAiB`d?NTi*Wqh2}W>x`hv? zS9l-3U2(j>+*Ie$B>DZ9KFHPSUXa{4gLB%%E1xBodLQ37x9qMr+ue!Al5Kv+zV7sl zS{l7=_46R-W6>sm*!ExjVErfVu>6N<4*vW*Uo5b@W^N=Q`Ks&HvntlNyB_W`a$WAZ zW0ivXG^hV7TK4s?XygB|&|!s3Ub*_)8^u#5>Ra(n|0vkJJ+O%@XTPn~T}flf@H@FL zL@R2}7_RxUo2dV=d`~#v-O44zZUIRAJZ9Q{Utwt zF-)B?EzjTETYmayv!A}^Ytt`HIv02JIMc;Tg(t4=k1HsLF+?A=FC;g-YK{| z_@}h=;4D4Wt*#G`@2KrkY?NJk+WoNU)V}M5ok#EH&p6qmY}*`SmJx9%KI7N_l5d|f zV&i8dPwq2$lwFnm_-=M$rj*U!OF3KD=4`uIoi&S<{qB}2eup+1Uw)`=X|>Aj)s~wX z^OxK9U;JZoNF;qU1n{*W9bK#)9;OD3ilLS%&OgdzK4%z zzJ>Lz@;&)W`h7oL(YnyDvEcQ~mD9Z>uluZf`0dyAZ%WlgVMZ~c+DfmxK59#Cx;{;UiONL^_&I`i`P9&v)0vTnmX_L--(J+FJ?cu+PY_n zX2vATlJJKX3m#OwocHOScI=U^(x-=_eHC=?KD6{s+;Z%$XxXmlM4!(~y17ln4=3LZ zdiUe)j$XTb|IA+v+3C|+wzXUnUUf>Viuq*oYSB17i?4@@7G$Xf16zC_my6;E-ZKMW-g9-OW1$@QA-yOTxS<{ z;lhm)=0zJ{7U%40HA)J7zIs1r{Nf#rpN{SNB)wvX-zwi9V)JjGILxhn>ZoCk@Z1}k z^A6+*9#wo-8f3Th;q4b6O3WV^$SKd4Dt*+E9?mTH{KWI#DZNkct>C^pFLzJqlbq~F z@hkqX%5r5ee75q^rrDOEc3+-KrhBaYc1z0M`KSFx*S&cM&nrjnESB6oO(5dPxATEJ zTOJs#5(_+9*t@M~{n}Nx7TO3dKlzPk)ltbSU7MfOi?O?`aj1=stF`Y-yV~76N7H_N z%2oN3tL~qfeXI7l_{B{vuar*h-`6wi_FJ9ru}_0sLwvQREJb=x@0f3RYtbU7NA(N$ z_)MJgpE-Kx*0)A{yjA396dbgtubN4L14qF#dA9?tMR zT|E`N;zwTZ(U1Ld;ZmnZTL!PfqtwGwW%8K+EU-N$^T4rHUEnOM!9?za;%g__yN|zi zoTaxe)$uax?|-*gYG)tY-)!|!Z}MlMZyn#c4qcnWe_NsL#L`3CnvJJ+aYruY7Z2Yx z+iSnW;ghp$%{PAccD=P_|4%WwPalhJ+?}U8!|ML@xBFCW_H?B6+dkR&{#;+U)5iV} z=7xMcj&t)RdsBA#dC$s7wLa~*xB6r69QU_3e7Nr~cbC7gnE&NP_Y9%%LJytAu{Ax1 z9|^ZT4URKdzi|H7Pg^1m>G;kRH~*YkDZ$9|*i%3Bwnfz`?Sri~EA2f_Is12aRQT}~0I|GBWAin018)OhcO^M1Hz*VuKA-pf z=f2|fXV2fSzt3>zkSw?JjFSqjtG&)>6`no9%Uvm=W1%r?hH?ticFjfGqJ>*No?5p1 z?X(*6j45HMFIan3n-&UjIPVkp6zrG~u!6;Dn%RAi?J7-GyPvXd3K0!_Vs=FN{B)%? zDl22=?t9HTFGkJg^!y#KG`begJ0ztXoq1LAX2wzOBa{7#V_VMOEwz7kan;U$v!ts| z`ORs&^Fis*lLs4qJMMku7R|C-X2Z@$y8~4$-a5*!y`J;C_5{ChYG}*tINvFj7S%c4 zu5o+b?bs(Z%l^oNm%o;+IJxu?x8H}ox`C+$F9Td;$8IQNIKWO)U{W9HwcJsWM##yb9~n%Ktk zQbLj0(kpRJvfp+&%X3a^R$7W=b2W-(b2ZO8qwS;iKPfuYYx$1uDI4SeG+wbb>AF90 z)uhjYx2k(qCil(v_js@9?RB>`^Uc8v)0c-%y61bza?$t6U-o?ZKv>_n62;WIfcGgCKuJg)Gx+>$Az==*iXvkzS9Ggr2`>O7P=XUzTVLb84# zP_N4Xch z;$9RKz~!NEZ*DJZpV_?=g#z~j9wh$?2z}*jzd$~;bWdcbxLilLopEv5xf{v9-|xR) z&tS4ac2Un#0mf-sZ*;9A3O7h4*dAb8xT<~cdabROPMo`WL1=~NjI>X8Qfdoz*Sv{I zYq3o0>pgkqL8tl@d+oJv#GNwJzjr;5PnA9SYTBhwB{#CYi#2a)8gE{!BlvQv!KtIH zFKpOvM1Hc*R=`Q*boZ*S@H_iH*r*Uvu|RQ_w`B{Ms{Ioz3fp-Qv= z6tC7Ol1P}$;FO#$Q~LNq?)}}rJ#I+*yL0GoTIi`VU-A2v4?fr8!tZo(2*$b2a8Y%7 zk-#;TA-cu?vAO4pos$Z+zLeHndv~g3{oBJ9x7Du1&+9X-(`U3_F65ubkk`^W_te_s z^52g?k9+!}MR^~~nd|ijS5L27^yEOf!AIru^U~(Do_|;Vr0nArK&%0^81rE#X#u!J*In4H+`@Cr}XU8Qrob#8+kv@(#?V% zQxtGtNO1)t1A`IXC9DP{r3Od|cyteYO-SfBi@LnZ&uMD>9Gr?gED}~r1Q=O)76dV| zcpgw`a1?1z;b1=LGe?Ev-L2~DTZ67`b$rw0#gx?Oda!Np+I4GkyK_rpukZV0{d}K! z{yiTx#W(N1|9}2D@!sC=cZ=S=e17Nmr#t%nc8mnHDbwa>qNUjEJ>S^fIy{{x@Dul&LIPo2Mhe!YXP{H~wwU;f-U`~S_e`h^?o zm%9FQv!B0Yqr(3wY&CAocIBV-IlA^=J};d2Z|Us%r>%~ETx^A4 zsM1;PtA`c@nYXx<_zT;*SpEHS#g#26I7KOEk@z9CO?MWVpPk|>`+JGwt`AE)_Z@mJ z_P1o><5snc@#4&v61GaL;NCBOt;5meV8W~f4qt;Sx@|j;7R*X+VP7YryfXX{?vfS9_7PC|c%iYqrb8 zXrDzV)q?+Pektb3{S$HPPGOv3sE=~N^4CdhU$wq%(s#A`d*;glHp6bO%@cJNwX7=M z^Qgjby4TXoMLuU1_nuk4T|HpsoI0%)QJ(hPFVYo#cXibH9obmZA01M8G^ub>w9dlk zC-Vxq8n;aOHSd)efck9a4xHE-h~U8gTeOQY8mb?-8nrub^5+_L!{ zdQu#dmkX*b&b#Q*>zjA+jo9jy6;@1bGRoI>9F1Bv-!b_53uoGSQsd^M_cdOQPsE~3`bpKyf!bcsc9(w5c|kT zfA;bC4~NnpeKIL*-Em2KolyAeM^afkrycv>wkyv4>g&B9w(gi?b!S1h^vWXPzju7z zU#q+kwDF#$`&Q9Zj>HN7I;g zw1(|It^3ZeS^kH&$v?U6JFe@#EAIY%_Yq^#1@=zvZ2_6uh3}k0sv^YucN{g-+7^^7 zJyG=IhP%3DJB}`nyK#E{0r`!WwdI8Sce5&e^W1)8Y4_c@XX5*>ADw4n7GdKmVB>rF z{nev(`qFyy7CuWa{WxcOuh9A3N4ZUY)`cWLI%@K9(u{Xv`n!*6XX-@nc_p@f=h4@3 zPd1x-+`IQ>Q}U7MFQ2zX|2e38udus3bCdn9qt#z*7IfQRy#4*PT&uwDHCN245>A__gE2O+7FEc;%un3V|q0RefcR{YfDTVB`73(x5 z=1OPfa6Q_v^5LvY4v)3ilHTo!tZe6pw+`+6!Q-ZG_`-B? z#j`7{#oE)SiG_#w%njYMWm8t2VY6fL;e*Q#P0gOg)M`5M)w5p-J63Km36a;~z1G4s zHCwvLWXq16V}B}DQ>Tg^eah{k12hzL9*I8GO3?wAS=v6I$?*!#N{O?T zJkDztzG;6Y{faC3?;EB~&IVBtbBZhytryBSEA!{ug&xklB)w>2n?vpbO%cv$W8W9I zd_GTRdz6x?*rF%0f_tvunuE7q{SuzleD)yM8lwwYizhx~V`F}_*_@?0@M@HWy!Yl6 zEt4w(<(#%YOz=I)!*ZU{+c)tfPtEvfx@bampcLzg^! zi(@ya>@;qS6nDJ2$kbcl%)GO`2Y)td?CW~i=J>sBNt@zF)|?WRiESA{`>(B-cWHQeI|S@b}GRE2ahh8Zojf-6OX>E8%(dP$F1LLF=qn&dfV;iX}}O zZ=B(ZSZv3pdhYN7y~;;@%V$Of3m@G$Sti@P`84fD_8Y}qZ3RjIL)Jva3^=Gqrsabhc~ zTB7C=!r9uKdiLw-ri-TzY}%#pGWF4$*2avES7D2Dq680Fe&T2LU~#+D#dFHNOmF?k zPcsiKQ|XdFcwbk_X02t%?$w5+&dZvcR39!|khv{lLQcq^-kq0cPRyuXu(HCpbi=_% z(R(#_EPL6~WxVDR)23W0u7U+}fv*;X7fL+rWLpz>@0CYI<%(@8du*DRF89?gH*J5F zB_c6t!_-?*YT9CRpB-^y`zOMcxhtx`j`5lYgNDHJg?dp_7l^*S>8~?4Iwt+KPO$P> zqp2&d-?JCG*6U_|%VaC#?dpD;m3tNXv>cx%@#(KU@^7zbEfitZ;cG6K>sH*|K0Zsbt-=O^+u5UinmLzOgJj4cYCny}ipOy1bfySMxw@fjr;c)IzPZLeC@p6>{D?^3P~c^!-=8p5bUC z%ZXVr)1{iarW?f#89C1L=wAc5WK=~Q(LuE}y z+ujRXi!c3u%=uNIu*uI;Y)NHWkJOp(&5Z5H_sc&LP;)e7Nn(EYQ7<9cBsSCk-`6Z_ zVb^qS<8w7~a67tk;>jCx{I*SZIru8wIKGO<-qftgD68q}3*BofENU}5d#9C^UXRr9 zUwiL%<@*(v3im!UeX*~kP5f5id5gz44t(qRJpb-B-p~No(kpFt#sR^T*Az*fd7rX# zN7_4&w5jvs_gKx?AiUSJSNV~9^H)LRGOw6Ym+N7%J(Fh!FZguYEuQ&r(~~$6_C>oV zUgDoU=acL7+EqR=8*SeRyDtm)8EgE|Xida2>7qr#|MEN}Q*UT1pL+aOsjNdhAX?4H zR&SHir3)F)r(QWHo|LmxVA3*~r!TcHC@v3J!N%Oa^0V+G$=lJhqkNOB@6WNi7;7w0 zmu-1!+sA~4J?9u2?R1X%sD!<}^ZVDRrKylI)3%E0dXyzgcI>>l@+993q^x#;vb=o$rm_yHOU(VO_fq+U#h1q;lH4 zo9#7|#g83jEHi2>GSt{?c6HyGz2-;8n-3zVw?B@4bz}1`J&6vjf3qcfuW0jqiQKhl zZ;i3UUBU8Y0c@%&hjz9vwlS#UR1~`VrK4?@K)+?7>Lji?`#7>ZU*&K&Kejf`{I)8# z=v9HTrEE&+nw0xH)~WvXI&@m;Y(~dgm-%uXoO$u0&7~VATWW6cyZ$ABEBf+%m(2F= zuN$W1?ODoyXxXD{Tyw%x`EqKFKiii|uSq>C8G5B>ZeiinppsX|bz*En<@RsV*0!Et zl7G`nq~%<%q^8uCcoCM}&C4`hIoMR(J~h4yoq9$6o#$?8rC!BPCklTQDd{Wy6gXYd zul|}(`>oCTotlk}60gh!dG-8#_Nt`3=h&$o^2v0ut<{A^f0swvPd3Sz@?355n&{v) zPBtzlpYJeRBqn2Jw{qp_w4M1q;&0Q~{dY)-TC1wew0dIUUt6@*m@L-s1>*YSzfKM0owdQu8 ze~@L|vLVs6*3#Nzx!}839u_vCFL!PcU3g3MMZ?+fmsa_)PfB(hz1?t5C+J3?(Byk3 zl!6N%yh^aNR4EkUvvQG}^<&a?b3vsSe~$H}Oi&6lyO@4S^XZjMjz>2f-kl;eLF1mJ z!##q^i`+dQXX`jzXKJq>qmm%L%8{86FxVAKCImr7@3cQQ66C9JIKV!N`+?{2Qq zD)k-9cCDMqcTnK2?^WKuh>Q?-HSXP_VOG0>OhS8&u8Wv_Ppjr%y=%+n|Dkb<+NU!2 z&Ubqy!o2X4)8EHFQRNkS6Cb}xJsT#`&$5T{>3M$JM;*!%XJl^*Rt3!!mNjxee_ci} zK7mJf!eoK_+jg%Jcx^rH*SzA01ApdQgw>pt_$Aq$RZvtqx0L7k+71)<)t={-tG{|O zp3aCm{=mDU^Wdw9y$AJ@r%S)_+jcTx`i5ejGEM8t3E>;GdCNq1-%7Z?;WAH|?%p4~ zyU!(D-+bBNNT+gU*@8k>*9|8V%r{6&e(_qGJ~8z1+2F;2!3SSnO7)1{#k;LCfc~czG;z9Lq(w3?i!}Wr%jxtHqF-CExoDTCw;=*gOYN$ zwy1E4N^V+y#voa-{8QSm$IW9o zYl6`Sf%FBtbWENIzLAOTGkg+Zd2WLHsl@`*uTFfnOUi!Xeno*?o@G(X0u@h9c>I(l zrJwa}zSD_i8OHB&7unpJ;QGeW*)K_7;*W;iy$O>i#y=IYxJH+$q&B@NQ&}J?foLIc)QA0Zt{_TU2O?l_ouLZwGWeP|0W!Nk>P(&LUO6el?1+n z+k-pr+)d6GpE7;LwahEGl&^WYKUr02WxBlDw#)SIvya-kbJ}drZd07(47$F(_xG)C-6Ime(OfHFch+vl z6NaZxp4fBV&gqinyYLxS=~-LCR+>K7>YE&1Uz@P@lFaF*e+9;K9eZs51baD!uhk2e zFj5I$)O=TN|FU_0HjkX0MP?V9xp^PVXstZqxOuHptBbM3CckUae_ZBeZkT@Kw2Dl} zjgFiPPcz$kPPsXoee_{F{&)LwzqXudt2_Vun^%}hW$tuaCSA1F=J11?Z%ktUotm)! znAp0Hsk>}0Pe?zxnYWVftL1c)XO$678v-}zO%Rv*q*Q76Hzw(X_tVt2Juz{OJg@jo ze=(b7Hvik@u_Q5aLDkia|2-1QFF$!X#~n4Bc-J-QhxFpBb=u6+<&(|T{UttSy^2|2 zHF>=R*KDsfmmS}*e_O1$Uh%ZaJhq?0KNd<#%kWGr;$qt=rYq|dkUWdkn`g~r)6|l6 zstS<{5B5I}4tzY#_0L9TjsKrKuGllVX0ufBO**F*ZkJFNS%6rpFh#g_nh2xTW4+Q zh?85xmvo?&FT9SuXt|&BBQ=k?4KBR<+Sa>JRGOndZ%_ zi93+Mv#51NZgd2<^uJ{t@oW2e`Rs#kUW*m~+ z_@r04UGe?I?^2)aHckH?T)Mf2fpyXAy&3zv3bTR zt8<*^Z@g@*=$tp*y5#2y#qv|fd4BGwIW)olRP3%hxhL+Qw)Mz~zAqd#XVYr~nLj@J z#OgaN`?Qwt@$@RuYJ1PI(EsG_i8~*6yCz@0P~`bq(OY%-Z{JeqRcb%%5-@BG*3CU~rmZIOnRE@Cd-+$0V(Tfc^E`Lv-pPn!MiGPb|q?nCt z`^#@EcltLzwEoi7YxHFIr~Vyp7H(>4tKmQFbLSM}@?SPCTo)fG_T8KDaQ!;&mRA=Y zw43<1_|D4xc;d^g-A;=m#3IF3M!t4$Zfa&a9q?&msmmM{?nAw2c~veRoK?wt%{98c z+A>k^*W9bwg5|#2N@}f68#4qdZ}lHsZZB}mRhRvqd?2S(%D0meoe%k(T%H}4%R6Cz z(ov$zG}K(eru)0wgxxd#70)`>_n!5|r&{Ma1^X0(1jmX{i=wI@`*If6j^h6M}z* z|1@9D<@NU_f9gYNsaFA9p;76+j9+zE%mH$GoXjK{8yJa0aMZR?`^%mAo**(F<(Q2cv zN9E?_k6*vJt9w9X&X#KroMX0x74W^-({A~;set3I+w0fsU3R=pzJ0GmXPuC?=k@jM z%lFjHElIC)cy1ezRq*SGcdqbU&6Ka5POEwW?b@1^d|WGp=L)w-WoCWWZkaPt_M6HRuACt8 z+19VFywoiGb4>MQtyP;_RxL2R!8lDkdeO5#In8}1Z>>CH(mMU+=Tm9Z z9!!hf=+qQ*J6%-vv}xhKneIzXvZ@cR<2G5iIxzmlo8*MRBuW&vS5vyj|%*a}OC}?S8fy2hS^E(c0w0~=}_4Iw8 z(hb|1^Pa7GyYHV*dBLPo;q*Tz`1sAN51Q37UH`XFE=c}sh-8++uKz3L%Ju;;H_)IdgAg0_i0n6oKf`I?YwP4`jPkD$7?4wott5C)Lqrt`nCLV zvz?}?AAcw4U7n&Q8E|~=R6eEz_52BcH)${xBf$+`|?!_ ztM5#kQT=h%;Z4U}7cLW3)3=I^p8Tws@AD+z<*NetTeF+8Pv|ar&~7K4n-g~}qjJs* z&1D;YK6$n56RXQ){Hy13sT+7XQjFIc4c;jkt)IKDTqC+B_VSZqCS;KeHve+{5D1zc);bK6idM z6sSCmSQN{?eQKZTZNU|e6)|e8j~9ksa^I|ZtHZl`hF4^3{jxbJD!+N3Fn!y!=h_mB zVwY1E##f)qnK(Mlo+;BgpQA*`R;{(W^IvsWL1D#jPvL3vBo`d+-I_7y@WIQI%S=jB zx*D#1{8$m5*YVY{NuYPKiTj0xbLPrFJ#yl~4*yQu<8rV1(pIgn{t}Q}Sj${%ywIF& zcG~Lm4SlcvWH03_f0)^$9$Vvi;7E}kOV#>g39IG`F|@R}T>p9@ey_&WPLB8h%VH&= zecFE#FB@~eoY__D=jD3k$o_MeO=U`F-0WCi`exyEFVoG*`vPMl%NZ}pZp;aBm%4T= zws-4FF@MIAt~f)s_fJB#c05*F;_h4=v@N6Lx51*xC&g!lS^j*yN=5bZ%kT*2T^D$F zu5R2C{kZE$^eNdB2W6f<`f5Bio84)y*yW?g*{{!9^ybf@cE_v#FCF#$RpDV`qFz5S zy=Ue{aO6$bXC5usXqJt;%4Wq;kxSk`mx#b{7puxobz{S z_{dF*uds-}Xj2v;Sa$ONv36g_ZT}f6MBmTcxx8$;QcxQ+_f#+csgJ|o?^1vEUXtgH zflBAyH*ZsyEjs*6=i4jGSKf1@tXh0nW0rYwu@}tvyn5ZMbH4H6mj&B*{q&o&tVXAF z_da2#B@*|J=AXa2@Yu^z!KeCswk*YwTzlOMcx!8}iR>0XxWHuU&z$#3ON)*K)rs6b zo-{?IOD8#{Yw>Kk!ZR9{rjutb+fwE8=~`5LYuT(z`Q?^(m-dMtmc6^%f6GjR4&6l4 z1CbManeD$U?S8=UU@^1F*PMjqjLCsI#brv@q-DRVtua6TxhEc+Y7uuE~(De(>5S3fJ2ZLErG`un0% zvv2wH)Hg+6_cX<>oEN@v_0`W(G5zzdNByloye|0s>(FYpyLrdI<^|=NC)dhGufJu! zp||XJ{>HlQ#s93=+@BS)|E%Hpw-Ni57uvC%F5l$)W4Gk@E9@}`KAg4PnX6EI)a*jh zgZrXThxz^qLZ2NLAT#tM?J-hc7o8`x(|7)}4b$?j1 z8x^qkH@Dn<(75*k^Ss8m4>~^{SV}PH9}u{~ul&$e!{MC-cm5%f3h`GDk|Vh1A8`G^ z`su*-0`402^3CcuVlCz;CN{BCciPo?%OVK8btrZt~By4Z*#~c5M@v`~-BvaU%fIZNBe+3jGj@9{A4MQ3*NvHgmv zp18+^tywr}q5FsZHyDpHi3uiW@*g}?x@LA%nONfi2}T*_Dzih~9h#0aZYS`q`^vH7 z`yr?K^9pVDMYf#Z`D}9B7AMWJrN@kNOroDf-hFmkS3N@aX_ zZ1?v#;yOLgHE)k(obx{2O+WsIS_u98t9jw(P7(>J0q zUqUTr?&UjuLptF6y*7>C%5zTMYwo_uxMOB5!|WUG1@^xs$~Npjko~5(V)9?!duj6z zEPoUHqp$X)#qTc3H}Y%jf2*HPzQ4KfjeD8S@6NM{_M2PZC|GwIhn)|+UU+idL#f>} zci&hWlm5Nfyn0gg4edLp?H=8|k-o?Jci;C1dG{tS|IBl5cKRnrn{NNdwLduT9QS`( z`%`P);wSHzUa-whFxfrdmLab~nr##NO);IjJl;3MuJl^H=D&N>Ii$(>A>%g#=bVk+ z51qI5ZcUOtwN!O;h|=5BA)R0J!WxH-`2Bi`;=pP z{u%5%GLbpJ*zROmmJul z3H|R@QF>Z|E#^=lJt*#JGzGRRoKd7e{bEX?w>Kie8Gh5$-i?ObaGx^ zUGH_xM{YN>U-E^b58OE~cQgMK*>FKW>_nevQHZ(DmwwTz6;4?qrb=CpzAfa~mHe^d z$cdN}Pd+Pl&u6fUtW?Jhlv9dFL)UNyO(y0}n(%K_0uE~^$jo-x9?_6@(`n+GpDktVU zb8HUY?Blfg#`61Sw`N$mI{!Y6qp#-Ji5v7vZR(KTV-c^Wed)8$wv>5$B*G_2-sD|< zeeqX|9~;l_s1~rY3=m&e)M@kZm~~=p>IXuY5n^- zu7^?%JABdBYdE-~{l!kkc>(^xx27$g&iKb%;m6m657G*=@AEKQM!D`2bo&^+V8VSa z^$%w^bZmF%xX&v7x%#13o&23M@(sK-+IP;&x3&LN{=jlPvQqoa!`u&S_xbjJnCtWD zcm)4HmD3M)i*QOS@VXu3eIt71t=tXf;z0X-ZA){0%-h>nb#HA)hNsrFdoC|iSA7wS zVp!)@@9BmyfuQqufcg5xR6}h6b^S0T2+{9m~y3C73I(%ul$doO|+^7Ak zWiOxJ_MWdoEkmc?cxT-7(A1cFY~ePYIjb|;eZ#{xn(g4aDN&iaE~_NJeYN_6+m*hd z$F`nWELZb?wo-ZAu~L`cuf-SsFLj=%e*O7E!Jn*=mzHlo*t_i7ti0?uO8g)F?JQ;D z!ZvUk)!h4XC~QaO#PiV(-|k8E|K*)8{`2H4H^zVrsg{XfP8`2yE?!w1H@`2&+y425 z^G7+7^L1}Hta{7F6WVEw{-Rm{IWnkP!six>T@e$g)5u=q!N zz#02CqkrKmp3HaP{Vx;tQ9r@-ztFjd@dsP~$e+lMKm7Gie1ZOdxow~2CmgS9`u;=T z%zrL(<(uR!3*w%v+^03`qtLQkDcKE~B?p#WWbAeeQTjJAqHg+M$-SJsrcX9^O)k-J z3;h)SMdwZc=XA}wFE?ybw<)A6EU#&bYxjIEb@^~xZ)DNjP0}lVTwh#!z`*%soz7(E zoXGQ+S1$Q-rA4yRrNDikE&V&t*4wE?V$3*X`=grB5Hs)n(T|b2}+GQ))?aV6)7_#)pTvlUo^u zUCS-}zBEKGQlFz`v>+atBkdS+{SRE4m5s&yHreA(%dR6dD+6aOmF9h+qz_?0#M zmf+J;V6x3?3v4>&e`ML|3M0cCzKj>wt<7TAmXVHV;ya@z@jN1RyY0ip8##^Z-n(46 zscT@9`u|9ro%zB%_BRtJFilw=w8i!=lj@WEZ@Pa5oxib9WLolT+w4TegDXAfys+fa z_*w8zIJ2&2aJK-{9RK&bVRULyUPCYba_yGk>S5c?}uIs?mCflW3_XMd4+PP z#hz~te8gnt8*}Dar}qt~Ld$5Cb*YSnw%lFPH(ow+E87-ve4W7So28Gozo{yej@Hjh z&rLGEt@|#q`sm&_xrOrYHRT>LA30nzBjf4eqscXkD(1*5&wG%#u{&OS-XrOwadq2o z9N*sY{Kw-*mH(zxG`|=A{d4mp*MI9OI{z!giRyiv^+N657T$*pSHA3DV0ZDyW`kx~ zm%XnP-wForiP*%WI8Enhw`%ams@5YDe&nxMS@&eGfx$mEQT@kvcO3W`bLMQUghnvO z?%7j|dUpq$HC|V|J@s4IV+(P;k4l-Vo(Bd`l?$4vk^99dU1o26cAVWx%S)#sDmL)O z=`8*k-<5f2-I@DqfXUA?qqOUtEYJJ__Y*oeFft1x}XHqBZ8$W_J<9sCP+|KRxZ zDA^+Fk7!!ge#ezRcupO;zc8q#lkIc%lMVR>0e{5K3Ew}+_EGtcYMs-&U##0a*m5Tw zz8rL@Zl&fb+2o|NX1)4RBA*UizSDf=L4j6_F4tO@=OH$ z-uRY1%iz*m?N#s3&(j?Dc!OL~(dSzaN>@MSvvOsR&&iui7pV7 z{dDmRqey~}S=h`yi?3XEIh^q6;!?(4Z}|46Sp7)xm(Vg!m~y6#>18wLruoW`Y;N7V zc5#pOukR9%Kg!wMW%^$9##yp6kn7GSi5>YxGaj8$e6nV7hziquXH90=mlJxMH!YlB zH7nt(s?MoIj%x)cCMYK~$gno2>h(-uEwf?}-*iwiwQ+LeLqGo#GlL(?_fJkZHu=R3 z&!=;E(w;cvH`!S~)GgA>+wk|LS;g!-UDA){IhIE`%5mmZihP+aEF<_jp*Ym|!-KsA zOLgwub~>mlcJx!>Ci^MJg0z_5_IOF|%71T=6ld}_it$%Id&HeeX@|V2Hex20qPtFK zUT{Cxkhn>r+?Km2wexM|mqxj){VmNk((FIKJhXONaggI)`z4iavs1SPc(q)f-)N91 z%CFpK*pPU>TeEWa!@FM9(!_rUAOIB~ac$4*-+jWu5Q)RtHH}uk%eOKP(6m{o^$Eun;T=j8RiV9{+?)-oB z%j%6yW^dQK>hY}72;P0+`7OTs+l=!I6qIw8*7Pr)H1m`0ryn-AA6}0AAi4A25+*zM zK52>j2gOC+Z#i`TIg}TE;{Eg zk}Wbp=AL}v2cu8N55F-C+24Oi$F9MaDbMV9)$2sb8)g%J2eQkZJyavW)!UG%bAtVG zG^g~8gY6#{THH@FnREC@fyj*A55?`8`dv2flv(yE&_?`uc8hYQ+%%gvRxgfzu4HsG z{(i{8Zr0vqM$+eROHO!RxiBbrj_v7w1=FQ2Q(SJfRPgl8NuFw>=2NqV_p-&Q#7pv= z2CNc~3&dOXbK<-{rd|@dFK59h~ij!wDqrY5><>7=_c?Qi%xPUop9zn`db zNa!Au*7oVKFDFlXBXoSR%6n&yS}9Kb%d*c+St|YyqW=xeor1w+s&9r*Q`;YQJO#35p zZ*u&B<)6HN`2AyUeJP!G;(f%nKaEdM$VbZU;#>Um{F;D&vwf%T-(Xbo&BI`wlXqE@ zs)Ug5|Lt98FRC2AFFKpMXATxkrD+P0QU_C#Ah5V*aJ-&pFrTr$=QR{qV#`!(+nEN8-?k<>pO|~k-R`z36U#@oX zg~xLjtf}Oi-w|jP<@VxqzuDu`UzgouTOXbM7VyPUik}lLU996Nq z`RVBU1BEY^9o#*I`=wvyF`s9loyTf+&vPryOLMFf&o)_MC~uq1lk+?JllP@8wr--6H^ebvT1kAru-JhVT1^2=CJ zIm4@Br_J_dr%J0IlKm4gb$i;E<3&16Uk{tRyb@zSDAE`qdHVj6O^i1`PB^y2ZJ%ea z>>71<)yaWj8~j_%ZgT2&PjXY^S90nP77S@rZjyR(<=)J+8}ia!i6M?bc0Sge6Zf!8 z+#_PNg&`&Tbi$-CH-1VCG5VY+xgwRL z_sGr5IWDp*nM4}Cp6qy3scB*9pSV8W#(8qXP9t?`<@H~KG#sr{HZALpxSYB%EpOh@ zS(0km?-C-LEP_Kj4Y|*V&A-#M;e2bbLPG#s!p^EsKQ=BaV|(-}ykqs|1?$VqcrKr7 z7QDqeVSOxz@fPpIb!C!smc;TYzV$kCGjv1PZYjNs>sn`Tc`bUcFJxQV-rntB&F)=` zu8?Nz?K;RZhvoREmmQ8pOlcpIyq&j3No5(e>X#h}ykYk!VQ=!vC*QfsHs^#^txXU= zeeY3+LtAj2<8IOKCDtX^-!<5+_~Mo|Tfu)f_pz+<#S8AX$NgmP^GMks+v&5d+;HZ3 zmu%<4<1BXCnnDZ3N-ezW-yAMV$#Z+_=I*Nf`P#TZZy~nAKQgaXV=B8TCT(e(k<#VRqtulY^sL!8Z8o5LKI_oXRXLe)H-%GcbzfEwK_#(o7-YNFwWv*{I8{NJd zH5Zzd=$}azVPE*`P3o%id0!lYc(gB-ZF(5`WW~-;5&QhJla;49z3rYSAbm1HT{`q> z@z#wo-n(}dR2jEj<4)o#lka({bL><~B`2rdHq~RVell%Sc&pcV{AR+E)51FK^VZl) zub9_-v*2o8(UC|40m~$HkGFhu#d~Jn75G;D{R?AZ`E0Z zSF>9F34QY6dg9`5Y&qBNwaMO+f57?Hwj!)rKJKDj!}YEG518L3|M2-OQg_iVy>^R! zMEzTDGq2xmvJ3xq`(ECc>b>RtP0d^WU6-dVR-Vt#{X@npe_`LO5RLOe%sHtO`R_AEHMCNu(fpE+b?TV#VF)^9dD%!ewOD{3)yKr!6+JDy@ z@t5K^ZQjHo9_dxPVruWg?)Z?LWY*%xmf|T57kRd=IO8TJJM-cHx>uQxjGLbocwUH= zO4${2;r`Pym58>e3#m^2aYx0i*O|`HRX@sSQ>p)FzlxgUi}sn*9nXdKgda0dxt}d7 z+f%&ZIEQ+*$gQFR7aMo)e>NXaNG!DZQ5$f>vcK2YN9ptq&67);`NGY1#MB;m{EGW- z%-@6s+U(1AvpKBH7MQY|&AB(5W6o2lcLA->Z+ShrBT>0w$%*EcKceczzuR5|>!TF%m1^+Dz=Vv(EUu>&e z#9AvQ@*&DZ<&qft=BL$L=Zk);tK0TXxL5w{vG2uRtNxx*=~q&opS3^ObLZly0|~2k zNd|hmzh({D9lQ69aCK$1l3HG7d#BcsBc2_dsvVud6V5YlIJK4MRjlcS2T|`19Ep(@ z4n#s*-x>sFCpKNY-@j>6wfLhscLTQmZMl|KqxsKg!=hh7?JEAIUY}fE-}6?pp5=9l zXJyvJ$hj$@>bH;g-m38JDW6zq)7{i{R%G}4))oHS`?6wn1w#Dxt+V0pmsr2mp>>I3 z$+zceu5w{dQtiI0NxUuAuFtQLI`6exbdO#6#O18Ne%w*gUMu=;=>dCfU)lR&m1ob` zwf@U3D4)25_f~nW#O;I2JTy*Udb0BISDn3H*B%@$RkztZSvI&ew*Ty<>&^4-Gfi5@ zy76(>ooQ0KxClzRFOcu3n``Hs_vF&L>^67&c=e~Y4lXF+Z zo%S0u&aX?melV`vG{1e~iCMlYe8QBg*E!zaEaq1i=eoZ+ov&5J%J!aFSG4!ky28C@*A?$Qmsha&U{p;0rrL=5 zb6@#xzpv{5d$P3Q?}MuQe$R3n55D?i!)vx+!X*7SZP5u<@vW--ci4`9w9=_uC^xHO zuhsEgjK@|98#SM8zZ{w}_gL2hDLJ>okDD9|%=K)#&^P~B-jT?n3VRl_)>*}> zEZn~!Q*-%xou^waJh}Fg$LsU=Lvw0M-_N-77lT2?UPSKR_-a0uZm~?q``gP z>ECbZpU-S`*|#6pf3-s5+}H9CyY{ubTem)dvzAvm=D&;SAN?6meu;I(-anXgoxfnu zYj=}F_6M1+pWo&r#UA;G=gV``7yOHVuJ^dOK-}21R=~mTpHsA_?vwpt*CY3?IP_vx z)}3l2_jjR%r)K^a-<^JIVcB}+m|YF;ten>GPH0(o*y1kp;<@7a#OzPm8y zJtOy*FaHC<^F;rFVDS9meeR#+`6M^y9>K_T*gJ?O!wj-ol2K< z>q95?Hr>50G{>jJ?&ih5;{D$yA6@W_>)7ELWl__Y@0}5!)Vli8o+Hfh-{biozsM^H zT47;e7~-=$;A4eX$?lq4)9(0~ZJ#>zT~cb=bM^qPcPH=j&R@%{JpaAel-+KyYLGpp!hol;}Y|i{^YJY9f*Xv?ySC+6^vsXT{sOX44 zxxT0(T1};UO406F@yUj_!o2^9v0hD_#bxZF7zpJ&$;^b6)<2DzWG;hx2Do=QB^MQViyN@yuz}mWzkxovU9h zarkWhMtcp5sIP1<=AWFlWz*#Cn}g-t!h3XGZHu#{xwmXe<=^~jty##cYlbcb=BpBSnJ6|FE3b`jN>Y{Lz^8e5;}4dF>yS9D;w8dc;3?&)a+Au=k#C+N}He5~bpv zJv8U4lRo6L=TJ+?=-Wqzyrq*4-{=%r>EPw zIale4*14K!I0d>mIGD13HQhBW#yVpO8_P3Y|CecBnsk?mnYJ07Trtlp<&xW}9=)w< zwN+)41+OP>xuJVu%~9Xv$#ULLeRM^yPhav`GuYt>%Q3ayIV+cc$?%t?18an` zXTSb*%J)cMFMrm`Df40$9c3>~+Wdzpce2>o*=|O=oK9b8OPFss;nJC!X5uJSFQxNISvInM_41rq zRkm2{I_Kkvy+ytX8!mcedOo%_`MS+;+J#HHg|^93FGKtU9VZ=&;#{K{thM;{&Bh$7 z`JL;Q-Mn3KEtXA9u=ne&d^QCYtXSfFS|fq!m)I#~qk7j>bMw#1%v_STq)MgWznfR6NN!w{hQV#u z1CyNOw5A)c{In)+j^@1Ut?si!xef+CTX*#9j%<_X6+DMb_VP^b*_UIN{EGAUo6C0g zb44<&-o1B*&>wesHNPBVBIMUY7Zh5dkr1SS} zhD+8P7qPLH_-joyQ@t<4UVE}nRjTs4y3n*m*_)%ZrhBHpoUndfB7b%CTaLJ0ouAS+ z8a-&q@v^%7cTV2}-wB(41yoJ86T0*9YoqdKpJmB6C;M1kzaclJ+dI^~hi_WgiWsq- zdLgG7M1?E`O`vXP;0kz4m_sij{#rlz{3u{Hj@I;GfC*^uwTH)T)j zeLmMbxP3HLh0S@M%QLnuUVVh4Tv&E;Tys!<<;sF@7emXW-B!yr{hC%`G=K57J}XNh zyVZMstcfc1*Sw#4_x8n2No9dHnWp{=?J64s6(%%H%UXM;hHYIE@41Ci8>fU_e|@Vp zJ!7Zit8XD|j%bOdD=h1pz_HpwI6bi4AZzkUj!@Cwq#mtfU4>l|>y>y{ZA=gU7PVAs z_j#Wit=qI_xfm}L5)RQh&K2rS)bLxJKXEj^}<^Otm;d?c~Ud6h`(9+`!oRHDu0$M_M_d8+ql!KXTRt9ThKV?wbA4 zRdo9UZ>_we;URb0)~~wJxPJ8ywtXuf`N@?%)DzuZDed$>H5Z{oUG21ZS=b ze0f#keEP`)X&=A0a2+}ny-3D+4Y&Q8X$Frrt-ry&?fU=1rc)k|_LOwXoj=`gVyx9Q zqrxinV7J(If#2J=gif^KQjPCuypwRxXNmdb%~IO??gm_Ta7bZ%eW_=cN#E4AP4S!g ze{tpZZtso$Yus<(du`A8C%ord z?UFB{iHo9_6nvg}(waLxd+WIqK^_iPC$GmBY)%tdeDc1S_2kEzIa4mp?lIh@bUY{R z?ddb`rAoerv#Ls;zuWLKqAOLPLb@j7(Q7`34t?vNOQJjG`PPVEns?RY`-8VLTtAz> zSX`*P_onL_QSij^?Q@e|GYh%@gn}?gSi1U&)+U;R5M?kD$n${ zT-l;0;JCq|@6NJrkL7x9wr>2)m*bxBbPw~~-|rOyj|-Zxi6|==YW~TQiWXc_$j!Nz zBe~E}?Sbu<&q7UKZOiuuS4HOXKT=0&Oe4Gq?R$^`$p(r6uuAJm)yOMvUQ{OT)4L z3$ILBJ}hQ=6yeaWso%i6o%)LA3bL)g= z&Fju5l7#~~^a{CRY>yxEf8Th$bM^ZAr_Fy}-00?%yVKtpyRYND!ZVke!!t_k)yjV= z|7)Hh^6@>ZXyfC(?fQH98awuXK5)*j>s&y%^YccJ!~beKzLaxpWIw(xWy##0DU!BK z`)^2ojJ)-pHMFsWY59ft({VmuC+^9Nt?OL0`XHlorw02)sX!fxMvn&yYVJ&_22B$k zmOMOgt|NZljF&!giiXDD64UCB>}TKnEoqzh>&)|IExVh(^ssz)|6_f!h)XQdF!Djj z9KHG7FCTm^)|NY@eQCY^>F3%Np>}&OJ(AY&X?))K>$ypF)nFGcosv{rOl?Da{1 z&YyBW{H4xbH}?nnBLCV8mwrfC{oyg&!Utl42lxb!)CnFsoWvt1p8Ro=MEmt46)%tW zKACE1(H3;}=#zz>7W0J8s+K$`Q&76kTEOhevOoAn^|tNt+xPz6_4Mu5kfwdp?^SZ1 zPSp06s-+gaCbN7c>^*kQ{CwLedUooz%;}NK zLN!uuNXE@^*cI<7F0OuY^@l|7>vfl=RGNtO<)mNcJRA{lD&o)jJp#4?M;~o!xs}14 zbL8rjldW@Nop;_*PQQNXjP}u-tw)Y{_U!jL<1)W{hOvi_PnYG+4LkJ=ZGO*KDqd?Rg(JwAM?gTS~5T_E@8D9CRa1 z;@EPXFNrm?{yd(z`TU6nagh)67prr>RJDqeR!?Ese$UJNZP|}Gj#^Bt(vB^-0Dryrq44ZLUW3g^Cp=s?Ayq-+T5~m*5VC|_FZ0OC?kGe z(=TB9ju@NPqSvRt^hI6QnsDz;N{Oqe$8F6i5=^EC#8&SUl#73H<^3zId;4VLH}8q< zxw@fNWyQ{QWs&=ia+XC;J^e|Fb6Wa!uYXOuzpiS$^_1tz`Je@L>$JYi75ieH^WwJd zi}Gs%m)?pLDRb_8snPQ0P;98|h7*|!qWhf=ypv+`E9JUTD8kgXy84HS`v2I{>I(jM zWlybAC6-%1{xnZ3CjWR`_iNiJ`ZHhedlhs4)stTicVpHc*uJJ`TkpI%C!=rQ+_N^U z_vu|n)d2SCIkwk7ukY}WTf1-4k(Dt<9mh3XObvS`AO`{&a~szh4ZUDw(ulxyqu~Z!rA%gsPs0yxOs1vU%Ftu zu088FyAETZ_Qk^I+mA%btk*eR^p7c9N$yay-jThf0+VmCzbRYdy6(cP=~dgUm)ui* zR3{}riAVmQJgCdKELczJ0xtu@D^+}5MlA*ghP>1g{j7?TME%U%f*k!+Xirfe)@2MW z$;^SCfYuup9WER$@~@AR$Me`C4X-O%YrKR5mYGLuUz=7W%-P7*wRNe5O1nXck+8b3 zUR3p8#@c1EcHc!`My>p|@bva|SLLr>eec7>!gHm4&gSQH^555f+y4Eg`u{(_pT{%Y zJLVra=g@D#ng;E_nvT^{RmwZs`jt8!SFy-Ho~-ffLnimHt2P2h6M2pa91Gw%yklY8 zM6o+PNg|oN$){Z05|5esXjsqJ6y6?XuyV_ClRJHn_?BHg9?LtQyXDg3!%XUzx}QzT zoKkz*EXREQ_BnedKGWG7*Z3@ZTJq29oxaQ7akTutJ4YnLH@ff46z<|nvyGnTtlP5m z?wZW|hPK|d*ToM1YYG*5;bVQtTr9li@&+!~+Y|iOy@=||=egE$yCine=CGZQs?)CR ze>$!9=JaSG3GckuVz$@IH?Pa}@pxGnUbQcD66?z!dsnip@Kr7~Xk51Fga)^M))1y7@{ty9&qdO2mql3Pr`No$Tf)m0nB_;+QzrLYV z=jcZ4=EqFl6!o+s{Hqq6>aZJYSugbVzlRyx%JJ$Zo9_jI@@kn zw<+n4BF#0t+Mc2nXJhu~PV-V`W=el8lr#I^p4Xy1hUVehQh5(OnOEH^wczcZFX~IT zr=+H?&0BvZR!%$pLf9(DoBqGzEMHHzohiLS_hRaCv32{D3!a^wvB%KP*4ku}WD4W` z$F&(3Y@bZpQu%lFf{Mle773g>AGfx>G-v9Rh_@=sCsj*%e&l&r`AzxW(v-WYNii&6 zSFJ0Za^+1zcGgyp9~V)V^3^NUo%s-h08-zMy>R^+uqwv zFYNuo(;oNW!_@+tJE4xztnQBw1CF1q-o^En!c$J-#bi(oyQhQ?hZRoU8e> zX3O(&tDj|UFu!=Lkj?PSBGK=XvpPjKxjZkF?A~#1dEylP!#pw``*7H&edfQz-5nn5E4N%P>t6C*sLJC>a@z3& z(Tq3!XKXLG*#6+|TAx^svW8}Nf%OlL7|;15d)B}CN?v+S)8lGKG5!DSpptO|Q{$RL zEDQ`gIq{W@D!5BV&j6${ac%@>#gwOW|Nm8={4-5WUVuqhVv>hLV`4+gX%A*MXC4C~ zAs-7CSD8urCm*D!o%7it61XI5Wv*?M_PwuN-#&2UdZetr8nyNKw(RY@Z(qBW7k%a0 ztGuhP@~*1>-Fx5Mc&4Y?i_QM?YTkd{fA9a_bNzmHUricZjb6C%`(;#|<(2l^5!i9v zbkD;>^FO4E>m8h}_lGrq=SQ=Dr#t_LJ&wOy!Tx^L`D)f5()YsW^PBwXclsO8TVKAI zLw?nHch(;g|CigToAP8bnJ;_P65O)*#uat{+BYo|YL;8vS=2eX=cwzvM`d1&H#_|_ zQ|A2Y2~QWk61gx~O>2!(tNlsM$)XF~Cns&1s+l)aD{i?@u~+A;X{-Ea{+hGwWXbX= zy8~5?=NMhqT)z6Q@tqw3X*&beH;YcUWPLPwXWqF#v(6MRo_1>D&sPHfRGRd4NWRA|nrCHC<*d%0}&{j2@Q#JLxhTK)wO)+5~nkQeGH)rj%pRa-! zpS0w95VLi~)s&^dukP&dNXsai7yT-A>aKfP%hv>6=guhF7kq8iS~k^VR?AJSmU{YL zUwxj{FSE?6JJ@W+Rkx*^eZA6W&n;T$bZgPcF!M)UKU|ykv@N^Zl*wz|yt`?tZD+s^ zBbm1^I9#o?q%EX2K5hEg_;vQQYi4;XZQt*C_G_A$<3v_jKA}~rg31O9k6m?D{^(*b z>4pf;cL}kuP_=36PMDaOu8oh3-hM4Aj935e%mqiqnmZ=0;Q0`I`xY>n<>#*XJ*f&OkbTl&2wGR$Sx=akWQni#OC?br9S zcU3lAcfDO*IYED6x$Y?-ne{mrpNAugy4`n?`{irGD{i|@Ag_u_iW7^96{Bp0>sXJ9;C*J;;<*`di{d};3&R-X? z#qU;Jh|yix=V5SBc<~hO;~Oq(?&w>7^t#LAm9~xdr%PAlty3r~mEIVpJZZ&JW|5M# zNrjPO=FeU49*nrNVUN<@ofph!J-Cx|EmA^j*2|6B$&SU7dDKhXlRL$lk2LehZcPri zHrXR3A+{wy+eBy~pP5Ve(M2)qWgZtb8g64QcCXs{>0p4$W4XuGk3?(_YsMx%b$+eu zDYQ^e`PSi?*0OwszIw}+r+QwK@Kxt%pPJ7iT)g32_wgv!rOU&Dma}J>|yPw-Wbg@c&%5XAWH(2caVylervR{J4+^kOb1uW5h zs}oiIN-X$FogXLjKEoM*>{;e#6rJSTvr_qQ){SDWo`mf5C;|6s0}-<;xk4NFPP2c0 ze2ud16eg`R9u~X{cP!Q2+@KjAX7w=T8pi@r$%X5c+`sZ_Nm_<)X`5W?mmJo8Oyv8S zpb3$|Tw&MqZ_LYMyrX+jZrP$x#i?t*rns&Sm|>N7L_DIe-E~Fp(WdIDGP`mnd#{+d zQER%|?b4kg9!cV5*_)iFhh<(qa$#v~#_h|m7ui1C_Q}H}&@Wxr{P8}UDSGNp6DPYa zZ!x*K@^q@uwWZ!3Cab)+$E@@ASt0#?#>?30EtB$!^k%=lv{>WKq|>H1*PfQUx%#x- z&Dp!s%I+@N-s`hfyV~iYS@Y73CcpU(hFsLo?>}~`bf?q0kokXi#i+8E?2OV&=XN&K z3i%Vh;>UWAm$&xR1*_}{pPXG{sd4>PQOByu=ec?L1JofMj%+i1_8s=nydcc(os?H1d7t_%pgcS0e9U#+R<@_UWxd!*PSI99J_Dp^ zp&`FmQh4Dti;KMhi!OJ}bdkLLY)MyMW{Ku9t=$F*Y*QZl$v^#~tCEzWv8F&`QRZ>K zZCaXV+ZIi2T*l+@HA7IX?Wqp^kq4| zsq5byU$*h|g1#*#bIh-IhcN2;Km9J#ADT8JAjWsCPUI`;$tPmECZ>yh*|o9J&3ubx zyy2?dAD?7h4!xaIQmTID))9@fK?$37h)Epodb0V*^v(C8$x?tnJnP^eAmvin-QA`#;tlr`1@Ef7 z)vs@#@p1Xi$^N*cS4Gla&vQ!NS@tA{%7}B`lS&h_&m`2{l2~}#Pisnf{y`y#HQV#uGRvw>_n-oMGr56>)~l%Fyy=y{EC zscX69;+}baQs)AGZQs9#ue6!-utRBy^w*f6sj4@Y%3Ynaw5aUpjfwMqvwODgDO&G( z;{Qo|Yo6-vZPpoO^S>k;AB%cre%0J~kIYNYIi2=t34(f#{0$#xEStwQ$M>k*o7M#R z=VmNB_bDacJ@|F1zcs1- zKmV{`*1hM3eewI6cYJnzr}I!l=JVg<3jVVc;*BQe{^2{+x4b|&eHUxX>_TpL@w}tc zIUSj{86ec!pQzUf0XN0-eH^{?&+fSXk9w z_M5$M)`Sqpi(eS0$RD(u{@+Z!j-+Xk6^yam_H?O(L zKa)9_Bz!&n(Ya?fN2~QJC(n+*&|m2~Wl>Aem*mF(oUg9=iqG;mYZmx8{-DT{nPrwe zGym-4P_Ogom@n`w)#aicc zm+TiVnQ-0XJ@2Ku?koRWZhuI(X)^!Fyr*~ihwwjK?;q$_h`)bWThqaRq;J1Bqn!x9 z-zgcMlRuM;|0eO8e6s5`$yZcv~E-jhQNZ>d+slbg?UcGgq*4d|mKzA^$~YdAIyat@G9GzdrtP^j~^l zA&dBr-+?y`))$1?i_Oc`-phYE_*a|@@A=2|7n8iNmRypIOs_0yR=vsK*L_R)<%t=- z_a<~+Si-T(=a9;)lvO?lgJ!m+X&!acJRGKJzV-3)l*t8rrqwfUSTR*x;mJMKwSM-& zT~mKwo5y|sfcaYKlRx+HCv%zqm>T2Vzu;#4j^67lKZ=Kae|$!3_u4mhJ=T4zbY0VB z4{u7(k*m)7E4lUCjnnV^*R8&KD}Q;kZsvz-38T~3zaC1zxKdIrdC||$Ivb3BFXhVn z#}IbqjJEWFn}@gOKdDvlelTgN#uVeq&zl3(P8+ySOKx0qAhL+>+_d72QLip|{LYh~&5`Mdn{ zGi`6bY(4H{k=1T>=k&&QqsW5affHJ+IoRhJJdCLjstsHBsPpiZ*I(?e>}gP{`>Xo- zw9Ofb=K^BbQvZwpp3qBIxXiLVo7` zd(Q<|Y!ox2++qWKYT9p2jpq1i^Z9Z{*lPDpySmrBlRNl|ZSqxapSg=8*2i`&a&Lm?`3S zeE$c%vRg;y9yz<^=;(x^5=MksFoiJ4chYVV9EmXRSx=lg&%u&U$bRM&-By^ zG+EiaXVPzj(4TX!&s#2|fB*g2biauA^-iJRJ1bsF=&d++esxiWOw65r&3iTc&zUpi zT)gG@ESHqO=uJ@$c&oAUl1pwk7C?k)kBq?+b_PBIHDGs*Bs}5 zPr>Z=3t#bX$=*{h&p!WnkJj|#shd`PEI9sH>c};b6H7z$`gebEEMw5vnDTAM)C;V2 z`HiY2TkB4^cJ8}wUGlszX3NqSkCJbE;|cvLXLsm$$lTCi{!Q;3>dtC?=3;)a-6FQ` zc+59;ooT`=CSDKFUvE5rZ>Lx#_w*CDIf{EuTJLbWcQo{qxy+>Rg_~;{te-gF(UyN0 z_*0_UsAYL>ll-lmimPeI<#T^l+C!QE>;Om3@OR?R!ka?MU$ z`-i^9ZM9u5_Fw$NH|NRC{hRw{L-nYus?^j?nKU? zx2X8QoWDnk)MsW`O*=d1?-j1{b9HIgUW>7PTmK>Z)83{zaSzWN-1a%_Pg}vP$l2YU znT~sBwN*_GIQ;H;O8>+h?Odsq+J5UicPx>=&0g>_Fzn1$*Mp32B5rqImO8U9$IC4~ z%`7zcuYttHw=HihOjDM#O1^Ub-Cgii@d`KlbN7vtcTArvWuEi!oKnj5<&)ZdZ|h7x zoiq9Ln#CPo6hAfHy7^P-*%!rGhu+E^+q*}8Mq@@#X5`hH*o$`<^ISic9TCs-EWcqoHar#cbQMU`m8)hxm6~3^Xf~R-7jtam?Kr6 ze@*(J{F#~`$Lqn%sT}n!lQ#%5Fqo;}8v!!IJp$xaQIhDJT3no%o(iR0b5e6t^GcxW zsluX5VnQYV`8_LAn|%4$GT&Jy3+FD=^-=R=77Xxo$@KBQ6*FOpX71Voqs_*a56{eb zcxL9M1*|(oCU$o^lt_Gx-u#$#Pd{y{Dc)IA^m4KPqwVJ{i#=zU zl_kI6&w!ZG8VuSRD%^FM|*Ogi%McZP|tlDADCA>LM$avDBc(G|+ zF}m-Xbt^w_EePm%Wbv;5L5s}u5F3G`Y&E|B_USG4^O`VOORnd^LXBBZ{5bAUxWs?` zp`gvGM;kS66?jdOpT0TY?L&*qe%0;9pT6&CsR-(_5j}djLai(Rv31bxa#5DH0rzh2GNm-uZ)m{o4dW!u9tt#{q0`Pi*pP->w)XWmWWzI)1>R?bOHnLAH#;`!H^ zj`IrQZnWiT-3V=cJ0Y=q@3grW=W;dHDQ8=3*E(_B_Ucp0aGY0+)#8NTv;G-zRyKQP#NW1V z3%e73!S~kf2+3O;S4K`;^4a}Fg4B1R7)KRj_vn^+itCSOMc6vuj5+x61j}mEIW-g2 zXC!VB(Qr0tPhowvC2t1n?b3y7GEbPeMwuU%y(`$PK1u1hMA)=|g_(CJss=60T2o~I z=0#bQ#p&dyvwfq}zx?T$zSUt*vsz2;MEw~l{T9>216gN3lD+z9Pv3^>XEKI5n=;dn zvEJ~vobToC^if&X{kuT0l}b>FY39>sFSHhm&bg$!DMvd}H#Ki_Zf)M02RhuMAG;Rb ziZOX2%-B0EMs3BkbSd>Ui$c8jsBGbh4$HZb9C{&SZu^NV@5P&&vNH}$l`_-1oqs1k z>R7Xs(qGTZ`KMm&2;DF_X}#j=`q!(T?v0LGw2=LL)(e;EO*f*Ru3RWTKfK`Y|63kf z`<6d6=vz_YclfhJ*oKW>f-5T=4}UjYxsaJtR6nbN^Rt#;c7^16jU8o{X?D}LaHVNY z+dAjQlm|+aFXv9Ywf14?oWw)dS7f~W9?84@;hZ++ON(BgVq)L?(@8J=W}ipz)0VZ~ z|0XSHn$7lQ&6QpLDNmPmR8Ezez3t5mo2(?s^A~1((CIx{+*IbPxN@QN?$AB!9`e=9 z%-ok0=p}sr!Us{A%OBJx`78~;Z+N_GY4@(>8j`1f|FJ(%$t!+fNuAjI;E&F{_J{gI z_bg3hOqQx^nyY9S0 z59b`s(x!I%$%yAP6-->Z^j4}yV_OsGFyms}%iP%lo2YagSxk=Gh-5ADxt} zo-?UPZ7bWIo4PL+i@DCbJTL5N+*~gki#heE(bFiu?n)J_| zE3arW>4j3MTyN+6#ml>TW6pP{ zGjo?b>lUa16!BnCB>S$y1fPH52?_wtLjF-2R|Z_DDo^{t<=w$A5q1 zIe+cB!O7}p68V!w;#6*B+AWM%e6*V9y`)Xg<|kEit@9@p&0D?wPJ(~%W50cS^HVou zcU(IdDWCq^^DmPrOUEA3?S*10b;jQk8q8!LNB{Sp)7mM%@JigLNS|MJcit^~9-~?L z+`vU=pZAmA$Kpp>DpkUxlQ?Ia<$%)rL32J30;~i@qOaC3F;>{hAYK7-F_%^OW1oy+tckG zYyWJEJ@6}VyGxSJ#M4W1>SuHKo++zdsdY;-_rdlfzh%qo`osP-{;pU1+kd0cek1Gu zM^Td%j`Ml>8pv<*tn&W(;;7@Zz(?C23cM@Y`$W5S@$;>lF1;>e&0qiF*Ls)#(W2}7 zKTYnHczRs=&T*Ru>AUxJ-2BN{b|vAdvU*M>$03p)z@Yhw{Rq#+@)^U8|A$*jB& zbSnxpFEV&p*qn|s3r;LF_RckX5&uy9#~RfNn;%)7)BY)+o_E%3i$zc9vaH?ed*jRN zZ7*Nm{qgZ(cZS-EOAWOaYmZ2(26=sP6L5`Zx%(pg(Hf!WQiXEjCNVh&RAa)XY4b`P zNMH#sTq}2d>b`}E9)~xy3AP;*J=`bmvN7Wct8=;=m;Tl-hm3=qo=ubWu3Fjo>2xDQ zw8*=zR3Wojkw#%XQ*uw#XuaM!?Tqk}pXMiG51VrFl-^qu+VkD$#ncC3i8t4!oUl0e zsVUJecxKBP?&(Zdd800UT4#8p^VQw5#Qjs>gn1YBDcU@GvSP=w9@V2MD>o?IkxV}L z?R2Tn;d#a}-hcUf5<{h#B`Tu49`@Z}D^&FMzq;gcZAk73UC&9JM;Gi<@m)M6{)+_P zpJRn-7fa`@Uc=I#GIvsT*X(JJF6>f$BKg$Sw8!&uSy#x-mJecc=d=a(8Qyu4;m&@% zPUb8Z3?0O$SR_J{eO7U?l+ z)_BKNEMD~Ew9(@;VwusGJ6Ek*uXXt1{xDD7eQ&H*o!VkDx9R@*gL_WBt#YdOk7sq6 zn|NF8OxdSOC5PWHvv+;J`EljX<)57|Pkwnan&(a8Q;%O)CzhyAdOBCLa@yba-S*G; z@;>{m;mESfHBS3o#wgP9=XP0_ugRK4QPcFD!jq0GcrKDr5Pj3Y>S=C>cC&|-n*RN$1z{7z80`}ew?#M zKL2{fHTzxPYTtiuaMJ1%quoOe&v)ysH9i-v2$VVAsqjeaVMyPWe{64LUwK@eGJRIi zmzEct>lgpCl{!?>nLP7)MvUuo>krp&Z0_5;IzwyyV&A*3GwPl$x9U_;Vw}k5#aN?u z+k8`=!*Ow*N7~0e-c`TuWifYxdf}<>zU(H>9zTw%ywnv~_P&I_@1mB|irNqL_Tbwr zMOcrz#xgT7{9(tJb@gz!%Q3PptUdlRSU6qcf9^WoL|ZN`7skg|+ZtH<<2=?Db!-&W zSs)g*`gGdStEtoT%qGtJwlDkjMdrUR+HYmf4b%!qU3IQxnf$M{$M0YMR(U_x>A-|# z#zu#K+x>p`x%%Dr?LXhXzg^CdbMUFrl|}u!e{(D&`kXCfoLJ6xN^mGPIF|jfiH=J+ zE%<+C{ha**wtF=mWe6O1is0JG;~a2mLX*^?LY~c=g?%oaDim7o@ zVW(MpH@c=cop@w&SyuStCWib?%e@c0dg5uRecX84vg4)26%od5k3DaNX16o^-;kQ- z#(G7S_iEpKnaxjstXLKG$E2=diJscTqyW>P#mmxeFqxfsc~0(_b?id_t(#^o5>lA5 zZOYx1QubrCSaNQ7DtG}|Banr{A{}q0AUVFdT@xrCfDeJ7vUStF~%v?14 z|?d-GJNh{XHW5#TezfHZ-ujBWZ;Q&$DTb) zW3;_^>33+{kojv9wF4~Dsx>nE%@eN` z)_TYj#Tp{^Vo!s5aiWXg>6aYxCqt55HY<1KNGy|;3{sY~>bjBE;+uX%c1nqG@z-S? z+g0}Tmb>iHerUT#{}D5%{3B&f`NzVX^B)-trmNQQX*rkFnLk^x!rQdt_7oXq&mT7C(4#e`bB*&+=pRvA-vbqQO%oKoP-X1Uevr`VNCZ}(hu;kbBc zO5ohhGwg3}37-4=+cz1zs*3Xb@`ADeFJyX`8c24_%{v%f}~b?Kro+ zh-*!;PpHv0PtCQnkIPh^h!o`t{xARJE5km4t*(z3nyrdivMKB-zfb-#gQBY(DLm@8 zQ;WI&m20s-Xs@hqxJ_kc(?ps3ofbd+?wtHy zRj#hK#Mb4@g^sgZ%r0IQ{c(a#px^XPQ@`5f=X2Za&6*E17k%=}t@K{Fe++Bz)(L6! zzO50#KYg3=T<*6NMdb(Q7@LII2kXBN`2H?%dY$5t^%6(kxBQ+g zP_NLuzhc_$m5Mng<%@g2o6VlxrgQ7!!R!gH>fb(Oo>(e^v<;Z= zwHi;DWzKxwK%K=esh)Aea+3n{s+a=adS}DHt?NJMJxy-5n2`NTExg!MHEVgmcj0UQ zUhp{BxhOwB|4E?A@YTJu2JH{yL2bf-mZJ%OSs55S`0!OMcostj=O<^UmbfJ*m*f{! zLMoL~KkGgwL!R1a=6||GV;Y&Hl(MuOx=k*5iOf+*(V3Fy;bzQu@T$f)1{tngCY_Lo zPtR}Go!@s)Z$E?D3%3l{4B>qt2QPg*Bz5>yW;Vy?hyGgqK@w$3-x8;(uugw!^6x^Q z`}>2pR>|(xT==&(Xb$^9Bd6n!x7vzyO}9#RdcSeolv6h!+3@8YQuuIr@?@v?pM5rX z7Og(J|4H$6`KnJeo<~>38=xGn4apCnU`2psp6SeT#}eql9^bN zUjzxUqmi67Ay=>3KR@^Bo{yS<5Ss+2(VCl{E<6@GUJ8v0jH(=NuZ&cjjVxwz8Vhr* zh!9;+HZGYfnyJNNB_<9z1Uk&|bx+w7gZeRlDUW>=4sJ8hgE zPrT6c*+gz>vE7fN#@Wv<+AA3JU%RpTv&7uvP7!j;H~XJseg3#aZhfKRl1H3Y^7@Zm z=Kd`@rNVK3vZ9Uu#mZIZE|<*HQxbU@v!=Ln!jxAr%L;eSp0$8E{DsY7-`6`1xcbIu z9uIq2({#?b)GqLOq|!T2tMKMo>De~Neb?4(n$2tz?(zJkP5g7#4V?2AeO#H>^~tF> z`_7ev-A}F@mAZZ^LcL!#&+9|b+}BT2XP#UBa?c&#%R3w&i%P9eDLTjPe)uG-&$dUC zOntt&Zk#4?`NY$Q85yqWzkdbPlor&oX#YH&eD>gpSqU~e@2@Sgy(#8rQ2AYLa$M!gSd0Nrz(@%1FRi&-1t&%>btXQgeM=ombR_7mnx_Xh<&+k&bcIT!X zQ~1IRj;$@tPHk^nXWkY+y2w-Ds@v>j-G>?4J6=dX+E_NRMKf|wO>%+plAh3O?$%b5 zdrwwq+_3w;B3)+cf+h2n*6vwq#8Q&S(WbmmOygGlpHsKiJqvI*lId+1CZ#iv_%Lh6~cgwu@mfvqNgNIK<(frOPt8I(oJDDbLGnVWN(c@LSCDkOmps3x) zSVzdaz&6-VQjWNr)cJ04T)NSsxpv!M8KT=cX@{#)h; z+PpbCJ!S86!^~f|rk2k1xWJ+{H_3p{Ibuhg63@gdyIec0GI=E4J>=Ye=8Qut*LIHk zjD|dmq6&2kLV7AC4OX>tMjefBQ^;m)(K`Ds=4R+=@xu|{{H)(CddNFPbdzdibAwoq zi`el+Les2oC*^WXn5pHWwD4L&O5&cYJ2v<%-o^TFnVnCc%kwJ6)z{?iM6o9yK4tJx zt8;r_z>y8xY-b51Tba2u2|4U^o0gE7lhyd;v~!?>UEZ4;GCd_-AFp5Kn1Al8+nNoM zF>3tpKTM15OSrY>m$cpVON$?^uroJsxTU1DE!mc@@qw!Qo=c6^cY8OUt0-Qfr_&c= z;o~=3QQCIPT)mGUUY0CvKfgd*P_W&!@z`pcJ117#)~Kz&Sh2SK{3EsA^WQ#L{o}b{ z8PPZET)~k8v-WYh9ca3L`1yyOpDg&7efKsva_Ohcmk(8WeuWZQvL{aH%2joItFkyE zZF5J5~jkPr4(&-NbX_=K||yqhqo@mCd{dLeh8k+TUqPuW+`w@`(S}WyJ&g zm+IcR^X$Hm&yU3$m+V*F!YJz3tvEx(@LyT*PD#0YN6sd(u6S%etGmkLT*36FR^7i* z;-@Em?zWlpL_sGY`$9mMN1`U9nZdH9dx@j+G5@T%>%0?7M(p|XDq-L{@_i*tPK`D zA!7Z9IW~l5o6Hc2*A~*>Cz8l;y|rZSr;>?P#TxStZ2YISY}1upA&v(NOc)!J|9wj+ z$=*L-_0Li6w0R{;QIi9mAMKZTYozw+!_z&?`xKvjyU_h*QhRyV|9HiJ^)b0Ne4FRU z^*2U3g`Dw7wtKuQIB5o_n3(T2$5(+fogy0gJ0;VXyzpJ_-%*`%X;x^Lylc4;r_x*za*y3Mr4>020`M6SR7&quxu(|&tNINs*}z4cJ}@Ao_l zEQ(9-$~^q-x@_lvx5p<;eoJ`W+m&FP!T!F4eKu=#@ak2oe#QGum|mDUZ(>BYcF2mD zyuN~Y$CheepBEm!f03B!#hZVBr=8k&=+T)XgW~lU*?Z1@(%oX&^6GS+(U;WQx*|7h z@+^)`P@FSiW#khvG5*s_SUy=b%gP#r)W4h(`HW|6&6=*{cM4UjrL2Ya&g)rP^zFr? zHL6o%4~ZNqFmt@-@bFFTu9_lA(*)_N+Q;m@Zkp$Vu5aSXydlNi{kmUeq4T-+pG7@; zd$(q1g+Jt*v$B)-*lYb;n`acSxFM;%`u3xZx<$%u2ew@kaG6^tBD^d+CY_1hy7wM%fqp{n@AkWZ|Ur{eF-`7ry;0tL2dBg z;8PbTFI=}pLQUprxIlJMk(lnLE59RU)ql*-Tb!tE-g99>SJ;PjjQ`7 z9cv!t?R@J~XH9;3t^XpwOJT)=bo0~A}&?;O#P3GXK3sa z@n62NLOC`qmw_?XFFYaTmrQJC?!3g@ZSo3R^Do@HZS?Kdw`V{r@p&z)8PLqp0lrwO!S2XgRVTSIJw@#+eTTpaB0B7 zf1wh(-Bnxfw#$Ef6_~R0No7EA;s@~f#+4r>8ow0tYUZcAAX!!;IpT1SI?=LU^>HKS{ z(yy%#_uYPQ;Qb}Z65Uw$yg45@{r=eOJn)+B&u+o&f`rpMQ_F;F9cAP;&weTPLTPif z;pW8i_ZgSpe)z?EXMfp6S%$}6|F~)=zGF$a_Tg}exWeL#U+;MCHoUxWIs<#I=)Z3l z_KM|*HAeZZ{qa2^xU3?&lC?NDVvC5?9K$Kj`DF z$#dctzfzm+U;m2XY+lZ$-wRSglP90BTmF$@ZqMH)gX@NhZz5Pe?PN*RQ}8ht__pEv z!^@XBiX{(Nhqdgisgg>RlIEH>abd#SgqD}i0?U>PKJ!uZF*(mLqxkznz4gyZ-&yWC z`C6nQaUN@eegR*<2lE@QSuM}sGi9{o?Z%+&y&vGcedKo&E5v z{)WkMsdMioidTqy;P_S`_xw}JnR8ET_%=JVnxt$`ez%Xu6pdTYTk@Y<^`qphk9n7UB|waIk{4vb=Ij< z+EtnF_BHJ7e`dP$UBRZp_pNyh2`R7($o_W_~>%k8z zKT6t}UYhg#`hoUkQ{;6v&)$;Cmt7LII5+IxvFePPnYCeY*KI=rp3Rtgy^jCs6wCCd zTi-1+K3W@;r7yI6^VwGmk1m+D{BVWU)0y$JH@OxzGjheVX%rc@OO!Ua{&ch~7Y~)H z+o|Gfr`TLG#qxL`>#`3w9?gxn=(5{+{?>Mp-(fu4`70tD_G^l=|6Z~0WMD;|zHW42 zqVtUt_G{axtzWz0^cKfueObHL-g;Ona?g8fhmkhZIj;4!?Q_L12xxGbKb0!Jo#U*=gDP_{^^%fp3IZ1u?qdDHLJO%Ol!THTcmUD zo@wu%Yt$(Qfv#MtQ%=J&%e^}K`%=bt? zWs~wYd*VvbhH@KQp7ih&CnukkyuD^-@A;;EOgZXLX67^;;ykOe|GqB6lj*&GI66LY ze@UJ6;H!GoWVxf^M?)Jv)P2}qXshr=;@X=pqMI*l*;gwn_J(~&!;0fffrbhy3RU{N zi>@*>-IbEP_F~Ji|NISW{#|D*dQ@}x?E}kq5t6gr>B`AcYR%V{NMc`a(CmZ>I{?j3!U~&U-qfiL-KpD zxV=aC=jju^eY>>wPwKAj?}6r@zCHdUQ9F6R*Znp={g1+5jIR{T{}7z>yxF7d{0E-8 zY0p1?-qWz3_sgCGtAFmUk=uXd^-occ4_X__IEwyoR8;X=RL#wQZ2rUUpJMsr--rLG z?bvg4|C9O4FDaHT{djrqG57Y>S zQ#}&zOK)s{zi8*N?tAXOzIJ=3pX19ov6wM@nZkU-U32BE)N7v|%yX)(%5z}e|9OpG zVQHJc-q{Z)KQE2i-0jWQ+8>;?^Q+P2C0BB$tiuQ>>Ib*}=UM(wdcki)p-1i}T)v@<^-hm}8u&i+U+H5w zciDqAryR{S)$gv3DcOH&>0YgVxlq!A1wt-e*l6_aNjy?xcQrgzra?JF#6c3aJSAI5lZ@w1P~ zS$6j8#6CH0ZJ8fv`e#nmk@c&Oo?7;5O0aIQ-qx6>E7?r_)`m>Jq7}MC>S|5tGOO6R zsSf{irJNTpc>dU9UYSGgEXERRStf@03+zG;oDWpBgP|$i2!pL1KWuz%vVv&E82kDD)Xb)ET<(Kg@YNZ^)}_m|{Pls@=U{7deYEtVVp z8vWwqVmQB`;8U!&?E6MDrMdhMmn@7q#Ca)iCnWE>Y4=TuE?jb_OZjP9@w zpu8g!imxc-4=zrD`BH?$N zPrUz9hUj9atB%2;bHrA&l&(Bmvh|kJ_SLy1?YI1PUtP+pw}aYQG=E{v&)pg_ zp7E?$9KU3`&x1>0YZjhds`T>wv)=uee{D=$ZSnJm`q#FgC7r#sCTmyP)JN;b-uQp| zL!m&^mF_12`isNsTe+@$&sdd! zBAGuGLl(ykkC z-YC+iGU2ccAB$51%OeIuK6j^_MN?A+XDhQDpE03y{EPWc8kjvwcKu-?moRny zgT3sBf2i0U-Q#au>2dI|O`Y4pbWt0jV^=K>ZR+3jW-*tY__607TMf(}Z#3w8)V-&? z=X;-KMU2zLmA$XZqNK0%wy>-WZQ9VQ$hnlcZDr)+x1O~j=5uYsvT|aYZY9pzb#>a6 zoapVUTaNnP?dhiLU-Ej#;lkCO{TbVX&IB2zZHbs>c5iOsCCTN-H#@Yih&vlBKTR!WcIo@+xN5fg?p#Oi+n%n94?q5yu)!v3 z{^w1H&y;UCQI=lK(Z6@ax60)ayR(8HRRdBrhJ+ga!l$< zx#XLNt6a6JnB~I?mG7-cvc9(#0{$H=fmYKUVE{lz~lk%^blu7x`04iUZD14lW2h>i;2lT7Bd}ZJBVZ?eibU8A)G% z*C<$fVdlY;Q}53ezjtElFS)xs`^t|^SZOKQeX3G6cJKd1SMz?{@4B9C{`P0=hMH%6 zyYnWTZ?oJ|+LtZo?{wmQNXbL(#nb1ne4Z9R`S4^9-n1KDYc5M%wf@?&u(CF6OUZYS z6}|C}6RLS`CeJI+%dK+|vki9OyfUd}gOdEh>2ub8EfIC{%Q_}+dFx=UTFnKc6&W_i zwZw{gTDXdxjM=N&UYdDu?Bag)(2Jw%C9$H=PBSk6(VEH06$DGWPZ(6Zt+R|l<1D+&5>2R@W730!>S70vfpT2Pp z+ri0NV!ErR&9+IK{J?W+`nIa#4Mq`tqWm^Zk22T1(vG$5ygp~;H0|d0O)FMT+uUKW zGWT2(@84@?0+Hs8UpF(#I*77PPMuc>R%0KVtu3%@6f+UG)$5>}cVh z!tQsXY&(bEFHX&4k$XD5n(cx<%2Z{D9T2nWiM!*&d9(BP%7Sk}Onncc-W;C2G9hiU z%E#G0Q@md?d}QhU+G?Gpq4e7S{@R_we7)Na_vaWEPtjSoXs>!v-}(fHO%4uxi#+rk zTGu3Om2sLI^Mq-gie=CnX1)vdQ|p+VoUY%POtutEEHxzQsX8Pi?@0;c&?N1Z*Ts`92yms;g z?qrgF>b2#>)k=@*+9isQ_VVVdx4d64)obzbi!pD$#Qfg=!H`RK{_VMk?Rr=LmiVu- z?&RV5M_)fnh<}#6|Jq}}}7S*2IqtZNirp0F_ z7w@%ew}q@;dw1h%uch0zhH42Xx#Ygh`(C^K_rCXA!>Z0z=TGxd%X-_t^ZmZ+^S0mT zysvwH=kuiVcAqaOGlX4ol=c4D&^FnsrecAJn%$y@jo$IGOTK!{I-|>%MgKC)XU-_t8W8LvSje7^L`<3@!##q;rApS3gVbhGOgKiqD0?LqmbkMB+YI3Ab( zs4n~Z!*hjyN)>-XkKg}LF8lw0ee;iS0e{wy`H}y&^!~xEo&}4OMMTm0jaX+ogCoXK9y^JMumCbTbszvvfA0!H$6VwKHRLc z#X?=g^9v7egp!EthFfbquG~4Sq$9N@X`0Uxj?2;fGuY4mQnZ#@o!`4GXP)lcj&DbO zt2IvEa=LqQ$4r^LvZv*0!tL#xZr(O|s@sp82|1M{I$d-{#Qe<)Rt6HMZ|>5cwPl;? zB<5vrBkw-ZSU+Qj`(w6khdXA!`L*C?^46TExyzpBUQXlNbYRv;<=1zw&yak-`u&E< z7c1hE?|FFN+4gJAlEsndv(om83ZI$3!0p7rApFSY$vJKL_cPvkaRtKHbHR(0k^oU!E8^85`~da4}+&&{sM_HTQu zclwu9ufPh=j!W{ssr}cYAIQF)CSF$d)2qVYbi%90b9FZ_zi;fa_~)BN-!COadtUZ4 zm}WY;Iv`L%=lHdn9ml1%EbgrETFiRpuHET-V!e@P+jF(&JxV;Z=G3arPrsmf3OW(*nPM*o!Qf#zhV}y52!HL-ua)bTy)$`BY zo_6bRSlZb)o?$*oj*WAK?`yVY`YSEou*XPyXYz@2onAdtb}V{S5h!^`-t`@~NGo^;%WBkDYBKk}m3U`mq=8w!AmF!@#v-!eq(id%xwJ>RckDx~DSJ ztVuOx^zNvY3g0m}^yGHI$NhmhTKD~Q@mRgm~h}&;h{5k6fI|;^pt$TtZc4qzV)up*Wx5o zgN7ZAj$fo-I38(ejbkoUOo|?Emr;8}vgK2d;H2-E!x^-bXWT?I>K_s1n3>^)gp;*d?uAJ%QVLCI#Gat1o6X zU%SxF6XpHdB+FpM#B0(eg1Hwm7CX+)*zD%Zmb-9mOY3gkeXNgbPCR@aCc|02`=aS!Nm1v1=}tHA@zDI!+JDW_$NBFe5;EtMTIQ=OWEz z9kJG##_j2f&u6uyIc=ON9=%QX+s?#SGtw^T-O}}KcdRbBvf%WQCRX7eQ^ot3p2RWd zADO-5#0ieFi0eF&g?%k^=D7Xl*)_+?^&eN?jlv%}Nj@<-VX}rRy5rVdtZQB;Vil8m z!TZFMU5lIjBac|h9WHB<-{PtB_S%Z$3pj2&h#79}d&tN9{>W~gSBpbgB(C@e#wq7W zvhU_*Z}*owpJcfDd{60(Wx1*Exzlc|Y~gYj3e%GDzwz+Og$D^rneFUCp4vIzXMg;# z>gwvlJG~s|q$!BoWiRNuz_?FKtvi%+zqO1%+b^D7v!ZyrE;2T=Es1o?S@D09?d@w) zQx-TnK9OpkWRVx(B{jP(F5^be{-@J@_LQpYsE63T-)-q!;Q7h=lY{>JkmlK~$Hleh zu)Y42|Ll37V8-9HRd=m&tXIyGeA#cUFM58NTDX*Cj#Hf5Jfn59Ql{GYMugprl6ck| zD%}2K){8W!H>SzX(~^0`qfYRx~Z|}ARMM0{MWIlJC z=6bteLzeq`8DH~E8dStle#p#@-O=2XgzVK^`A%5 zyEP6TTz5wA*p?|F#fAU;5-wTKTw7=4_Kes3xtPb_Fw2uua-^nA3fZ^Za&lj{disQL ze{G4R6MLVS{$StYBchM&c|Nn^?;FPC71nB%UrRE-sTyCrcz*is z0~dlqJTLsNo6x^H>CWW-x?asokKTyB=;d9yBaH9M5g|>@XK!7$$p|z@$Ry5);Bqqe zGKhVZ)-XTD%GzIVYo*?)TKS|u=S0iC*&ck~T>1HW!D&(5?Ne{xRsXVapy})*91Kt3; zAGQ98v)*T(`E1*~)N5fBYruMwm<1&!TFky#T-#Q!ys>_n^2)RXkF!TM%xXQ{*C&+Y zZrWC;`{zdg%^iIDsq#0SWe$FAxLj?i?CIyf;mbln=|bkbmP5Waub%G=|M>o@#VOsz zEmn11d${Hn*I&CMBpLL1PA+fxt=ml>r0%@YUHg3+7hBcCM@K8WnQtEb)A>;MAOGo} zKP$V-S=O4aNqv_&Wj6=cn#D8RGgiwUt$8%-d(1l>g=4j8)x7f$9lC5$F48TtVZKf0 z2g5Zsy+_pxUnv|DZy!FbKFv;LQUWOkPPWxMJzRI%t{bwv zne;qQVEvKTvWxD$b9~sh=itF!dv%*dX4L_6EIW54uPD3|@ovY)j^D{E(rdz6!j^43 zwe%@#X3UIZuXGBMBQ9$`=zZWixzW7drXt(ec_92f1054??|VR(<7I*}Wkq_mI@pBXjO?d7COP-S)Vulrt}U zdXmrEqJ}*aekLwF!(3!8mfmRdm~m&@&tGZmCth1}-D}$ZDTghn{9W#y)6dQ8m3BUO zrR=oe%*J;%Y)hbh`U%v6^(K`Xt-nDwC&Q@xiKesUE zxYV|}7Qau&a7DBQwJn{TxRXgY%f4*o>I+MKTtdtrX&t%{VX>lW^PMhZ9X*wt8nXlZ z58qa>Ti4+NN3jS}IT8hv~ni znYvFgXU62@SrvY3?|yeW>YbZ2kDaLdOs@rAyo>x)H%2Yp5O(vX^P1$k?xTz$A205i zU0vrFdp z-s-m7w^c&hqn_ROIN~FFRP_{RSHcQaX@#g4mpU&`-*tKB=bRIB(zAC@{yq1|f6bP; z(>YhaHgf#>L2V**eA!G4_~t3 zuzLOXkDq*ITt8V_cw3^ZY*VN5jjL8|cjuZazsOk4`_}XErl_gM?nQk(=GoWiA@!R{ zS}cwI-JznF`Z7nKPBMyio|_qS@xglC@Aii#{R!|}|Juz}{hVFkYoosFCsU;KpWUzH z>(TyM9%^c?Z`r!jGG|*NTXL~_@f*D}LB|dK?>4)>Vo{%1T{yAIKKZj_%({2Z=KH^| z{{6Ga=H&Fp?gcKk9nwGe_Ivg|2rIQZeLQx}`@b;~KQ=Z=erI%ZyRhr5^Xi`BkL-o= zi%q-rPpjCO=uNBnu_5{T-yO5&AKEapLWX_DLpA&OW9P#kC|+~;&k7na_T<{_ZO_ZV zU?+obz}ST30b|I*@W-lpm6By)Re?9y!_ zI?o?2^W8P=+NW7p*J-T{+I@lDBp{URd%_C-_QU#fn4cF^{AFRU zd%T`uU*y`!e^h`R$OiO{m~>*bFumQo{GEeXDbeN z>sNkA)!+B%uvy|u)tb-~wZ10t;%CiWKKt_D`|vRO$2R`^2g_}Dyf`{Lseil8k9qvn zANLsiuH~41+o_x;Qr((R|*=Mh) z*eNHYyAm_IQlF{p`1QC}=+*DzQ$Ks{NXV>;Fu$C6)}#IR&DA@dh4%E9tDfWKmGAeM zuuC=PjbXQ#pH`J)=|qRluvQo)zjsu~IdQ?&vL|g{tbWntsmsdr ziw)CGzRGrZzb$!BdgY3pu1^!sURa|nH06Sn-J0&wzZoX;mb|u2>sojHOLm)-c8c4T zI}?l+6{}syR}=laWYXm$H)eiWIF_X4+fAwOQ)tBC!W3}qpl`EfIJ_OoW zE?c%}B`2Sfu%~HurcVriolD%6bnY&{mA3*6KbE#~%F9cJPrkPBn7U*|aY_tB{5FpV z$zFA9UaZo-A~AJ?=Gv&ev(~w(aVVa*RmtHrowibKjf`Pu$igKL*1q_b$F+98YUq`P zjG-qzZfr{kGd>)s99b{!md$+U>HSu(XOclxoOqT^@Dx*xJv&@( zu3fGB<8#l+2|F3mt5@aDPHob{O&VUw+NU>IS#vti>W?mfn)}dv$K5qROsE-ZNTbfvqejsCnZ z6(5A{?;Vu1mpkkzw{DR{EpL~T^FeJ3*Gc{oKb_37pXr#E-p*p#TlZyQxYPCab?Qu4 zLha?)i|g($@=uLEzB$WJ@ZS{cX-2)ZVFsye-OKM>y?IkJ@wt(o(6pqLsa3pu;s>8k zso9XQLO4>+-gK!yoAH^hKwsaBd$TL9_oq8N3J&<|k$k4#-)Z`VvhsUXAA;@c+Lqhy zcz68#M>)oIlM|oBoJ=d#&HODrFGFh<(}%dGij%05O)KDxbHQ2OICjrf|*w-35^G#B%CrOU`Y`tfkn zN5(#RP3iic$L@t2Ozc{!0{{Go*Vj_~{Z?uIO?DT@&DGb8cBfZv`fay7JvTA_?0boM z3)a@zaXZ&Egcm(?x~y}*|LpsO$1-;gH=c^Dcs6@h`h(o8eXXk`e=M2Sx|KI+?W2Y_ zRu9&d-fwx`e0s4pSF~955 zx;mN7)VKJC$(=h!-Th}23{tBt4wxNVZu=y7!qdwuCbe&jtm7*E6v^^5eM5Mdz_j2O z6Wj}3{2p^w@)SlMRye-=DbKl6Y{#D17=5aoGhO{dmyKt&LiE&>D)UDv$8~Lv71lV} z^!`+zG5L-C!N}IX<{o9SJx3ITu1qjgiMuhy>fn17zm0FVuiceXd0)nipMBezMP>V* zxGvqGxj*OqzO5Rew=TC|mUyYg~QfLXmQr=(}q_n>R&F+gang?4ZJ3j@un_TYf7| zsG7L!lWEB5_eP@Yj79G`d(2DH@|n)Tcd%JdC3i+F- z&SorLYxb-pnlqJokIPT?MSqk7|8;8o_nA`fxcQIymXr0a%l~}e^v5>p)cwU54E)wS z{qiaI!3FCVDMbamcb0rzeBIk()k?;n@<%@UKl)J~xsTO*PfD22wOLC~{+j>vhPTgA>fP+K9${~%N-U_+)w zznJwZqgfT-O^RRpzKOp1KK1^we;Rci+fJ?e&kSl-u-nv3YXM0=pp%2gJb=L9Yt)JTVqd!ZP1FE>Mt0*B}d#|sBy*=A*Lk>PT9USMZ2tZ zZ|9WHz8iUYe`>{q9|<+z+$G=ZTyg4&|7}oy?r!nA=HHVf{|-T!85v+_Mro|{?i^$(UE|GO=6^1|2K z%_WVd9_Uy3p4wc!@j~E|4Z?DBc@CAV5nL&~HPt`NM$YxOHBWbFyvOFt)9<{gjM>(- zAzO~k?@cE+7w7pKXZ`*gWL-2p?r$=VW zeJOX*UX=1{+S}MA-q)Kfwj5ozy2Ob2+^nqGjgoiLG>$IZztF|}(T&nB>n7{lPFqfF z+g3UGJ=entqD!A_UUR9KcUhy54)5zzcBwP|d%x#NDQr&sYi}I6RGg={K5uQ~>>Wop z{L!DAI76=Q^y@VD8KmuAR%BeR#XE7BR3OlWT8@o2fgv5dn%{?K*KVExSb!R-Du z%CF=)3)?4nPMatj{g>sN;m^5?OKl4G9gmIbEoOT6&@NJTvwd^CT7ARKHzy?B&QJK& zwK2FSeJkT7f5U|?kxH}F3K#fI-K%^)W>U^Sc2GJjHR}Foz{J3CgBf2sG{oJ!g{MR4 z?1N`sT0W$0J2j#*K_*r7|K60zGjr53cW2&O^5w=B-`!`o?)9F$?Sfk7>{&~;zKqrN zDO-N>+S$AtH+4NlCj<)!invBQ225ELro(EcIdNM@&>D6zeuqGZ4@^h71w;D2pMCSj z@6ySK^1sj4+U7M*uNGJM z9b13*2k*S;ADX01D*|)sv@_x-ec04xBKADzw?`lt0cU+ACSV|k%}FOR+cF@3{1=|^ufCI3(RxU6S;i`4&<$Ll}ZZ``Bn zasTAu-7MRr0_9Qzx6O{3q8z-g!prES(bJPprfJ42xgOwB(Nak<&yR7RacPhL-SxkO zKL*^8?<*^5QIh?aR+qKWs_DvxjdiEb`S!B(cZ!AmERME07V&520z0XTkF!+v`SPlp zIMv0xy|E;7W0kI$y2z(>j+Y-V?2zJjRbHdOd}~o>ghFf9K66unClMx6<}3FsQ;6kO zNm^L3-u^(q{vRT@q`6iU_8zTjl3cgC`QVIYuUjI|3hKVQe_c5IZ~-`B$GI=nr(}{`>>~|@msC!zhB>YZFSdl-dbqt`pqr! zS<(E=hJY*gMPB+Hxp`yOt5iqYRehy?lG^RZG*(U5!2(Wlt1K zl0uwruDEl<=$iN;9`-M?x@UP;mb;aie`DE__mDq!QQ@1re7f^ETW0R7Tx@L`zkTwV zPrYu57Agq};+waywNKDU-*C(1&vPt!Ad>lI}+sb`PBb)>?o zT?u=Rb}YB#^Rav;)L5akj5YU-s_vSZtL8m-xRg;Rl6h;TTT|lNi-+`ztt8qPxEkh* zv#$yGwP?Yyz7x0hwoN|}cj!*wp^UXs9q!3{4?T0NUU}+jaH&?PflEr>-8*Mo&!%W> zxw&g+=gTQPO$FDM^eno|^J#X$vD2C1%}j~66xee2PTX-T+5An(?1QfluUdC~b=94| z2SR2d70OX9wklcS9=z>*9}JgSOB&?b3LaX-R2=fry-aw0+R_QZe2;g`&B+$&6?`TT z94vKGo9SW5!jjpEyUkRz9vo4;y4KAg;Dcg|D9b|48{K@YbCWm|=es->o#h~BcCq8B z+d*54Gock6#g5TS9vuF`A-<-EbM~Rcwa&cTkKVkQslBOV+Jtq*!k@YRSD1gkxp&)& z1li0*E=Re17o8NEsuAK9{9{g7?W7krt;;T%v@YWg?UD&`RSnO`EWBil)irG|e9p>(qTVgqZlgGX1qAR8(cw+6RkwOcFlnv^mruf7gwQ zb8EA?)`^x(Zrk8LS%ha*IM>w6I-SonOs3bo30l2=hWo8GD{GWmpKZJr;y6|2nRV8* zGx2(XQ=P7cIM2uuT=TLwdv&tm*6Y_Mw#@y@b#^%`m)_y0cQnrx-gy<#{;+g*B6sW0 zvJE1KQ&VGP-PT^>T6gFw*Sf=3=WO`)CpcrF#XY4~vCBes^MXHV?O>EockZ9Cea+4Q zuLtY9U4`%Z^4<$LvYPFC_l!%uJgdG&9g|Soy7QVD>t4mX(hm;=>~&(y*T|UAJLRR2 zZfJ(&PZ6v6(}cbDUi8>;eYN_o-HSKwcz5^Wok{B!O@6hwv*5x5d4cBH8W-Xe6E5A0 z*mC;x8CIKhMS8_CD`X~Z4Nr7Dg}9i6%S_e%OBteAGKjj9g4d{Xid ztFpkXr@vxmO)R;*mgmfZ@PG2bbDiER=gB@czIXq|K7Z~bYfmX2+tRzuVug&ixo@dn z->iEOLrmyUc`SKhYk@7-O`?q9jKW9n|H>vl(F>V1mNao>Mu`gx9?-R9#( z9C}L`w`JHEA6v6+{>h%kUB!xiYNxh*t=YPJ_TshsCeP+PulcNRy`;EaB)c<_gZgShZ$# z>M3L1SubaH&WxUPv-y>eeShXH3B`+q3Iou6f%*Lw6QV_O!ruF+t;rW*Sn{ zE#sdbD^M)js1)l~b^GiryC#(^vvQ?oh#1d#7?#i z=eA52EHvzW9lWyju>rT3bzK6l)z3o$y^%W?NS9}o71y=Y&heXYaN*Q0HYd+t4&UlE zdMr+5NAEBE?V3G1O8V!%O{Zt=V*5XP;oIwna{Pr?UU~VSuTk*{&-d_-ME#Fhac`IZ zYD-l*_vDszmqD1E^jW3#l6FVt{Ht`7EK3k)Fz4&kJDnf=!SM~_L#4X&PIB+{x4l*W z5V!U1>5BV#x2J!$OStX-Sib+kF>C*a$2J>(eG)lmerwO^$yV!Q_uM{L@F+dgRledv zHAiI9NwIEk9n0_1O9Y)S#>C~fa!=npE8KYT>%f-T0Zr!>PQ{B%7Ti_HY2P|QBA83j z{L|&5=XW0FT)FCv`#VjKwW3!&Pe@KQR{UJm-h9IPrcnGbnLD{1>kMu#cj-2lEp(o{ z(<5Pj;`W%BF1eJ&(--RfD{H8)S?O`};CcVX`N1C*HuWtNJz?5#f5TjT^;$c*oZus? zC9J&@!b3jYG7lbhc$|Lk9P>vtX-_MZef?r%M~X|&vor+)B417*~Yp{sV1~2KqY;JlD?JJq2j%h zl`Ne_D_b+;WZfo8TSm7$@GsaSx#tC2-)xzGW!o-IzRq9n?JD$hd7uG9>hk3a_*>Ok z6*>$5O2ofj^~p!0RJL7RdTr>{GgKy4KA* zn!k!6q;eT&gwSPn!=xKL+~>0&P34RbGH!o#cGHKn*%eQj%tY3|(vaW4;=NHuIQZGk zqil?E?Jee(FYi5CpPy`YuXX<0JySMqoU>zhkl40hzHb3~R+{{_PmYNmnQo|cK-WaB z{36Rf7x9O7vpVW#^{B64@xLT;_|EDZ2R1)EsJ^pgXF&VP9g^E6JZsF}Hf{bPvRu#H zWzNGZe@(KVJ)g3F>S|xJ{{AU%{3-o_f{RwFfrNS^w^1ymwWdS zj{c+S?22m&9SUSm+8x@anPR^#!T(+(c--_H4C!VERkBX_-Do<*Ee^MUdYh=cG0M1r5O7PzU!C0?zpTjFkX91_R4{Kxh|8g zB{s||Y`XSX#q?q2tp@QQc`R8Ab#A3p{9#ak$@5Ne{^94n+e`)7ce17>2d?7UwPDia zAQwlm_bN4wuN}m$GjMK~&i}r!!T*zMo%g2g?~la#R13w`bS5it>r3R9cdMvP7j^ve zO|)j};v=g6BE3{UChvJ{=jQ6VV!h9zhXQH0-<*1RamJCTZ7b7bk8PN`Jm7v%>W(O6!!^!t`4QIO^Jh9QxZ_(QiyWKs%tf_WcRLqetc!)*ic2mw)1wHOf zXPcfxOnA#QX=R_=ugiKnGR?Iz`JY`r8sYYK#{{O1Aa=c_0_&F4%5Ws!af{tCUCF|C z`U4)-4B+ zf;0Z{`pAg3=O0S-gm1>Mk^9tMU*c*p$piR=`CPx6CwiPnbyERPA5{eS0-PufZE=w-g% z)3ya~NVPIP>*2b^bFG>8;R7a}D!R)wzNS7?txZh3_vP$t6VVB-P1>_}2#72^+LScW z%w%#K*VHgq!8-?wZH_->|9kWwzuf-&*4dXlrELBcy|4XV_x*$Zs%eSY9} zc?VsTxMn$%B%AGH0jaN0;RWy68T>x?3(cK?xWv2!V>Eb3;OIR z6q)~c_wGA8q`y~usJ!#~NUhwO!+-T`4*V9csGKm}v##z$r+(E2#!jmm&iHQ+w0~%E ze>Gk9#Xz|7NUM8nMNgvqcY($0KYte1t7%r;cT(VfQjO=E+kd{P1S>UYiq9*0XsuT> zU4LHLqiQ*u=5)z-GlY+`=3Lw-*SPG(46Ai*o2Sj=Q17`IXlp9fcWK?sw@js)Z#||@ z+gNt|@v;M3FHT8oJ+7u>x@PI4OlSYdhwlzGDsJ&EHLp?L15M!*gHPF;*`Zyv`El_I1j&*}i<)&lXtC zxo|_o&BymmxbNKk+|$cmPnZ|k=QefQhT|tKpDc4`5tQ_mTqY*|p~U~lmMu%AH5Yw9 z`G51OH8ZTI85l*itOykN`Eyxe$YzaXE_J+LlgH+y6GViZDg!< zVGoP`qDdFe6xuF3+y9nHnsMoeJL_jzgTj&n`4MzMRC{}I#4E5CAYDUrJAa%Z}cj{MOD z`jMB?ju_N()iqtOsEj>WIVa>p@E(l~ySh%#t#Cfb`o+31@Zk9m#jN`e%;u^)ne>+{ z-Lq%X+*>to%!H1(A3d%9;6tRF^v0@g-f!7^);^Hs;d-MX{jFox$CFb!+iP|`?Ov%V zRvz&=^<~!vRYy&$pVpUGJupA>ZM((l2jxCr6zshFUR~7b-gz!OP+^0<>oX6Tx&Otq zXSV*B5fybcHMf9QBt`wX!ShA(p8xJQGv&VCw7OroKH!79*{k^<)-}`%9_eFo6*gR> z@ge+)VT9g?zQD^TmT5Yl;+%BNB=}z2@0V8&tDo97ZRtJMuz-RocFM6#*F(aVYH3W= zQ@Ztdzt9;Yt=o)#57_FzdOb2ug9$!*aTr)-aHTC7i}X_@@nE*%-v#iW1tI{PQr zHMJ+7$ZLolVhdXS`-N-qfvZcOpE~J!ZR@Va*}w9vEiUZc z|NB}VW8s1bk7wsCZ|!iiUAm3qT12i`lEkyEH)g09 z#RR9vigv~RX8JLyR;;}|(rx3h;Q5l*cicABPxL!w8oBrcSNFF?Ha=b7zJ|`O+G)OS znZt`+YaY5z6FqoZTKvwXgVjoVpO{xCN?(lJR%I&p-lTt-uJRRbDq`l3Zr2joYfT zuWz_K{?GSobKwKcyk#Yyigr)6-dc1kd&lh4`B^Wv>{eLOUv~Mg+%KsH-m+VB8xu0b z9&K@XvGA(1^#ljqNjp0I8f_$$c1TW8S5trTQYQ=aYz-pl9m z`OFTj6xtY7`7?!e)8ZBzhpy)nomrnq-9E`W<9ukswJ8SQ6YCYFUU}Y(+BKW!*#=E1 zj@;7^XPNyrSvU7k*~?@69_D!~3m&I^5^*%I-hN@>#keoeN>z5KpSb@oL!o_ba7OC? zD&{Ar&5oNi1!qhWah~*u%gWrUNTF?QZ{KIeMG|_|HP)RxQmL{PoL?(uzA5keQ{GlH zO?hd$Cfl=u8ON^d{wVeHKkujCtSevW1wB)^`Q5C>t15BRlmDJPfnPW(cgfD5)@jsv z{=!K&8MOlTqb+-t)D9euKj>k&>+zP|D#=OjStZ}9Z!nUVmKT|EXo*SWhC?Y+C)WRM zIG^zYyH%n3!TL3SzGx<@0K4Y1E z;O#bz^GU19+;d;N)$jjg{p&UJ+RH7*e{aqFx5Dpx&S$Bd1&bv!-{;NWdpG_2w=d`S z*Z*OCU|SR4zWw9Irm#C91|5p5f;`$kShi<<%+$3DHfXwC+VQA(qfu15;hjK(zRsvS zqWAS%oP3TgX|h;$q*~S$JiEd z=22cn>fx)0+^mw@c1}HWqwQ(i*CVIgEN1Q4ZTL7N%q-bDuO;DdTk4MO62F?CANYF4 zsA5ssBx92!Jl)5OU$T^^ZE5i|-Zx`y_Omt5B$8rgec|}-5q)Fk1|!SzGX}Bm3|0tF zJ34p8%GAwsM3mCMFM2&gx9i!VAjerxZmyZOD0Vv^>(>00Tcj)#GqUc)7BX{GX9!SC3vF83P&8#|95`mWA1-OpoX z*YZPK(>JW>SzLC`C+cqAfrsmoKa|Q@q?vAba^vOVcb}4`h2}im*(F|a(%{E_f9B@z z2ac~i!gYP+kzJ?L_HuMdMoy1riV+n_-}Cs&o8W1|clJKNv2N|{Xa7=yH#`rx>MzV1 z*2T5-`I(0St1VK@*Dd`yv7t+BW$nkUbJ8xgojrKtV}Y{m6|ujm%4r!(Wc%a{+CDy* zUANyd_~8Y4nX9LNTP>UGC8#5#T_^c!+41Gi&DAlIvl)Yb5CqF5!`fqdSW{_`+^+~7q4}*NN3t@o~f8` z-Q0d@+Lo_#3`E6VPqxX-aOyN@J}BHfw@ajOb?cUMy?6TkkGv0vzB7GQhf`ZdWstVm z-GfUN%`z`c-?>l9wuJXj#kuHr5>KD+a?y${f3e{I{IGzp4V8NrUA~+@(dBU&%Zs~? zixZ{1zl2sf?{ECNukDMs<8!UO`ir`bw6BbLgF%NL*C$j~d|GkuSlEg1$CE#=kp1+-wtjJ~c9%{6&@->DB~W*V#z&PU zjK369Szof<(=YhPB|jm=^;0|RIr~FjnYQy35xCEZaHEiVHhf>u;<5?w|u3u-{x$# zHvM|kexaS@V^zm^!$6;!59~h{_oPn`-Qy7aHTBsX; z8d)}R&N*D7pH?-I`$!EFtBC2G>jtY6{hAM6P=0^Au58}I2(cKcuiH#`cV8^w(Oa`D zn>#Z^`|GyARd@38tCoG3y-t0)M$S#KZ83>6PXBd{sq1#s-6@tXp>wW)XxAJnC%6Ew`riweli+t`sf3oq8ZSR}+2_gRf z%QWsj+?Rh%3T<5g%`n;G=vPJ>T+kJ086gyn7GtX|pqL}2| z+O4rqeKU7A$!s}RzHYH>qsjf%Y?_kGb}6|2o2LK$Z!+)xV-s!^M8{1HUfv}6_tJ@- z4Kw*<|5~vbtWR`2&Kk31C9Ci93zNQY(7bE9@$IV}EvKc{z1Y!}&GXVZD=Fg7cfm_t zEfe}QvyN3QJ-2#N;pqW*jD|2=jFLv$60EvI1OZ&z15nh zF4*s(Sj*5{qUIT`7Q4_oP@|4PyQbxn-WSP5#SDf*^2+OM9Or)$(cJV>#QmN}a!X#D zu!W@JTL)MEyFVYvC3S0^UZH6!df)lHbdSir<}WvGGrC_zTRqA#U;Hj8LF(}gm;5Oo zcuc&0@YtRzUNTi&B0MfRsIqg-C$7t<{5%p`C#9UUZw~HYf2pL^Xwr3Aaj(rW4sXt- zg_Dv*j9WK-V*_h|jGBI8iIH%6Vqy4}uB*4gvb$rq zYUOQhFzwjl6^`+fE6u+{UUqN875dS8F9+W52DOr3}yPxtPSq)qca1xo5)sN8zz`iZAHJFlEv8u?so?)6_QIZF0qS#UR-i-)#sf`rW##2lP5YE1Ry`*~kIq_3}m3sBRB^FKp z@gr#8ni=}fwN3V2a{s!={qgFOeNh&6Y9iM~K5yLyO?jEr=I!m4B2|O$I&JK)|~h;=iKj-eWB0KpYGN_@w9u<(di}sHl2$X z{CB(SXW741G4C$?@Y{KR>BqXt%?>Blp1xbO(_QcTuN7_YFaM~UyZ_l@(K~Mz>(x2j ztGVla{Uc+h?3EuA&hej`oiB3PFXI@0;r4Uwrgag|m7TtK^y@ubELDHmJ^aJ=lnw5C z|47Jxe)#Ea(m%fYOFoyI*2O$mH>nGHzPu*kP{j35m#yrTn{8e{e*U9csy_bR`RqT; zbL%z!+F$x{{OBLye=99Mq}%fUhWyh{ z>K8wpxBBn;Ts&oh{V7(hJsRJqo7CMrzWzh}(O>Jc{+Rd1U;a_r```buxk=sR%#63& zjLX;hsqPLs`Kv%B^VrOuwu~!1*WH>rTV^ImDT(j~iaQ=$b@lYjV{5GRcPK|p_G(i$ zofzTnZgDGcGgrCsz6mRLl)aoOz1?h^&iz|g4uzymc570|^gQOsIcd_Z2$P9CZj)a( zPn@E8K66^zvR_xMN7tXc97FPvmLrg zUD+wGUN?W-U}HUZ-jiV}Kl*;2CBy}2)=H#66C zL*2KXx?*0Xvjp}p$!(YPZxdc-qbu^Yc45R8+dCHpa{CRZes{WjDa7JZ+QW0~7uu{B zrOp0PopFAni>FUZ=A(wiM!dq8=A4u1F0s6@IB*dxD|W<8v7>3CM^5@8%eEeYqcW!q z{P;8YO@hMiE<98GAPB8Ow<*EiMjhTTswG zxA|1nEjOVDD^5wS3%Nc)Byi)7r~CoWQx*tLHU4CIjv;ZeM|YXWznExCj_l{Nqw?4F zgmC`+mSCauPa^YkTe2zdYGVPB58G#QHteXdwve`3v~h<(^)8)!U+EsdM``{Sye8f| z_on6;?}8cTd2G(N-(EQ+@Gv^9?C9Bm3rzl%#agp?%4fYk+-aaO&1Lb%B~P_B?m5j7 zDd!>6`hq*Lr7c6_8t32CEeY&Lwm+TS_POj~!WugcWd-?-GdFHpdgs>Lk2m~gK5*)M zz;R(!>9SC%+x>1r(?3qw`ywN^bIDyT&ZFh!s>!8->aTrXMK?JspFEbfDfr16M&s>= z^`9J?BZi6p`mUDTfAYDv#Pf2Qc{rc>vHlR5kydnB;9y_IoJxD8dXp+Av3aZ6 zWAw5e*&QDy9C_q)D(%y4BjGd+QGWIE>mK>OYg0ad+tA==Bid#B_g4+EQ~B*# z>a+OwidzhyqgL8%~{k z{`Hpe*X<=U73&WhJ=6)3664(?#P;9FSg@;ocaGSet1okp`22di>lxeX>)LyrFYOJo zkG^a7Qts8~sH>*_Ia85%)ru?3lSP0t(R?O z(+F#2`#UwxbV}nX$EhFMeL{6T*J!29j=y%Q!+z)8p4tBj4$1fYx}5h({mrA30ZRoI zw5?dE5&k>rbNc3_S^b&s3f~*^nEHh12#cmi_no%V$%~udw94zp!58O?ei^Sh?0Qx( zOJ&jRvsVTERAi-(p8Xc$R8-~3_l?)ot2Zsm;KkXKQ{=284xZ<1(+W@KF%44-P!yJ! zdHC`6tkTVA10K7a|Cr?@*A)>yJ>bXHBX!K`wy9N(aaXRWIQxbLo0wh=xcox5e8soP zUTcHAzRct6c)s%847DrKSLfSHeoj_AGU=%}<3FF7X)C-;4=<>{U~d|lx?-k>)T$^o zdv7&+^?FBE2ea9V#(S8X=KeZxU#`ED%P-xV=hvp}u7z15mu|1D^~&n{xjg;k^52I8 z9aEy#Equ1Bvf)jkj!v6Z;M|lIldozf%?!Rg?c~}M0eRn72IlIBW_J6D-%wPZY3)=O?s8%+{_hIv!*VT3Z1+#Y_;hLgTLZAC+_KLPdjt>!iF-| zusr9vOJ|v0OGxa);H}9?%+kDR_GHu1z3+xVe8Z>s5$C2aa&lsNnY-BS&1tE# z+X@QazSCpK5MdB5yc4iFd)kF_uY5{6>Ygikde?MoXm8>b4Y_S1Y7{biQtkf*UaHPp zSNF{^C{x{$$Q!tN$!BlVXVaPP2HXynU=6L`x^US!<10V4l2-VMUKJ^Fo4)HnK;hI2 zA}mX;@J)$vdf&hG@K)#4$|HPN^7&Q0w;#7J6wDLNR0=;Ql(hVe%*@i3mV)1TOYR$7 zYnz)jePP*ZZr;*~yCmMNeDA6DNGP+XqbA#5VA~}A54_noT7zU z=}U!c)6aA*TX~wN)N++&Y3nYbZ7(XB4wg7=Thqfb`NI0kn%Z|iyqw7vbwM#TZl36+ zg$36nF8I8v7L9E^bfAYT@WGF;e|IjwU3pXR(v4H|{B}K<<{COL*yqUBIe#s7PZqw@ z9<@{bwDPB~$~g!3>PhWWNVRIezmwg4X0fKN9www9F!@0Hoye{OT=L8s0uF;mnu&u^bADCP5@WnY<RH`p`0)|?Jsskr{}SsKUJJ@L;mlHnorknyVsgsN)1=kn=|F{mpd67GR1DymAy4H z5G<^b@$_~+Y&Thd)A?kY!y-A+&m+itew-eKvCAxYJI@qq7 zk<+pM&3g+Y<&=O7_L{VCzKXbqvsmuDeZO}0T>DK@-_j?>+;U`JdcCOk@7L3h?;N_8 zd3ME)o07K^zkNIX<>1fM$+c{EC&ZP#4esDszL|B+$wetCW>VS7H=Nq$2;ZE$6{8FM0EG-3h7N z{HFqUv@30FnfWcP)>(Mb>Bo0&9S+mY%2O!h26JdZ)Fl{Oh24 zR>xuDRNlig5BjD2|FTJCx9?4d+xjZKCu9QTZcTldVm|BB^!^8t0W-sIG|Wl*Jh4p8 zH8ExC{F$3Ie$GmjpPahu*jJ2$1{YgS$?fZp+OBll(jY-;?T$5ShwnNj)UKZ5$?yAR)}06YE_WOh`pIi{ z$S9@SK-6=Wd6ebpNR7{n)ShpMnPz-_;f@Sr<@*PJ9-I7J=Y*}z^qcEW&ROKQPUgjq z*t7+?IWb%Fa{vDMGe5h!$(v#3-Scw;Ee%$E3fSTQVQqi)L)i<*tlqADVS4q=?bdgj zHucB8wPJAo(B;Z{!8~^P*V5Xyx_t{jwO!!(xhG&lN-6i{Wi^-BHXVJowD|;Y!O6CR zoacW^7+IV=yeZXPEqU&(_ZfdZSHJST`g*r#twD=GYkIrx>eca^@~+-mD=jta^)@pz z6EDjtJ)F#!uQvboyEHwvpS|^O-J_W{97fBIxEKEW|3%SbP3)bAeD6Ge7CYtHN!+(@ zja|3qWL>u8ZR=k#_rts1=oXYoPi)s(n_>2R+Ros(U+hYYe?K^0cl4L7Gl%K!8q@V# zoYq~LxpS-Lo4wjE_7-kACNa}Gi>>3{ik-%Loq4|eH_rn`mpc*p>@w#S1w3d%W0dvMMm@Gr%O{WFMINLuKRoa><5z;8}kH4>^y1o zQsDMZlj{2~3t#)|S#@fcz3=%4QEcQ$Sw)SjHPa&u)oe@1zUp{>WSz)#zz{d{vgPwSmp^G}1R zHXcjcGfvo5eG&MmD0R#C@VAQ#7l&Nas&CJ%xY>~>6?xZp@vh7-iB^gM5$`G|g-sKm zHg$15^Sk5%{qH50BQBgMZvAX?uG0Qq<-7+rzvn*hJoj1Uxt-+qnSDK)mGS}n73 zxm;lHvh)&n?P>0XA?Cj4Z>{AFQ`*IRZFhIq%e;t}akF@Hbl9x6F~~Yvxg0eQ@@5Xz2X~P0ArB1CAfA z_;ANnnD1gwt;ww-x*C2cvKFz?l&-?_gceR^Z=s=v(X-ty~qNb%|kXFMmLIXmgh z>t(`M|At;YzJl$>qWeA@J^am-me_A6U0&Iq=*6G%MATD$`mPFF$$QgZq_%Ir^)OUV`u3c~ zF>|yI|2(B&q5kCQAML%b3g*2knAS0~?}Cuq1)aAmf0#_4FsWz4{)^dt6OQia?iTs} zWX{u~1*a?m4z~V(zTyj8)T0gNFW1Itl?J~(yyXqY!kD+3KbGv#`YXF)W9yls7Lh4G zt2XJCY!pk0`0x0?Bx1dL+lP+8{-E0It7l#v-txy`vgpF(SV5~JdDBhLyjo^#m_PBE z^RbAB=l;cbAKk+fxvTG3v2Ex_uIx8jC(IM3mcNLfmb%J#+RA11$+AhSzphK3`Ts)o z0->{I5A#?XBCSA{%>}Kk%{L zsx5CWrQBS>^!AI;7OUMXrI%;TOx?F>^RAVa4>Z5qxIWfBcTvwzTP@n5qF~t?<81SS z1s^olW>0PZT6D8uh8Y{z_sdrtCO)0TH9fn{YTeC{IF|b|YnnJBQ_a}BcI)h5jnS~45zg?cv zaBca%+owz~iZ8qGRhV)r?3bqhqm?^uzv~HRJyW9>Be`T|&ZU!g92xKNEpN}%o$vp8 z$K-7V;<-;*j{a2gDx6eS)b;HX->z2uCFeh>mRQHTm4ANvg(Ke4{-LeJ!>Fpx??s&P z{TuC$2LEK6cW(Xz)*9vOpO@>d$Z`C+Y4V?#BT}LtOJ*Igikh{+Fhg;`# zGpeL+<=MiuAYJmwbSAavm!fiqoEcBwe(5L2#>W^U$-ljOe$!2cO9BOU7xbq%`AwbJ z7-YWH^sJTBiik!flUu6Yr7SiXdFi+Q-=E$WBr)eXt4-6w!zFfF3l2FiDGzper{QXK zn)~4wjX7-bNBaV&H&30kc*~-#Z<-E^)ceTH<;Zy2`e^Br4@-At9yh!tdBO65?rqig z<7zF>r)tC0EWM_0nHF2sp{MDaJ+rtZH~Z$j#U-)XH;?mQ{%U;MoBuLzz~Vc_4EL-%j9zJG zJ>9v7XN8CIx3X0&=KC3r)CqR%?S1w!JX7(${Wf zepJexwtu4er+D7k{Y`57TlMPMxayDd{;9rqrvAa*KkEBB;vabbOnvY>bYK7dEduv? zQ^NUk`Zomp;`t)7=J$?+nNzvcj3ep~IO#>NohWwg`NyL+UGB`Ur7QP}a>|`qdGX*c zxp^nm3oJL(X}d`rP8PK0PpDk=pzy$N$6pP{ljnX@ipop3H~G-`NNrw6nBnZy9~n`^9z8fIyQugJ8C_I=)(#ik#$d1vI=$Gopx_*PH;;Z@2Nzf|m_X_nplQ0^a}wGOyn z$*c*{efEB}>V+Ni;)ByaMQ1J53RoS|nicf;s+DQr+Q7+IBVVOlT@&@hJUDCdRI|M0 z3vXQUap_v&;&I>M`bVC1PTBIYT@&UvJlHq?-1Dq2l{*hDI=t!RSr73WKNoJj?x`=e zf7-j?$(L(|4!oSQ*lhXq@GU8tp<&*aycwsiP*d3>#ZtRi>#3!OT#_fh&;uJSsa2ml zHKx5iwe8RLsu4W(^|IK^Z8`s*()Z?o|<_0<-NRJ?-O_ZcU&@q-SM-+RJk)7 zrbRt{Z6?wcepuvsB6C64R$dFy=;E8Mq6zI~`rBUld@ii#Fn!|0wfb_$fAHym%N+Ti z#7QzRwA&z0-57U2vtmF30SpWbd8sA(SrsLT`kA=}Ir^!2DFykNc_na$Z)!G(9flWI2zng) zReJangPZT21)@59J9XcP@NGTw=-nF8|Ly+|c8lv@{PckTgL~w+91owQq{;&R%f@%t z$M2ta@8`$Qx62v6e^6-VnHIET-a%fS!~Mb=$@>cwfvGmFPn@J&llr(yr0C%sqRPUOedo90T?R}?mX!kamS+Pr#TTaV9 zs@f(kv{JF{(&wFr1MJxD-;n;$`L4m})4$B#9+9+Nfq$1fX|Mhte4O{}{G+TXo@}ux z&haVEuEvrkQ=NrKT4o6HA!)9PA(^K4Gva$v*P|I6IO|L#6= z`d^mRKY_GwERKZC{s53^pOwB;w| zIp!+tmdKx$6fd~ltMl#Et+i)LyiR_tl{nk)5i!-jr7uw~eB!K4`j`1CoR+6=srD-} z>#XiJ5L+0Rz&LlsC+AhO7VVlI(C6~JK(csBXp7?w%OjkeF^;OMHaP73b*4b~Rq{u1 z&}^f=`5z}!CI$v?7UU#rgqCD2h)uF6=@c^UICsk1Y?)Arqvuo1ZS-na?w)QNM5`r_eJ_NT0~$a#6TdfH2!+54tdEj5(8b3v8)xm*SBspmp`A|VEWdedZ$ zFTB=@lDw<8#JKuS@bagYeVdwAh32jfsJni}-9vMG}DeX!%T@2a2$vF{EQufMVFyquNqs-&N3XODdq z+q)@$<$vjdE7w#{f5}aKZkwNbbj!UPH| zvdgQZ+Ljx19A-QAtzd>G&w~UeW6d*6z`-7D(R)~vr+bcorRF5DlN~9p zZZ3YEJzYFWjnk`+3tg6EPM804PwK_G)}+MLsn>JeFF(>{+pVFf`+J{Ev)(Gpw-%rL zejG_#oV`DFr^Jjpixy$8t?E zw~V9tTx%2WJA5-gQt!U{kJ*J~W)mhnn!9T464L~>y*4jqJ#{$xNun=Y*Hkz4jREhi z|4#G&lv!?nzWJE#mi{XYf9J5BQEp^?_lMPKTE;G!L%);{bLDg-%O&UV)E&NhLZ`Jf zA>ht`wG`psOLjD-wD{dyo4nU&e)xsP@SQ8KpQx$5eT;4OMyrb~3zd~ht_bT09u>P46)&?a zG*&9PCVWrvVXV+S<%hLGb{QTg%p6~Iam0RY;rIN}(bDhvqou`PTF7mdLWz6JyQ)LE zLUzgzi-qG47^^mc*#fZ&llG7eh%R458vaay}I|S+=`_w z+cvyBw{7LdS67T5uGst^d^!8SIWCtOSQr>Ca3Ys7=oO+N+G&1wJ{mZX^}Ny#JGC^5M_!g|Bx%ZY)1}U>VP9^+2Vm zSC;d9J-j%&&CR}>)%kUl){>c)CfB6>a*s|t-4PJAY|*Kp4X^H8QE*`9(O&ZV>Gn*i zEAdgjPThO>5;dP0-w@8~zuIWJ$!+S3iCa0dBOoiS4qeDzEXT;ea2D^)y_RG|NKs}o zwA>HR&XEZh{kLxK?#=xhlaGHiKG!YuYK^?~ab4fbm(-5%S!|sfWUc9|c(S5=mt1=J zv6*vA--=wi6(Zs+~I_si3t%`1L?clx^8kE{&M6=r>NE4*d$k9JDL^-j+5+h};hXS3(# zlN$_g+8j_joz~VXdbGFj%%c*K-HSYmW^^yo@A{{~w#dVEqjlFojc+c7Qyk>VnE0OE zm~-)gQP714M>op4K0CL$GT?Ain=5ZR>nvYuFo-01&u`*AU-X7~W{C2(`Utg=$SHg z{^_OD#1{(n%>Hs<<;1MhTQ6+uCr}><&9-I zTeDqPUDzG8$s|4evlXXwta56HtLNrkH=i}L&8;K8?_Y8*d&#N)6Kt)Y9QZ1nVcjbk zXWzc<#P=xc-m0+g>!*6k+RV0^Da1PYlXCi8)8#T=e?(8uF1&QqhI5%)ky`c6j#-g; z96536OB`xa6m!pg3||!cP;pg}-_1`p?J?^53zny^iAhU|^!?oPre)&vNbBq~(ktgA zrUy@+VpBHl2}|jg>DFEIrY`=nh%0F+n8eYFrv-sfW__*V{D+7W*Y%R6v{r;jt|K9S)e=FP) zURY_Zcl&Xt<&)4Wy+!{v z7k$x9kzOfo(IwD#QTT56UYkuea@&*SE3fT3dtGYj#nLCzOTyl>UeP}CPI=>Fm;Lcw zTc>jFlW^Z2d_-79yT4-f|BlWlwc-L?b9Z$FgqrBF`c1Ik`RJvP=s~-!J~L7eInK=d zl)2Prf0WuGqlpX7FhAMsHIs2`&oQH@fV63UGMD;z=?bUL%m_H9_Ff~kY;|gqjxhJB z9Z$HuW;$;5nUng+ac1Qwey!ARD^i7YCUcycqxyeBP@0GC;>|sBQ!L&8B`!VldWF#{ z(LT{Mn`Vr!)rF3wqD8JCU zDc2cQcPe_+MS0fQ@`asPT&tMgrp$Ne(ORL{zzLiO@EQ{OU>_L^p^K^(&-;$Z^iHPe)`u|Ywi2TmVX%J zkMVyD{KGN-n17+5{o&~!KZ~~3FAe$;Zs1tOR30p&^k41Q-Qb_c>=&L@@!7ZgyO9}p z&-Ylj?FT9^dK?sUe6m*f@AQqmi{Jisn!B*KcmDCd&s#db#vfY!!bWw;O14aeC6P+K zJ$D?ACv%<`z7fRS=KaH>ady@L56<&~H=>xcROcvfSj*NkEn%hFETs*5*?OiHs5i=* zChTcZX`E}Cu&5=BY4@u2&I{spm2KTs_xXm?H}Q-^`Y#`S(%vQWcUI6J^DEz@Z%Nj> ztCovS{$acJv%EpG{Uy$?Mt@^}3eP(*|D(=7r|fUxQ$Cp2@YNrm{((R0ZFolM|4#YG z@k=UtBmN)L4lxu|beX(DSXN2Jth*!T`s|FkyE4wGtWC2$`^RY6lTZ)g*)Ob0^w;lt z5f@k56}JA@Z0+#HtLsvAzwYzcKK<$L!1eLLoNQ7VnooJ#lPXV6{4SE!@^h6^zVwxj z53SDkBv&l_xYcpqpDP`o9_pXZ&pPshWBPG*Q=yusQ_d5ls@_`e=wFvAVA$d!lX$U# zZ6jmuBF<=6?y8rr-@C$kI?V1U-zp3$QBb$qsIlwAjvITFeoogqx!)yqi~l>v<4f>{proSY8EopckT~* zHD#XN^3&pLmkOPK?7i#H)<$us6^Ewt)~L2*{r#84Az0%(zsj(q+UbYYK0z0w4(sNM zVgd8^3vKzY-fh?VnES_9^`BV%^3&x!dzM(&=Rc5l+QD!?bl!B{n)3&~PyOS_k^SMY zz&}BIqYqt;^+q4gJO1(Jko|F8p!M(UM)}v@PYV2#{lD;Z{i{#HcYm)JnDsF@_Fr`U zKOfV7JN5oAwy$4!WwqDe^+EraU(x?6^nd-8^;4>RS6*Jivc%=fD*NlMj7xf^OwoQC zd}@8j0Rd%=g95)oU%p;?Xu<@=sZFa~vf`_hMBkflo_XZMj)cPd2XDx3JlC0{bo1tP zkGpxtehWRm>D$zG@Q8=jw7Dl{G}-wtJN-K-ZQJJu3v<>O8(K|!V-oyvV~Nt#Qcf;I zijwNTB1_j+t-u_dI_!?V9DCEmmUv;w=*&T$=XNWxm#Cg}{z0rt%7o zy!w};=lJY7>(le~)5Zw1xr)W}pC8;Kykb|xwuJm{T?I++-V(kdebY@VOO}_`mFs$& zaAxgYA7+_%{D?!&m9DKqGn+OX-ef$jvzP1Dids*r%({8q6Zd@He9e2xgK3{L*94v9 z>6`RRc}LE_f~`IE{nXE%z7IU2US*et8c z`zR*q@M6a+Q#dvTooFqdSTr@?+h(5O@#D{>L{zs&Wr#6t{BqWD*4m83?H6vDyX$)0 z@;O_fc`K$ij%AtM^*jDYCUtI~x%+Zco6UlXs*0p5SEN;a|8Bd{{p;VcLq!{t?>iPp zsP`X|OkEsq{(M>DtrJbD=>n%aGjA_UEcTI?-M&CLGWzk`nI_qRKOH|$NN8Q#cIeKA z)#V=ww4|+{*ezqt`Qe}>d4HO4MoO}B*-qiQX-`<6Z4)_~p0xA0NB@jGp7p0TpI?!B z=}_4!HLhiw+0UHm6DgEFcgFYLj?BKVOOEq#-z%JEcgAsPW?xBKwbIGMJKMhHY(7x* zndd>%yw3|1XMeBQ7vlK&^^Fq!|5w&^>+BY5uRC%}_tla~CpLOyI8&IoA2fvew4WI;LY=%nw1u>3@W~!`qlKCM@%ZU@Zo{-3LWz=vDJ3%6JDRo zc9gTYzjlAo9|xV8KKrlwP1yD5L5WYOr2m`y@1w5T&+*BAb@kaU-?~I2l`~mJGv=M( zncd^Q>1y?@`n`6N$JXxXb%@KCN#sc?moR^2)N;2?hr?SmkMnVw-ll+6hl858C{Em< zGwIfbD-T;99NPRnC_?PC&_UJD#)}>-s{9d@s>l2I?2eNYG9q53Mn+6K-L=8wgqO3_ z;Z0t81}UWxv%aLAt=cTQ^lJ6?N{!bcw>PW_T=weGOC6o;s{y)~tioNpC)>}7|9tq8 z+S`&@B@&zTbY3qF-teh3&gVwuxeI12(RZG&WjJv+@50NOvnI`r?l%8=(Wd9A?Zzv& za+2@J`1Ke*l;#!*s5NgX6q(%g?&tM9XS24aPG66^?kXufSp6Z6_u+R6^j!zyXJ*S4p5m(10tb59kmj1fDww_^Ideab!euRL9$*Iv=J{o&iHf^v!Smqj7d zqc_g)GsD2b&s8wiOm6<><^kIqRdrJe@9fYun6K#->dBR-LoCxH!@; zMBK#x)+r^C<&1BQj;}qEJ~86q-RE}}XgrTO+jKc7$}#FDZxiS89UFg739~sT#-8+; znWz5s+IfHWP5F9QqBpgjf5nfj#nt5x7iT{+IX~&+s-G-c=J^Wd$2G5Jaq7Q4s^l>z zQ|rr)Q#Pd=moLw`)uyTU@ZIVR)~{za#?(%mHC1Y+(&Eid8+I0yy}x+UFxhC+BG&Z= zt&@}HK4(-|T zk#$rKZl5#J`uvZe2TvDS^)rNfUq2hNqaywNwYM7+)p*wDy?L&3{+D(}j^>QV+-y;` zEe~?j&&`{;FkUs!@_Fafe;z&GtIpSZ-<>>Z``s1QQ?gGR=L?2r-T70$Q)kxA4gU@% zMHMMmzVCgfonHK}`|%o8#?>1buRCwxuAB05gVQgzhA(n;d1rqARjX_JRQLXA``-JD zEYE(Z<~(n~RoMIS`dbZk)-~C)+qTSgxOu_klze-B+n4hb8n?M8+Vnk87Q17&?kh*Z zUO~H6+b6ub8oV>D>)nHU2L6Z4EFKyBT-)^By6OF*2S#=A6=qGhZ*ea%Kk&fniDIq3 z*{55p4kkr+Ep80TV%x`&aO7&Lape^4fEM{pW%&y)=AS*xwIhO2{569RU)b`m(pUZ& zvdEV$WV-fjpUvVQu@c*Io*`c<WWWaP8%ufI*B({=`K&p?zr2yMs;WRiqjhpT)N}VJImnQdFDJ7cRpNLV{UWC_ME+(IZwsC4OZocXWh)NP|yD?z2{-< zo`<%q=6fdpF5bUz+3~w_hJqh@I;$mx-_KH23t6XB{NeL~&()9iwpYBL%lcmK&$QH! z-w-CzITaO9W# z0izm$)gP-f4$4Ob-QKbP%*9=EE=lXYo*t>b(|YT}@(+2h`D8ZQPTH~Uhg1EdnMb}q ztc|<6WZR7$@=uNBXD^+Vu`ul5_s4&?6+WFHJneW_@1+UpB6@fCee;ODQZCaiIn8g< zv`=B0`BOjXoqWt&@hMC@f9of`vya!>wz9sRxFYDzWubDet8XV(EnT+Zjm5O{cgn4^ zcKnl+{lICq!E?)_$v)lw52a+B?d6gLYG%ECrT=2mc>_uL#0I-l8-D4`{UBl2l6mW= z#m@O#a!lL2l2~-zS9!1gu)E?wQRd{wm+CH+N$zZ0F2BKV_npg!ZMFs%%vmnK#V^0u zKQsP1_i+h3`9=J7^SAWhm;Ljn@pXTHvA^}b?zjF4tqy0eElB&#)HyY4o13o8>M6S% zUc0886bX}eEV-)`BI`amDn9v?_}A=5ANQQI?T>ga`1;QKdHSX2SFin?_1fmaJomMq zXPFt9MDv{Ov3z$u`nUH@r|Udxt^2lK&amvemVV(Fn|bG~y#JgfJg(PV|6Y!$FZxvS zU3t&5_K%ixTy{U+XS?F@FOgLrO{8CYnq50@tUvFl+MGjXHGP1-ltX`RR4HxQ0nOCp`gS$Ov$roUTl?FoPVdq3 z?k1})?W_J0efCRJ>)W_LaC;{$?tSW&lk}*jX;RZ0x%zW^jb7_b-u7lwzo6=of}GrX zHtAi=r~4C#51-gy<oRVEhm;7{3R=w#0zm^I) z3%NP1nm9>HW*W!4X;yc%yFcc2KB`-J+&x87Zpzacli21=m};TgTj3b?So%^+{^_Va zD!M;5Zg~`%IeEdF>8zJDy;GY_PPksuiM^yWJ>pz_$J9-1*^>9n4Y#yg=+}333O@1K zdB|%b*Ov{mG!@BqmnX6T!Yqxt7Jei)8cB zJK%9saqX4mk*%k7UKuYrrTZ!|$gaDpWr{rGz1M+u(g{|#9%jA%B2k$8vw!lYRNsk0 zVFl`;DTiJr@n@{cnC7$iyw~(7wq?&w37Tv-l(@Sv+w)$;O~KT4afX$@M13`8e>@d* ztmE*FWaF}%J-59iSIZvDKAG`!sjS#_BV)zzi9fThoC?#KoSQNA?Tbm~i=wLvTfZc( z{*pYM=Rw-d&cvN^zf;ZKp0e$U{brzZujO|N$NTBC?{HmrO}?qSa^g9Qw6nG5#pm;q z_P)Ef_s-_o!N=|{-gqbKLqjn4p*8D|uZ@~e+}QhDLR0!}VUXFeDPQBhw?zLnvtA#) zQ22#>7mrW!@so!(y5&{RJ@sA1&qDbAnG%!UxvrNd&XBttxK5$IZ~k(ff6ME6L35GZ z0#~+i@G&qHs^RN(I+8jl4eNF0=Vg}ULk~$<8{SzTa#i$So{_Qs%u3D~trm>TC#I!3 zu`pfPuth>pc(OyIn`7?pNj8(+)juyY&W~`}66P8`{Z`i2h}{>w7IurS@`;Gqpe2&E z_G;G4q?hrRzU_X$*XP+;7GutTpH9y$o?d*e{G9FcJD>Ibe82LVVcG+GN1elVtl!xJ zTWXg^bp3wvf!FfR`UkTeHO_rvcI4yNs_^jpcKT_1Gsi4(n?{E#D1`lC^X@5I#SOZw#5KHAi& ztd!UO(HZk^_GO_pq8 z|LSsj$DP$Ir+Omh&+Ov8v3wHKVS6VN!_($CgH!D0O#&Li4MjnB?+U^N) zjHhOlEfY^}%$&YDE^2mgv-PGmvfF0v=`5NoICan5xw3P4r(0V_O;|nY@dhp(4UcAr zld+t|6{{7SBTF{9MJzMsJQjR$$vr{o3+2Vjo4Gk{^VHUyopto?Dn{F^%-P1;?{;pO zX~3rc`Q4dI$JcT$uDHE^$%d3QE0?anZLFWb*TmaeRqHfA{QK;SEAG8FomgnPyw2&` zn(vp{LK6Z?Q;Gw9CK}G)KH=+&k`Gg!UAggQ`^9S;Yc4gu);L-DA}4bGY_Ds(<4*T7 zgfCfi^xK^kky4LytS_c>&f@v?RnBY`cb;KzXWiWGryAy3);-Xf#uxIDbxm@jZ1J5oK?yIP%-0aj{#Yq$ePH{7+*f<2cZKPM7m6GY`NOBredWot z@6thTB@VBuS&zRwEhd`TqhYb|k%}Lu&de{_%Cf~#M^{()zN(EqDs6H2_l%&M(}nJZ ze5~FRx<_7Fs$acBrMAe^X_rdw?v`Yx)$15q9h#@#)>M@K zGUFV>3ESwWD@$ieZ7Jfaoih8Kr+@IXCDnhYw4D5BwBYDt8~%RR6eZ>kKmu>uEn@AFF0>e=d?3WBpOH&fTEl^DfQ!+H_{=^k*+2;2=`FKt9c0sjzqomxkHS<;})lcm`Jz?6L zi{;VZ#7(2cboC!Lcl&kx1cPU5%E`hha+{BC zD_-N;@YwCgh0e?!t)KOD9L(1}zSVmtP?j~KfA){phueBS>3L14-rC!n$#PzyL?-L8 z_P6>>snpCV{h6BT0Sm+x?{pdDot_l)+DmMQr0lvUV*gIr?iVRFQC3ONzc=sboAQ~@ zh5qR3ecsLT^7;F3%j5(tTV^gd>~-_c_j|mmi;GY2-}1nl&Nufxo4i8nkYvdApNIAp zN0dliy**1wdB(+Oo3|g{H+hBTv9*`hY|!sreVL=ZHn~IWlU>95f@O}5@@dY;lXyO@ zYp;lBGkm+?;9;{zVeC`8BZ6W}Hg8xd7v%b9cdy_3Wvj)Mn|yyL>CWsvd&8*mG}Gc~ zSJQM>Z`GZh87+2Vb55Al^(WEaO3zK&a%NHL?v5;e-QBaNy2JmEY#!PVf6R_~QF?b`@r-h*(%ZA#40cB=Ep08nG$VU{mj#>4F$3#`e;AtI zDn2`1cjn09Esq7C-CJyS&a$tM=UmvLTW%~*ZMM!WR6YEY@6O94tD~2->XomQz2#Bu ztdjc2r`2ev;qkUxJr z;@yV7(kBx-ADr${P7IDuH4(iTBCk2$_iOTjX%dMoCnLBo)|VHqopNclWZ`MSC2xd| z%{^#)aL4ai*~jBfX+6y6J*YqF1hZL+stm{F6~7Em`1S2`nAje{$#>h}`Yo?)BLgUk znXz<=LL`LfpX&;D*B7Q5cf=N{&qd^X4Wl;jVSb5ZS|cjcVRcC(DU zG3|@VeAf+~k>T&6jbAe;e_SC^oYWJ@zQ=`K=5g$$Jzhz z{pyIQiw3RN2>dVN);ORlc)z z!lQSN@2qbAtVo+K{w%JZ)Aaol*3Z?mEy@zjQ)Yz;{lELoddu~1hioB3`tP?rsC&o3 zz|bp+uW^Ov=3@Lq`jEyI$~jcwufsz^MgGT1JUetIRFL)Q(jQHU0qTp}SN?nus*V-*+Ca-(UY*_JG_S-UXbsqA!j+u$n!dA=7vIVT%mg>5aAxiagU7@08Jf zdPB-V*3avrhrsdztB$~)lMj2k%9lP_(^bs4=5Te;^IFkebB;5wa5QOYn2Nhn?qi0iTuz z@76wz52d#Z7bf`5PwZ?Asfkf(`&u}8(keUaRkM|=4o&#obK$v<o32n zfDcz(OJ5;pzn&^P~1Ja925V^5DINmZvYKZ%#XMVNr0K>b=f-_`#qfXyruFUB}?8_*UHP>(QD0Rw!Yx>p4F)xVFfDL?}fGtJP%lA zkkah7i>vjL3H#!em;GiMu0EQXRH-(pFYoBAPfZgH>u0@w?fToge{J&P%Sxwi-I&(e zyPM%&+idPFM#r0#UW&16Zw;)dIww^5!*#`?4=P)4GF@_Y=s#+eb6dnJ^Y-SL{i5MJ ze{)Q=E~{FdU>kjBv8dLIB*&$X|5s{E^O(NX+vx-2!_${FrA-xQ1iW=}k+Y3>TY13$ z$dq|+whJpUd-gS5OX?O$o4K#(=c&sd0}YS2TFk%XJ1exk>+6%rQVY_ieR?|IA}c(g zx^eG`O{e1SJU=?YIq_@K!{bVOV{NOZlpcL>m2+Rm8?S8v8t-lI%>P`qTaAUky5YHp znEd%`f;kWKC#Zec*vzl`iS=>*G@+jzJBy3c@(R;?t7<-2wC$8$8uKtlzK%)t54V@x zLX$VuEc0bfJ$X?7LTY>An&$bB4d(JFbUa>hgfk?0!l%SHXB>pNc5j%yxkUKnj-RtQ z?9M%0dbj2E(^ZbAq(1L4Tio=xqy2iY&u^2ZTVz- z`pNv`iZW>u?mNB}<~@i%?&RUsV$@l_{;g)1_KW*JMY2Wi9Ou>3616#gt1;F;P&NGZ zx1U+Hp|6tH?C(#gxNfs5GGI!`6VFo`oKHOeOks)j%>E&n<)(S}1B>+Yz~3^ZZ>F+G z>|XyyQp#<$RQBn4376&h|Ly!U!I3K_W!Bf3TdZ$vJ)qmS-SeRAvYP4BKT2x9Dqi-D zwd$kl|NlR^(m(L(?qB-$`<8!wEO(b*aGVlxiBO)|4xX2ZTbE^H!W^IllHi=>`V6M%*V@gTPFoA;9Tlyp6TV~I>Di0@ARVw zv)At_yTTq<@qqDQKV#<-p{c*3I^|nu>@3?8ogS(>b?MBV*NvacoS*x;{{QditPQF; zQw=(!oo5_y&zWX=M^CZ6zp}9Xth%bv{7?7NbKY%=Ox(Qc;b$SYg4G?>Z}w|EsuRqX zS(jb0V49^#Hfe za_xe}?@k@KQ7bj0?e05^wvySh=gXQ^ZaiR0KAT&y@b;3{{AiY$`CjS(Ew z(fjJ+Gw$Wj=5ss=+oPsw8@fGqr{p&2OZ7QsGE47n_Icj<^7fuS^Wua3W+(U51ZYXY#J+oOEBvlN!7r=}Hfek976OxOMN8V$`#_VkvQoY`P`e1dpE;BlKQt92V9U3zED z&bxm1LfNc4^Cs4%hRV*a(3oJzW3{$Y_Ig2R!pkGcUe`Cf|Jbn6+xC&!{)2lye-ZJS zWjvkj;i-n-6(vHC{G*RW{$lpMbYH8T=lje>JlmrxU(Nhve2U*WK>NOG^unpWqLH7B zx26khZLLkon*M#_T3h$L_HCbjYy4T-b$-HJr+IIrrmjim;16({t6*;6zPnhEhqIDD zK=8DHR+6G*)r%8Jw^9#1C|9m^iRxeBB6p*y&z&o#e^PS6!Q*nwwd)%iZ{E6pA?$1i*k{rWJwC%OGe?P7~%N^_ntrxkLBCJEZa8_ss#RQyCcbK6el zDI&7$nfvlP-&;R2e%T{+rE>N9#HlUog+3QlI!8fQcw+2ei2 zUT|}9&aKYe)Rj}iQ>;&t9&n0 ze~C3bmEd2L2!zMJ;Y+31e) z;k`yR5pBOyet0l^Z@NNw94aSJbs-V{C`bi!;i7q8xG{g)nr8gu=>E@e0RS@NlE&rI{lT&w&S zt~_yX(%GIKj{PUM1*O%yJ$omVy8U8B=Nd~!A;E|HN;J1P6$cjin@u(-wiL`QEQsx6 zkF8!ib=#ZQB4MTPJZ6`@`LIH^KXT>7hcjmS^`)%Y@>bAVb=Qp5E7f05e-pgo-W<+wbKjj>&UPlJz9u1Jx%T7^{`cMKx-)m5$*MkaN^{MebsN`AP1wY{`pB+BSEoPR zbmyVfz)E4wD<96NWz-Ce>Xba}xmcHip!%-$^}dLLI$dbTLWb0J6h^(ChijItLm z%{i;hpZMK>oxrONZi}8;#m#hyU3$tZQ+Kky<}|bOUa5P}JUn$wInB&23`T3a z7jxu~#?RgySb1Bj@9UZQL+-!$k6%QC;-XxeaIvO@h{YJy}E z+pm@?>!c%V@BH_zv`S3lt&xj2_|U?kCq7kl$E^cilIsp?F|TfoQoa(k@LJ;3LtQVo z3o!pKnB3@mL+*e$Zw+U>*$0(cK(m6&2QuhO9SX-X_`)tMA zXJ-$XyRO)1q{DpvQBULZ4|^KL4Z_qO%7~gd@<%SOWU5;q&39={a&*lME@^%D;BV(w zbGAOc{O5^Z2r=&4@C$H>Q-g!DBJ4=3z zebC)7wL@IS1Svf@g1-x$J1Gu6VKHn_US$ zms_1n9-8ecu#S~jz}?xsQ}%zM*Uxm2%VS$oy_^>^3R`io3Ylo;LejNc+%dr`@COWI67x9UUUz3=(N zbv<8d)miV_-#kq?<7FMIt~ICVtB3hA7lT8O9&yi*teL~|LF7rH5%>9wFF#!jev}(u zeEOxVV)^!F-e+QayV-9f$#j?R7MosLzOnMc5zd&apQU)t^;{1Ku3hy!lKVmCE8_06}H9Mv}=E~vHq~*IqyYV`Driv)|iy8juva*BNhGd+Kew+$8JYO zrs+?AqW>cC-m!I0U*wnFPTY}g?_c`$ZSsuBHy(<6zvR}%Yi8yp@~ib&M9+6n-yz8N zfKhD85=*UyuS^m8A&39`kdW%S@YU+nd%<77-^{ny=(Krt(B1Zj#_dO1xqoc`wMiWf zSRCM+v|{C@3;dZc+)cjxQk9naVlE=+EVyvi(SYKm3(YfL95?wg+1q4^!IN0ui-ao}Hi5eok5aYn+y4=7gMA2P`wcBt2i^dFcAQBB76So-WyW=YH!N_6N&nbk5(X zR^NBDVsiO!{TDBzZC3A3xv^jC=9lI;9`>)66IX36n34S@=BkmSQt2M+OKRUQMV@)p zx8<~|v)8(A;U4u%idQ1fOxw3mvbd#4g159k>srjh^N+Y*hRibb*Kl8Ua_UU|Ey}_d zdsv+;jn1w+iezpig$QDWVxrZ(c@#z-rVb#iX(JFp6`0~?Ul#ucUoU#z0W6c#;dd1_@-4$ zZeG^le&UUW(e4OsRvG1DKgrGe7`o5wbWJnQUfxh=^n9wPnOK4C%+IG)W^=tzDt4Ti zvZO&{Cby~a8!t0)y^^?F%vlY-{1*LgF%Inhhm}m5|DOv>oV)6nSZMQIofUtz8kTS= zt$kGx(ps>d>#<|%gF;hb|5a6U!gwuKOMQ&J+F~BUlD{(TkDu#D_p5E6v!>l!Hr1z^ zefDV%^W|N${|dcJU|#!-^+R^b&y%Nwrp{IQ9GL_(b-DcO#0*YO3>lOM{+uKzh1CBQ*H2m_RRP5&+9XMx9GpvU+A{O zWYeatOM=&F&HcFO*{tA0FUpkOg#LTDHObRE`^aju&js66c)smaPd{zcaJ~J&bqBux z6K~HB|J}TEv*+VOOTMRNPyeu4b4I~urOsICleg|137OY=cZ%)q!gcpe9~S;@j+}n< z-9-D%Cs#RlbBHHS)!LGhwe6JU$5^I?%>jWf7EV_r4jJx}?v1wPyrtql`<~-_@CMaS zH}^Z;U|?V9WfoXctOPG2PMrW#Q_Dzh19<`>ve%f#`O@b;@@H-fh|J{Wiqt`PZmr ze;(c_bds>yuenX>|HhyVUS4xGwO7sk_@TQXo>|>(daAdU4}egXa^wfPUS_(5~(sj?5AgMzObZ}1V_ zLiaB%!RWP5iOm-d7ihab`AFHL9Htp60R_$)tyX-Ur^7XQmpa&S9h|UW!Ip_pom*=? z%wyk2y)Ny#686ehzbbI6{nDvj6T6P+3fZrEW&Qf=t(z_r51*aWKeuweW%08&xBvgE z<$WL|x7@H#+F9aoy5^bX7yD;#`Vn(xt;t#OP36&NWDU!Y>U2c()Nb3(YQ5UuIjmqV}z5m~`FATno{4HmiLaU0iSP^ISN4TJq2BB6?4%82s}!cyxA% zo;}k&ZLz%RD%H2PhTdl7My}g)Zb>goKWTMG=EMHYGoD>_UcS;ct#Zwq%*)riCuM7w zw*H%wV))K&-Pc_^m&%)$IERaIi%lSWq%;;bgv)vvhd}wAfhqhyD z&1$dOt((lxre5CU`oty1*6P5?8`DkC>lUlcH;TR$-}U|U&pRdlvc@lVzt&l>d8xs% z3Ax3`b#5%%9Gda=QgY8H?%u4!X0_Sw+fVr(_?mZMVO7qSH@CLw{hoLw;Ou4V?zP9f z*YDZ?(|@$H`8~2_UVfxTp-BGGo<^BvyfGri z+G%{3_e`j8d}pS!dy(zDr0_gT=Kc*@X}#uWUU=_VQ}FY{-L(ZF0WL- zRO~tV?#m6HX~os=%ifo^FQ482bNeTY1M=xV&r3gFzfr!n$b8OM&)(*bAqITS{@jtb zzVEzsfMGv_@XzT1KWB=+IKAKLzgjr6{)8Xa9kZ95y}-Z2e|M9jjl$v%W1;I^$3#wY zq&bD&d0N}nQ|YGJryP6fWM7HZgoxJ0tqzwmEZZk}RVj&7dHH`l`|Q8tC*GhbUMEYI zbvpKON?Pv{_PDT4xmDffOSnbf`pOSy*KOGxcq=mIfcp}S%zYEmjB_o&q|7n9dL*D> zvge%dyp{JSeV-zp7_?mE!?Fs+kgkf!ivDSpX965OkAHXY+kWz;Mdai^Jt^H!a$nWl zH?G{K{;6QLjf}dr%5IfvmFp`XfA^X9x-)0XNw+zFm`|Sf{5SE*{1u;z`%@M)^g9v6)~T$ z>z&P6QppmUEAyL~8VFl!G>>7_R?uCCy4|v14jo`V;w@^7^v9tjbrs zHY}R|!Cg@^hX0Y>UvS60?r^NiMrHtU-v5bIEEHwJd+yZ*F{z^eYb)Q} zJ??w!*;Td7%hQ5pspVeZ7a#D;%TzVDvCS!()$C^Wro!_48*kdg1RWW-YBV*>TC|8M z@2HdGZ;w!k4aTolSUi^gc{tELt;8*@#LZ1s{)hGVdwX|Re>dAU_e|aQn&zK6VSFhb%%Q!|H%)DlJBNI zwB!BWzL7(I;={#`I#Zt?KV;Fw-qdmG^J7OH{-oB9`5Z~10;`)Ngpb@(xW>BCu8IBQ zNe;O~hmC5y4l6IJ3^|;f7^Ans{X-`2e8DT{Po+4uEtZnI{=u>})6L2*OYPE4-H#Q= zB&35QE=)JubaA5d&4?`@^lk;`Z3#?tvzmTu@@c*qJ4^oTnlsV(5!b5lg$rHw+a~w* zo$7AOQA+(X+em-U;;(+K$AYpKH(b_uw)dq`Me8!5+u6p?6s{{CJ8QOWvF4%adIjz} z6HBfK27H^nD2yX!ric2b*&^4<#LDM+^s05=*5}yWvu0wa7{i*I$BzCM$=Wuva9u%E zyi)F)b4%HJeCl%)Jbj(#TS|Dp>rNFiDxYF{^C8RQJ--&+H0pG8+jmaqX?R4b=IXGB z@{hYk>u%;{m?Wp2ee*CdZ`rP36JBSxZO5ZMxUI$G12j!9R+gul3eNm`CFb8HUCoQ% ze}{}uhGYPeR58Gh;@$s zSo^Z>=(aOAH+%f9J+MPp+}r5Q*}1jK8$U*vNP6?Te&^|tXujFo&98A~*3HC~)3b^b zT(mYH@^JJ%x~cgvo8!6{dm65AuF6}u%aWh(__4OPmoLPuxxCSE-L45ueD)c~k7?=a zruvKATD~Dg&z2=G_sra`#O0+4o5RlR@zzl(SSEfm_K(i_*^{g;2D_!5*wD|ZEGTJQ z@oI9Xb%e#!*?qH{cTQ3K=p*%Mi+S#i$(ww`BeYto`FN!k-)xyFclkqQYgJ~P+4;Vn znUCh#@Yd>IpDd^4zhkZPEIW%i9>=P=u0)xcZLwCH7+9o|(;s6tG3C|H2|hj*se;vK zW700%m^h*ATEsoYX`Pe%cwb!nz$$C~!B5tEqmR4D`wNxvMG=itt-?CDL@hB@S}U44 z*W>lZpv0%DU({rO7cB0ZeR1_;&YHl((@Sb3{a;mZ`M>_b^+~Gl@yt1z&71t?*2{?> z?J7%@t)441sakp0UH6q6o(9>d_U6fIuG#T}yG7kLTg+>9XYak`JIvxAEz4VAnjLj3 zKtrrwJYt()X^YlRZPTJNOe}Av2F2GEX6(HtxwLq`X7)~x{MFC5%)8!vw&`r`Y?-4y z2Wz&7J$hOEWmawchuh7)<Xx1@XNo3m4He`j8@|Cq&@ieQZ+)>f&f zKY3T&JR2-kvM9=N{x0rM+pcG1x>safo;%~b{_{Ky9Y=}KO9?*=<5X>rRq2(_dt-8~ zc&c&y+cVcKK5so&GuJpi|LpC~-Hg(faVI17zlPRaE1lc;>XlvZs^ArM2aWc3CEKpD zyw@Rhheh`H#?H-Rw;98ejT1bhH%u*H+Wod>gQ?vHcFx~GF)<_257oGY`K zw=zYya7Ubq){(etR**1d%L}gOlULN;du;RK^&h>wC6{)7+i|?|#`VhO>x&P(p7W`6 zA6xCZ;;FCK*uE}2_rvP_r&PYGnfc#K@4Y=O^U3J`%h!93Pq%!Ny6^b)pHcD8I;Q`u zi+}#QW@f4WXXbt9uKzZ=UO7|#Q|Z0eR{3d;r+15WehbW4Xv5EttbX}-P~4W|UKgTb zw$#OMaS-&KoT+*%Fn)`4&Ba5mTRMESFV6em`dGZ9S#0@MnTOlng$LL-E_*jUaKHDt zt3v<$l5c%{mGnUR1dk1GZ@i{eU!vH&jTfE^IzGSe>oR@u{bzE2&B|smhl%lTa=g(K zZYisJi1n~uFlPx3$D9Zw_E+Y zy`vzpv*c~M@rs>aMY6j0YUJ#l_2hHT$tEQ|9~MI%3tjbh400)^o;|Zz4HOy}CvK_S z7<^$*?C0Apb%MSXCwY}*V}GQH?~`Qvy?4U?>+?Otm137zDX#h~wAX3T`w1`ZunP13 z6lQJJ&>e$tC-m0$l@g?WDqx3+5N1i5r5#VwMb^uk@G>MK*Hh|s&wu_v&+ ze{B8E*HzMKqt(T`28Zp0c_(K~nVr|vH5B2|9^JQ)%rx|pW6OM?pM6ucU1a={0`~=M+E;!^FOw) zm~*qMnODleB$Sf=y#%9H#nypJtkG1Y{X&p#S-?~wPoqr8j=;-LyryeSd5!&&AF@PE_j}aEyEXRyp+$e!ZcV>%(toK<+>_sGuWM_? zdBry0_+;Uh>OIqF!g1x0b2?hPBWfz|xTa>$Of~3dnVOqAZ4c|Ol{xyGd7c-VPThQ3 zN4c^j&~o{ip!17op5pVCEYx}ZDWAQ2rDWn%r_34anlgeFbwUJPME_fceZ8@2Sz`aJ zKISa8N2?f@WgSVp+EN{AEEl3XBf$9Ml37Pfwj>2@eK;rU`06aPxZvUs)mIzMug3g| zJ$v}}E2Ge*ViB6RkBF>EQ@nF5e{odN{zk)PYi2$DV72MW)emyN#Ql%&SP~X09^}2! zXzTXq-4)rMbJy-&=maQ+@p3_x=0-u@y*1vrgGy)tGt5@Y%ZNYSxs3`+I7# z&oncgoz-bu@*$RybX*1v zZhZJw`lh|tw2|BM6t|?Y=jsTB<;uFv+YbDl8<6?_N4T!-{+nDjqSvA)%D;wkvfaMgqT0FQvWKx-cn*|L=wC{VeOIo)5Q|kF*mxvBtf0)!bVjowr`klw0}3 zL5?-7K4kL2g*~;O=dl?7TI;{^`>~0ulC=DIbs( zzV-H|h2OSbS@Uwr>Z`A|ot(pEeKs!WuY!<3Xrt2N*>w&~q4oDJG8yyO^ghy~*$>(-{cgTJTUWpT)_ouQ{Djs@*;3<<`mR08nuZ@_SQxYC`qu;8~cVqFYeHJz!XD?$HmruTUlqW4V=E#}@cRwzXn73T- zS;5Jpsmbf4Zk_+wdSL0pNZXe`9Pges>BAlM?&s9{6a!7n`PWMwO;>%M zZCIZF;CyRyzeeej&2#Pd3R>FBJwn&bSBkCdKcn5YY59r2i3h_oo=;eMSLKPM+J;u8 zRVufRF)a??ZSq58KI1iGqn58d6GY_SX>0CwcnM=^XSe{5d6HEX}_ zSE!P-?IM2(lzD1akr{cbv8>bXqxIW`S|50>5(>HtJi0oV~giEnetY2r=8Fo zIkx?hjAGB2)E`VgV|M@4`@o8?e3Mnb_b4ypl3SW|-Cw%C>lu%D+s|y~KTqZU`)X%J z#NuV9y{~GVsYR7`+bY+SMM*r|M=~uoEa^N-|iKkw*}v@G`CpZ{?GgEajX}b*I!@6 zd{RLzJFqc@S7}4bETLC%3xk||uPgQT@Z5~jGd4;|eQYP0BUxl*Vf3WgBDDK##eSaU z&K=ht@tkWj5Odl-L7pSAn!{G{4aY;b#F`C!@`wJGRxt3N`tVS}PH9ei(~lK7_Bw}^ zjcRl{`q@9OXxlX>bN(i^Gl|K!t_VoZG4hlAIAx;WF?X5UUh3u99MwwhJhPqpGP5(j zL@;xPcg-oO`_(b`q?G63jYco$u;nHgUiaxqGclP^e8KBt*G!8!9u$^oljx&n}s|c#ZsDMdRtllb&@XTkwQ$ zNKQz2Fd@TK#W#J4gwAT~ZBv_1uWE`BOj3HnH{GcvQzl~5(?==1Gk^QdG_!qpZ$<8s z;+s9Xa;7^Ubvs;n^l927j~sc;R-t~?8ByHoIulozy+19jDR=EoV9C+LkAt7JY_7gt z$Qvq|9<(lWrsVvn7_)f-%I3Ki!jsi{bKXWsEng~QxLSPrthNhFCeAK#l+$$C8c_0U zOQyQ7`DV-Q({z%2g(BSNBny zl%(su;FfNc)vpbc-MkiWwLdTH8|^M)DBJ&7*vhK)mrCB{i>(m?{x2*Py6Yr&30~hA z+a@PjcA`MJ%JfZ4q~uGB9%ZX{hu%8ctb82&V@u!p2b-fGZ@ z+4v*VBQm_5ZL;Q-?OE~i$0m+e@AoSoYgf1(5C6EPZ~eoau0nd3Zn)K));huc%-zPo z<9ql0u(p+n_q|M1x$Kl8wA{>2XJo$6YW}p8_mH>DW%(i_Zi{!(f$~>2l((AipM0rh z!+341H@t7;*_Zg_ zPWH@>&A6L-YSYd)Z1W?{7BB3{tx~)D?d-hJ>3Rotd4Vyz=Jj>PxE^EYS2i5U^0A(Rt}276Hb0p9Met=~;cj z@u=d5MfC++lhV3_VxKPGwSP@f>B^#gYd$&NiF4ce&#Cj%%}uA?>#V*Lum#R}SB|jcj-4|hb=8#{%C5&|)h4%}s=5@h>Q6+Z|2vJ9=~vJ+9=`MvX{=WS(K%9@zF@w(v5 zgRgF6cko;cSuuHkcSPyJO$9qS{Mq&^G*z^T%|9AtvwThd64tr(?-zaLYW>R^vi+gP z?P)GqQ)Exresp|)ta74plpvp=}@~x;R#2x?osOsngD$WwVOAw#L1v%+aXWKe>+ie)94?XZ(KFZh6dp zqeI6#+iT7;7TQ@v}xFh&njk_Jh!6Tck4Z5TWI#4YYUswS+2Rf7uQwhJhV3H z{(UlLb4R2tclVjCtj})$NH~);<;*tMGi{M?6gSrjZY~rHG`cQ6BYNhoNR!Ds{S05* zoc!?Se_z~f=87qaEOng*b*>hFW*z*)oA@i5?PYn(+xL-w>J`}jpSbj2_|gyKz#rl^ zE&CsF{^9k1`2NrF2l6`0>xF*(KVo?u{U?N=5)OhDmeekhJKgMm%(|;UM z3(;ElW95z@HPL0CKGs6k(Eq%>)Z`^Q1H%&`d`${x+)awyznoFUC9xzi zy(lp^peR2%wYV6zMR94^%W~mRk^g)5Eb+X&Q8zI=Qdz_!$ScbAsNNPG)~-yATuoj* zgSk8}x4iV3;S;e+)HPCzX;apO$LvR$>spe#Pgp)`%>Nhos@C`=6U&6h?K{7pt1iEv z_V3s4@AeEP4|WG#QFwM-tAtBS?|>fTu01#2x^wP2>fO(psl0uP1Ry^_IY?jinb>SA~QYO-nS=>E}J!{xsv9tdM4sQ7V>Ttx*Z-|p%#pZTi&+4$tZkNvc6DVTO}_SPOBH{T$M-x6MH9Cf3E&j*MLKXP{0wOrMk zaw#y>KaHnXr&pusT2~p@jqFoZX2~dEO(Rw>^({@`AcisqND z8Ov6GymO)<>)R>jOe@YKJg$DwgEj zo{gBbFqm6TQ98{}U1RxWp3kzpnUVgk)$G2HJ3N>@e^>X+S-Il2$;2r;{ncu1;6;+n|XQ)-u|^xIy{bo#ZTC2Gx70k|Gprul4MY>)pta#aFsML|7sPCwr ze(>0WmS79r1CpGNe|Q~=tkGS_`&?y?xM9oz&bCt9X*p3&jqBt%{d%A4X^7;)EB`G=GI`UGLseIA7>F`{vC!f|ZhUUbdz=8ZZSc|HB3 zuJh^tS$=J&Bv0>VYYSoTPT6XuhclWOe=D$x{QQNBE84~7FV*2&#*Q7&-HcvaA zW4ub@Y^&?LD~GjsdzL5c-Zf)Kg5t|n&okB3x2#c^`^2}mQcyK3W-%993Ep?!JZlHHX{V-)0-FU+xN86H--v zd9z%;;Pcxqb6bwvb-HD#A5i-Kpz8x?0pp#CONBqU$SqJ2{3$B;y|Ma(-vRMR>&8pg z+a{KC=rxN!n5*$LSL6BH8K)nwc(hyKS!~4d@?_?ZEC+MT@3|T$1RqMB?z?ruxgX#+cO`f0PD`3lV_NB{yfxs>vzNhCl$eZ zm6Dj_N=`8;Pu+`*9k={uNIiQu==%?`KfUjE9l!dn-TPC=ouh|r#BSbNo#XwqZ>hu9 z#XC%jsZhfjP+-ta@i?_+=A#QulXbv0p}c|Omdvt{0MvMhdRRU0YAvHkYmgD3dg-Uc5{ zuztCwB`?pa@c7K&DMxwglRTBa8PAHJc4n!+`s9nZH%0%yv$MA?y5smer5VSQqMwyU z?>n@RS-T_uX|Bh1fp>d&&);hQ=&|VH-xHqYlP<-+U6wQ5w2C9VTJGPW_c!L1EtWsc z`Tn59!Mb11xNY3-S2P}fd3l=poa6jvWt;X)v||5bvg)Vgl~08^&(klSJ)g+G-|MDr zJBxjPVjZLV57(YcHzoGB6xK;j|0(+C$a>%O3dYpyC$pQ_lG&}^tlJZLVi&h{?hmLx?d>L$J9oW$bdy)~Q_Ay>ctu>9`#>7GxV zf=Z&~HO5FMCyv<-j4c8}9BPc76MT;*rcL5eF)kDnD=%FAdmZc6cMqC2u?vW95qq1p zIyZM~>Dy&%uikQv-hSWm``$|9$v#Zm?*IS)^z`2Ecgx@Hd_J%G+V8wi&Fkk?i7}|1 z+UqCLbbi+cf&Ld2Q{?A8epIQq@AOe_tGfQz$uWCQ9QBr}i$5&CLqWX1;G?r_{gXrT zkNtlMW6)PVT= zG8g^7oEKznncdwuOXA23Hse16QHvzJUW*>yvtF z`O74$&ku!T=Pc?jdbDxI!tR+d=Pw;y8FT*HQJHnxC5GYRQ+Lf+-mMiI@;Ygsp4f{; zZsOdWtrouGTX(Iv?7CM^%rLRLw9xAOP8V_B81q+2n%C0}z8J;oTtCWH7q_xI^vn+9 znF}`0*tNNIxD1c+zHepnE3d{2hzM#0=W zTsvJNwmd)Z`BBUo! zclXX6EiZS6h|ex9lr-0WZWwOxO1pB>>K$KoePh;kX2*PpEz~_6v%LHD&xdUD-n+>a zOjgTF%h{gsD9rcHvhLfah3$Ipp6tsn-gs1XTi5QA!tLI7l=mGDDp;@guDI*>QD!|Y zxhqGU^(tihpLDbzHOuOJd#9=;xuv_-e4;Jz1#UGdGl@;yn z=DdA2+&-%!SU5lPQLgWv<_qcb%%A185bERnl2><%5cwe{ZDdz&hBZbV&^%FE+xn{_&CC7(;0 z!k6`{*JNbG+}*Kc(Z0lwi&T48YiDaqNo74#+j-Z`UJK{IG?z6_~Es-2bCs?dDS((*%#8A#Z?aO-B;Q; zgY)X`cexzJ>-WC($%y^6TXN-tUfqce*XN(B-`s!T)8t~+)||3Qvkz|jc1^|mw#0@t zeu=#m&KJv~&YjQ;^2*peOZj1i^`Q$Qnw%_3tG4GDZhcnV{e3=*?hP5PACb#G1wH#Z zT~qSaVU~~|*V&aeCS1AoW|GK~X)Te9!Y@nCDA#qYJ^$&dK*t*XUrcKZJkP0Kix5|M z=`iD#YGx$Pjs(Z1;O zn|p6&9t%FqlG(6j1;&%Z#>VnJuJ=nY4g>W9a~vE z^}P3YMhFDnY%G3!FHGvjb`94rVrwI%KO9Z#QRO|A$GeXE%0-r&hWSfox?1hmR?uB{ zR65s?Q|*;!xy&B17FAbU@9^|YFT3A|_gQqiNAB8SkiO}b^QkD_vkZIptTW5>m05dG zL-3;g(Qjd`9D0vZuNmLm==-*@OXBtn#hJ^NnIAO$DA7Gfj%)HPHYLVwDV{Z7AGYmS ze{|NSti}2l@)n-U`^0v28=v>AhNTNj7k+5F&{SZ;d*vnX%{EsS_es58GZ&~Gd!p4_ zy6w|3eXgx}P7*UWahtAP+nAQ0?YhMB-b}7#zj*SqC%kx(-N(^(I!kP6Q^u0p4>^Ko zC9Uz1p30@RXiL#_eVHt-Nve5V$~$&jbnpC_usWV|ck@#Hv$dt0=Wo#xRxe#%y{6^n zijei<)hBBva^OkmWhF#LE;IFQtTrZy%MX1|u*k~H2r)KbN*2^fDqJ+## zTh3fE+MJ$fJ(YLqS^Y(x{gVzI(Ykf=&^PUaszfa`#TfV}sHYwMi=jP_DS-NB5lwYOh@O0-DqGw6TGX>ud0QJYis#NUnJoIuyp*y2!s%)KN1GN1 z7A-otU~Z_j;MeC7*6Ck=3tPYHShZvO{-di^8RHdp*cq5RyzJe1@8Od5rN=qfTuYg> z`P?e|Z}mOabycqR;`QF`ebyW`7p0cqq?Mpkh`RXSU2azC7!{@{3YxQ|9qLutCQFe zB$J;Y*{6O^cDnkJ?|CvC6z_??pSWRa_M`H)AA5f=i&jVqs{G4%z_Kh+>AW$gy0isr z=DU{_U5!sI4j-6lar!`T;kL%lGY(D47x0tXA*p})$b6nPhpU+Nk8AV9H1TpI`&)=# zIP$yghr^$n0`-FOm!^GrQq;Ni)NP4J>mMom*5q{T@AT*SSpJdU`OoAq?SHM#CLdQS z+6n((HskG&hm+L)C3l?vX!NN^F5cqatM36Ho&{`mo%Pk(2PU%#ef{BSRNHdRxpHTFna?7%R>h?y6QV8R z8djdvaZXF#sAlT?>e5Qj>59cm9E*Z8C*O0?dJwo!P`gq6ptJL{Q*k06zDXzwDm{Al zYr%XDpW903+47SL+uro@ww+PlcG~Vp;Y@vQ9+_s>mOaO3T%XVyk#l0-rOtpj;i&VB zT86HkTa((kN^HMHIy|~-(Qn0}aLu%`b9LJr^?eso>Ye!xC^_$nJmNlC>||rn1T}W) zq7Io=CllMg7_=TfYOkSmvLr9zgdk6Wkg}wvr{(IW87&uMMK6SG`r^!Obf9d>!ZS`x znu(IhCzPI@jz|*jOWw!hyJni0q`BqeOvP&z7K=Ylk=_(BO(Npx9Z7XNM~Mj{x4T?U zMTmB`D7WdPUX{9V_al?P{k;jPlXRjT+YZcUG2Xe)CEdu-yHR?Yh(=e1lbp5xH(rYE>-kT zD-Ow0V=lbM=6^P+e{V+rR!zCvQkADXe}0Pf+h&-xc*@J~Q-rN!{FZ0d+tlzqTRAh_ zZ;?%?pYqY=;Wh`1^##7VHmNQBQ)Z=Ix&FxQrQTT~?=|n-w!V1!<@#58+joho+onZ0 ze10ad;O5aKl3$Lz3A-H3@}NlV+A=BZ?Y4(Ezq~-b>@*A%i~KnPD@GC z3k*MAJ<*~dv4iUy?|ZMVN$O=nzW&|jPt-N~C3%*3COwkSpX)d$@WQdemc+vA6Q&l; zJDFs>@neX}w&N2*A8|W}ZT32!E~{bHcSmi7+S^zM<&R!_x^_4krf3UG@=px@aO8(V z)7~EQC!P`N{#SfTOd^v{w7!w@GfvU{=@6NIqG~5c;85KQQU{3xDOYe+)@&ebW2{=a@jf9M(Trf5o`6;cOBLn zKl`*yoO@?x?Tsq}pKqs~ouK_x%Pb;Y%0krh;b*J)+oe9~RGOU(x}~OiDfV*cF5`wqo8k57sXti#HsaSRJMAZsvUw|I^B*r@<9qXJS5Cdp&0-zn zCtp9YIp6bO?RzRK8*^Qg<3qu`*M|Kzyp_W3t>&k*IX2(F?Kb0&rpkoc&y~t`=YAaj z@?qMX6djpwF40$>&*-#uW^>+Wz$$DPmtg!>#Isi|-|)%WPiD^d^xi8>3)8+;;pxS- zruO5Ebk4Rtlea&-UDU0({nT!aWvltC&lKn-o{VhbsocKDee!)pd$aR%?(zlM#7=2H z{HEHoizB#;Vd>)C{`c}vu+P}ef2uub!>6iSms0N?T6MCWcc*XO^(V@0HB$~>JO1P` zhw!6`0hZngl{Ru;ru(g!W0#op^~&VuzVqU2Q!gDk6}-%UzES?ImX*co{`1Vre;w%* z_Ph3k&)H6K{*@&hi9B-#~xezjGo`OR2$@@`LJf1`6@#4K0S{!a_(rxw3i7z*9;5-)Zlw~w8 zYTmTOS^w9ypU?kf^?g~|ZpnR90)AYV=?GQpI~BZtYp;jxzc=r0#5^|+|NLZ+hUh)N zHJx2M`bCf1pMSL|(9%X-ev|tTo6SqA-O_(-yJY^Do2w^!&&6E@DiiHpuZl08Y7(xo z!7xod^ridpZwpsDvX~0ZDZO{g`dN0k;-;^rb8_m>&oS^{sk=SnV{%pC^YsDhXXYHFa9+u66K7v&%F{99~3ll|J!yV=Fpt3}%$z24NN`qlL7 zXTdEg+0EucL2Kl1`3i(=uF%w-?H{fEDm>)O?CncdH6EJEv}nn)%d!04o>9?Pms_r$ zy#4}@hxM$rJi%&DHm~tXTvoS_J*n30>H7SY&B1odpOwE|`gKC-Ds^UOC!wHF`FpvS zkKaytwY6JJcV2X0<*bu|W|wlR*_KEqz0xthe<9}bt{XFiOGQl8pOy7hZ+Ekt8?w>B z|HJ1?tzF5wU;i$;B>kL!-{UT$?qu`%{hyjIn*8aC&J3Pm^jbmww40uk$5g-az_gFa z7kn<=TD$Cv+MZ6|)xpz+WL&j>x|Tg%^y`(B&}|vj^PTG7I9G}_1RyXdH;*>w;jv&RSCXr3}wCgwz2E~vw3|= zs}G)8(%JUs$=vO`RvlZVdP<3Rv*7CF_eQUOBzY>VdQ>T8wq^GDcVz;GN^`fF*p%Lz z5Wcg~?xe#ZJ4MUqE$ere6wlUoeRU>scg=PEFM%9WazV;l1F^=FhV zSoo@Em8yt9%I#ha%k+J(4l@>9J=UPVZd-Z9EbWD+E0lB6Rg*;Q!mXSDG1o<_6M-Hx(Of%5ZnA}^=^ z{4qEvPcmYD9#o!!%0C3jdJ-tstYi-|>T@YS}D>UrARE+$=B z$Dbc?@{H51xq0HghvYdYeEZEbcfYc(y`kv4H`o22M7=#E{PRfNB0XQr^0E}CmGclDvK5euf}gs*AcqSJZyjn{)> z5zWmrw<-!f`EdWi5z-(-v>NERW!98?P0`Nr}HVO#ImUl-t!g;-JxS zd9U{}fu#(Sljr)HY8cAJZQ0Zw8@qzz?8C;Z&pxh`bXK2sLh88tmCns~zhvv0JZw} z+_pZDPFy9|sJ^mFr7!4f#_D<=v6WRiVykx@c_p9zb^4=<(CLw1S-8);ysi}T3;QZ! z6L~ebaMr5jk2P269hY1+uXA%qt=74)uQF=_zQ(LsQe_;^!hAyd!1kaQmi!a+w*~HO znD>uWO5y5#Ejxxq7V+=c-3{Nh>*#Ijei^8J?)vxU%{%%ZPyPEq>s;~M_BoFZC#=!9 z$KH2%!tO^5UluLf%v|;Sd7xwNb;lRZYxz#N+c2>HUbtb$d6^shwUU|kdcTSd8@SEI znRiMY+01)yt;YI=MT$?ff5{YR?|5+gg7mvaryGoUH+T;}Fz9JhHsFhE*!+O~LHl$? z4*Pb2J)D6R{AP#dKXCdXV0QTa1Fat-;zDYNW7OxhZ4FVrU%0uVz?5S`h`+YpO}5BB zS=I9gC+G&m6p6H55iLJ(q43LX#>3k#Fj*aN_MgWmv5(c{cv-;-*`jvePYx%RebPSB zwBFH~ac_VVqt%0yGhr$f8MBxq8oN7K4hlydDabaQ=f|QHzhm=>Sx3%?ygr(BOz>po zrk(QDOLe@rPrusX&DnMAwRdJVZ^N36M^(?fDLnJ$(&7T4kGr1;^tfo0Ur6J9(-7#M zSW-F7`nANAotr-$muXUBe0uZU8)pNtL~foZVTMf3nMd>93QSRWyX^4W8_Y*~f=s3E zM&3S9EOBi8hLlGNQ#N||7_dHM@UeMxZqdGTCvFE#5a#?jneSi<(*?dmBHOPqste!W zzU<-I`Cbw)bGh!ZtXsG;;W9_VirIOLx%Pa85$g|6qj3V zcmDQmef{O@J6#p6nr4CYvs~uq z(heUob6K14wM;|1d|A;qnagV|a<3WX=2d;sE8gArrqMLo)A;+rS9~9GTjv~puspC) z`TiXbLtWpTWqi)Y{Ux#uVrCI$?c20;RxM_3y1kJ9^3FWhy4ANU8E*A`u)fK-@a=^2 z(GF+w&)ZLbIcG1sQuGJM&E4Ob-={1RdfmOOOUsiX`>A0@f%WIdU(zJ6zV@Bv8E!5h z^F3!vwOORW^P9HMqiw}+*osHlibsAu8Ztd%hTg+%w~SUl4&u((YFS9ZtWsBIK1&9Q6D|b9hKHxv`K$Hx3 z_(O{wqNg9o&0*-j^yl}9&-VSn4|G5Mct3f6`Gob?3)oyGmJ78OcO28|64EL#`uRg^ zjmmOE`S3?fcO3E_D1FKapJ=^P(Es@D7iZt@=n320bZxU#xxkglJGlBE&HN!WuU9|# zzV?fw<^{ZKulQ%jcFQL-*dJ7Tcpxn?Awc9o)J6X2qXKsnx(XL-9Q9qqcV5{0W6eex zeS!4Hs)yRAcWtd`-661EWc!1wkM#Dq*|eB<%&k~`quIQxwqkOHXueqf1Kmfydt(1^ zzn_r&!OxQM{iMww^CG*ypGd9PAJh5$l<`Nqn@#+u%W8bw3TO8`UR-2sr1AAXmWf6y-@|A=2k{vp3?{Dc0@RS*3)wLS3P z+|^*YN5;w2tq_S+zF|Z*KBe zzdXB7^qJ5%WfAo=74DZ-X?WK)Jib$VVLs0b$92{ZCOox05p3(q=vn*hCI9M|#>O8q zlN4CzbU1I|@J?7ODsYcsisgg#8T|FWKTp2iV!VGL!+YHs9r=effAGy|dq0W!zpTzt z`$Jwe^5+inE40WvvHa(n{=mIJ_8)KF@%@+kYTUj(zyE>dAA8?}=O2{nIPZ&dyytA( z+j68XMYN5Bx7$T;8i(w0PW5?OF%iDgk{Vz1YP-sI5q7bmWgU^aF!4CyYspm6N)%p@k3BTJ@C*mIKar1|62 zYh9<-Ot9lLAv=ev%4<1+J@qMx{K z=idI}fDc>ZswMXAUbN)NP38|yviW+fZugTJPHmTKG%s6ypr*zv!LI2RC$CK!Taf-N z!^&b!0;#i ~S$&{^{_1k{= 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

F1ZXa^@`!P0W*P2{FS^Gn00bMFOP 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 ss146zx5U;_xB$E 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%0D_aZ^J2rs=l_fF*8>+Z`V6Jf5Y8bPaID#_nWwe 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

l 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

hG%mp1%5g8En~i5VBwr=t3v!=TRhVX{*ju) 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℘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 z

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%0DJ{$)EnGKIvhg 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