Merge "Bug 1280: Added option to automaticly create parents"
authorTom Pantelis <tpanteli@brocade.com>
Thu, 24 Jul 2014 19:44:19 +0000 (19:44 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 24 Jul 2014 19:44:19 +0000 (19:44 +0000)
12 files changed:
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/ExtensibleBundleTracker.java
opendaylight/distribution/opendaylight-karaf/pom.xml
opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/instance [new file with mode: 0755]
opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/instance.bat [new file with mode: 0644]
opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/karaf [new file with mode: 0755]
opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/karaf.bat [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RpcIsNotRoutedException.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeGenerator.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/AbstractRuntimeCodeGenerator.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcProviderRegistryImpl.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/RpcProviderRegistryTest.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/rpc/impl/AbstractRpcExecutor.java

index c1ebba7..eff267a 100644 (file)
@@ -7,6 +7,13 @@
  */
 package org.opendaylight.controller.config.manager.impl.osgi;
 
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadFactory;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleEvent;
@@ -15,74 +22,114 @@ import org.osgi.util.tracker.BundleTrackerCustomizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+
 /**
  *
- * Extensible bundle tracker. Takes several BundleTrackerCustomizers and propagates bundle events to all of them.
- * Primary customizer
+ * Extensible bundle tracker. Takes several BundleTrackerCustomizers and
+ * propagates bundle events to all of them.
+ *
+ * Primary customizer may return tracking object,
+ * which will be passed to it during invocation of
+ * {@link BundleTrackerCustomizer#removedBundle(Bundle, BundleEvent, Future)}
+ *
+ *
+ * This extender modifies behaviour to not leak platform thread
+ * in {@link BundleTrackerCustomizer#addingBundle(Bundle, BundleEvent)}
+ * but deliver this event from its own single threaded executor.
+ *
+ * If bundle is removed before event for adding bundle was executed,
+ * that event is cancelled. If addingBundle event is currently in progress
+ * or was already executed, platform thread is block untill addingBundle
+ * finishes so bundle could be removed correctly in platform thread.
+ *
+ *
+ * Method {@link BundleTrackerCustomizer#removedBundle(Bundle, BundleEvent, Object)}
+ * is never invoked on registered trackers.
  *
  * @param <T>
  */
-public final class ExtensibleBundleTracker<T> extends BundleTracker<T> {
+public final class ExtensibleBundleTracker<T> extends BundleTracker<Future<T>> {
 
+    private static final ThreadFactory THREAD_FACTORY = new ThreadFactoryBuilder()
+        .setNameFormat("config-bundle-tracker-%d")
+        .build();
+    private final ExecutorService eventExecutor;
     private final BundleTrackerCustomizer<T> primaryTracker;
     private final BundleTrackerCustomizer<?>[] additionalTrackers;
 
-    private static final Logger logger = LoggerFactory.getLogger(ExtensibleBundleTracker.class);
+    private static final Logger LOG = LoggerFactory.getLogger(ExtensibleBundleTracker.class);
 
-    public ExtensibleBundleTracker(BundleContext context, BundleTrackerCustomizer<T> primaryBundleTrackerCustomizer,
-                                   BundleTrackerCustomizer<?>... additionalBundleTrackerCustomizers) {
+    public ExtensibleBundleTracker(final BundleContext context, final BundleTrackerCustomizer<T> primaryBundleTrackerCustomizer,
+                                   final BundleTrackerCustomizer<?>... additionalBundleTrackerCustomizers) {
         this(context, Bundle.ACTIVE, primaryBundleTrackerCustomizer, additionalBundleTrackerCustomizers);
     }
 
-    public ExtensibleBundleTracker(BundleContext context, int bundleState,
-                                   BundleTrackerCustomizer<T> primaryBundleTrackerCustomizer,
-                                   BundleTrackerCustomizer<?>... additionalBundleTrackerCustomizers) {
+    public ExtensibleBundleTracker(final BundleContext context, final int bundleState,
+                                   final BundleTrackerCustomizer<T> primaryBundleTrackerCustomizer,
+                                   final BundleTrackerCustomizer<?>... additionalBundleTrackerCustomizers) {
         super(context, bundleState, null);
         this.primaryTracker = primaryBundleTrackerCustomizer;
         this.additionalTrackers = additionalBundleTrackerCustomizers;
-        logger.trace("Registered as extender with context {} and bundle state {}", context, bundleState);
+        eventExecutor = Executors.newSingleThreadExecutor(THREAD_FACTORY);
+        LOG.trace("Registered as extender with context {} and bundle state {}", context, bundleState);
     }
 
     @Override
-    public T addingBundle(final Bundle bundle, final BundleEvent event) {
-        T primaryTrackerRetVal = primaryTracker.addingBundle(bundle, event);
-
-        forEachAdditionalBundle(new BundleStrategy() {
+    public Future<T> addingBundle(final Bundle bundle, final BundleEvent event) {
+        LOG.trace("Submiting AddingBundle for bundle {} and event {} to be processed asynchronously",bundle,event);
+        Future<T> future = eventExecutor.submit(new Callable<T>() {
             @Override
-            public void execute(BundleTrackerCustomizer<?> tracker) {
-                tracker.addingBundle(bundle, event);
+            public T call() throws Exception {
+                try {
+                    T primaryTrackerRetVal = primaryTracker.addingBundle(bundle, event);
+
+                    forEachAdditionalBundle(new BundleStrategy() {
+                        @Override
+                        public void execute(final BundleTrackerCustomizer<?> tracker) {
+                            tracker.addingBundle(bundle, event);
+                        }
+                    });
+                    LOG.trace("AddingBundle for {} and event {} finished successfully",bundle,event);
+                    return primaryTrackerRetVal;
+                } catch (Exception e) {
+                    LOG.error("Failed to add bundle {}",e);
+                    throw e;
+                }
             }
         });
-
-        return primaryTrackerRetVal;
+        return future;
     }
 
     @Override
-    public void modifiedBundle(final Bundle bundle, final BundleEvent event, final T object) {
-        primaryTracker.modifiedBundle(bundle, event, object);
-
-        forEachAdditionalBundle(new BundleStrategy() {
-            @Override
-            public void execute(BundleTrackerCustomizer<?> tracker) {
-                tracker.modifiedBundle(bundle, event, null);
-            }
-        });
+    public void modifiedBundle(final Bundle bundle, final BundleEvent event, final Future<T> object) {
+        // Intentionally NOOP
 
     }
 
     @Override
-    public void removedBundle(final Bundle bundle, final BundleEvent event, final T object) {
-        primaryTracker.removedBundle(bundle, event, object);
-
-        forEachAdditionalBundle(new BundleStrategy() {
-            @Override
-            public void execute(BundleTrackerCustomizer<?> tracker) {
-                tracker.removedBundle(bundle, event, null);
-            }
-        });
+    public void removedBundle(final Bundle bundle, final BundleEvent event, final Future<T> object) {
+        if(!object.isDone() && object.cancel(false)) {
+            // We canceled adding event before it was processed
+            // so it is safe to return
+            LOG.trace("Adding Bundle event for {} was cancelled. No additional work required.",bundle);
+            return;
+        }
+        try {
+            LOG.trace("Invoking removedBundle event for {}",bundle);
+            primaryTracker.removedBundle(bundle, event, object.get());
+            forEachAdditionalBundle(new BundleStrategy() {
+                @Override
+                public void execute(final BundleTrackerCustomizer<?> tracker) {
+                    tracker.removedBundle(bundle, event, null);
+                }
+            });
+            LOG.trace("Removed bundle event for {} finished successfully.",bundle);
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Addition of bundle failed, ", e);
+        }
     }
 
-    private void forEachAdditionalBundle(BundleStrategy lambda) {
+    private void forEachAdditionalBundle(final BundleStrategy lambda) {
         for (BundleTrackerCustomizer<?> trac : additionalTrackers) {
             lambda.execute(trac);
         }
index efb7a37..06e0a92 100644 (file)
           </execution>
         </executions>
       </plugin>
+        <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-antrun-plugin</artifactId>
+            <executions>
+                <execution>
+                    <phase>prepare-package</phase>
+                    <goals>
+                        <goal>run</goal>
+                    </goals>
+                    <configuration>
+                        <tasks>
+                            <copy todir="${project.build.directory}/assembly/bin" overwrite="true">
+                                <fileset dir="${basedir}/src/main/resources/karaf/" includes="karaf,karaf.bat,instance,instance.bat"/>
+                            </copy>
+                        </tasks>
+                    </configuration>
+                </execution>
+            </executions>
+        </plugin>
     </plugins>
   </build>
   <scm>
diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/instance b/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/instance
new file mode 100755 (executable)
index 0000000..7288042
--- /dev/null
@@ -0,0 +1,349 @@
+#!/bin/sh
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+
+DIRNAME=`dirname "$0"`
+PROGNAME=`basename "$0"`
+
+#
+# Sourcing environment settings for karaf similar to tomcats setenv
+#
+KARAF_SCRIPT="instance"
+export KARAF_SCRIPT
+if [ -f "$DIRNAME/setenv" ]; then
+  . "$DIRNAME/setenv"
+fi
+
+#
+# Check/Set up some easily accessible MIN/MAX params for JVM mem usage
+#
+if [ "x$JAVA_MIN_MEM" = "x" ]; then
+    JAVA_MIN_MEM=128M
+    export JAVA_MIN_MEM
+fi
+if [ "x$JAVA_MAX_MEM" = "x" ]; then
+    JAVA_MAX_MEM=512M
+    export JAVA_MAX_MEM
+fi
+
+warn() {
+    echo "${PROGNAME}: $*"
+}
+
+die() {
+    warn "$*"
+    exit 1
+}
+
+detectOS() {
+    # OS specific support (must be 'true' or 'false').
+    cygwin=false;
+    darwin=false;
+    aix=false;
+    os400=false;
+    case "`uname`" in
+        CYGWIN*)
+            cygwin=true
+            ;;
+        Darwin*)
+            darwin=true
+            ;;
+        AIX*)
+            aix=true
+            ;;
+        OS400*)
+            os400=true
+            ;;
+    esac
+    # For AIX, set an environment variable
+    if $aix; then
+         export LDR_CNTRL=MAXDATA=0xB0000000@DSA
+         echo $LDR_CNTRL
+    fi
+}
+
+unlimitFD() {
+    # Use the maximum available, or set MAX_FD != -1 to use that
+    if [ "x$MAX_FD" = "x" ]; then
+        MAX_FD="maximum"
+    fi
+
+    # Increase the maximum file descriptors if we can
+    if [ "$os400" = "false" ] && [ "$cygwin" = "false" ]; then
+        MAX_FD_LIMIT=`ulimit -H -n`
+        if [ "$MAX_FD_LIMIT" != 'unlimited' ]; then 
+            if [ $? -eq 0 ]; then
+                if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ]; then
+                    # use the system max
+                    MAX_FD="$MAX_FD_LIMIT"
+                fi
+
+                ulimit -n $MAX_FD > /dev/null
+                # echo "ulimit -n" `ulimit -n`
+                if [ $? -ne 0 ]; then
+                    warn "Could not set maximum file descriptor limit: $MAX_FD"
+                fi
+            else
+                warn "Could not query system maximum file descriptor limit: $MAX_FD_LIMIT"
+            fi
+        fi
+    fi
+}
+
+locateHome() {
+    if [ "x$KARAF_HOME" != "x" ]; then
+        warn "Ignoring predefined value for KARAF_HOME"
+    fi
+
+    # In POSIX shells, CDPATH may cause cd to write to stdout
+    (unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+    KARAF_HOME=`cd "$DIRNAME/.."; pwd`
+    if [ ! -d "$KARAF_HOME" ]; then
+        die "KARAF_HOME is not valid: $KARAF_HOME"
+    fi
+}
+
+locateBase() {
+    if [ "x$KARAF_BASE" != "x" ]; then
+        if [ ! -d "$KARAF_BASE" ]; then
+            die "KARAF_BASE is not valid: $KARAF_BASE"
+        fi
+    else
+        KARAF_BASE=$KARAF_HOME
+    fi
+}
+
+locateData() {
+    if [ "x$KARAF_DATA" != "x" ]; then
+        if [ ! -d "$KARAF_DATA" ]; then
+            die "KARAF_DATA is not valid: $KARAF_DATA"
+        fi
+    else
+        KARAF_DATA=$KARAF_BASE/data
+    fi
+}
+
+locateEtc() {
+    if [ "x$KARAF_ETC" != "x" ]; then
+        if [ ! -d "$KARAF_ETC" ]; then
+            die "KARAF_ETC is not valid: $KARAF_ETC"
+        fi
+    else
+        KARAF_ETC=$KARAF_BASE/etc
+    fi
+}
+
+setupNativePath() {
+    # Support for loading native libraries
+    LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:$KARAF_BASE/lib:$KARAF_HOME/lib"
+
+    # For Cygwin, set PATH from LD_LIBRARY_PATH
+    if $cygwin; then
+        LD_LIBRARY_PATH=`cygpath --path --windows "$LD_LIBRARY_PATH"`
+        PATH="$PATH;$LD_LIBRARY_PATH"
+        export PATH
+    fi
+    export LD_LIBRARY_PATH
+}
+
+pathCanonical() {
+    local dst="${1}"
+    while [ -h "${dst}" ] ; do
+        ls=`ls -ld "${dst}"`
+        link=`expr "$ls" : '.*-> \(.*\)$'`
+        if expr "$link" : '/.*' > /dev/null; then
+            dst="$link"
+        else
+            dst="`dirname "${dst}"`/$link"
+        fi
+    done
+    local bas=`basename "${dst}"`
+    local dir=`dirname "${dst}"`
+    if [ "$bas" != "$dir" ]; then
+        dst="`pathCanonical "$dir"`/$bas"
+    fi
+    echo "${dst}" | sed -e 's#//#/#g' -e 's#/./#/#g' -e 's#/[^/]*/../#/#g'
+}
+
+locateJava() {
+    # Setup the Java Virtual Machine
+    if $cygwin ; then
+        [ -n "$JAVA" ] && JAVA=`cygpath --unix "$JAVA"`
+        [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+    fi
+
+    if [ "x$JAVA_HOME" = "x" ] && [ "$darwin" = "true" ]; then
+        JAVA_HOME="$(/usr/libexec/java_home)"
+    fi
+    if [ "x$JAVA" = "x" ] && [ -r /etc/gentoo-release ] ; then
+        JAVA_HOME=`java-config --jre-home`
+    fi
+    if [ "x$JAVA" = "x" ]; then
+        if [ "x$JAVA_HOME" != "x" ]; then
+            if [ ! -d "$JAVA_HOME" ]; then
+                die "JAVA_HOME is not valid: $JAVA_HOME"
+            fi
+            JAVA="$JAVA_HOME/bin/java"
+        else
+            warn "JAVA_HOME not set; results may vary"
+            JAVA=`type java`
+            JAVA=`expr "$JAVA" : '.*is \(.*\)$'`
+            if [ "x$JAVA" = "x" ]; then
+                die "java command not found"
+            fi
+        fi
+    fi
+    if [ "x$JAVA_HOME" = "x" ]; then
+        JAVA_HOME="$(dirname $(dirname $(pathCanonical "$JAVA")))"
+    fi
+}
+
+detectJVM() {
+   #echo "`$JAVA -version`"
+   # This service should call `java -version`,
+   # read stdout, and look for hints
+   if $JAVA -version 2>&1 | grep "^IBM" ; then
+       JVM_VENDOR="IBM"
+   # on OS/400, java -version does not contain IBM explicitly
+   elif $os400; then
+       JVM_VENDOR="IBM"
+   else
+       JVM_VENDOR="SUN"
+   fi
+   # echo "JVM vendor is $JVM_VENDOR"
+}
+
+setupDebugOptions() {
+    if [ "x$JAVA_OPTS" = "x" ]; then
+        JAVA_OPTS="$DEFAULT_JAVA_OPTS"
+    fi
+    export JAVA_OPTS
+
+    # Set Debug options if enabled
+    if [ "x$KARAF_DEBUG" != "x" ]; then
+        # Use the defaults if JAVA_DEBUG_OPTS was not set
+        if [ "x$JAVA_DEBUG_OPTS" = "x" ]; then
+            JAVA_DEBUG_OPTS="$DEFAULT_JAVA_DEBUG_OPTS"
+        fi
+
+        JAVA_OPTS="$JAVA_DEBUG_OPTS $JAVA_OPTS"
+        warn "Enabling Java debug options: $JAVA_DEBUG_OPTS"
+    fi
+}
+
+setupDefaults() {
+    DEFAULT_JAVA_OPTS="-Xms$JAVA_MIN_MEM -Xmx$JAVA_MAX_MEM "
+
+    #Set the JVM_VENDOR specific JVM flags
+    if [ "$JVM_VENDOR" = "SUN" ]; then
+        #
+        # Check some easily accessible MIN/MAX params for JVM mem usage
+        #
+        if [ "x$JAVA_PERM_MEM" != "x" ]; then
+            DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS -XX:PermSize=$JAVA_PERM_MEM"
+        fi
+        if [ "x$JAVA_MAX_PERM_MEM" != "x" ]; then
+            DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS -XX:MaxPermSize=$JAVA_MAX_PERM_MEM"
+        fi
+        DEFAULT_JAVA_OPTS="-server $DEFAULT_JAVA_OPTS -Dcom.sun.management.jmxremote"
+    elif [ "$JVM_VENDOR" = "IBM" ]; then
+        if $os400; then
+            DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS"
+        elif $aix; then
+            DEFAULT_JAVA_OPTS="-Xverify:none -Xdump:heap -Xlp $DEFAULT_JAVA_OPTS"
+        else
+            DEFAULT_JAVA_OPTS="-Xverify:none $DEFAULT_JAVA_OPTS"
+        fi
+    fi
+
+    # Add the jars in the lib dir
+    for file in "$KARAF_HOME"/lib/*.jar
+    do
+        if [ -z "$CLASSPATH" ]; then
+            CLASSPATH="$file"
+        else
+            CLASSPATH="$CLASSPATH:$file"
+        fi
+    done
+    DEFAULT_JAVA_DEBUG_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"
+
+    ##
+    ## TODO: Move to conf/profiler/yourkit.{sh|cmd}
+    ##
+    # Uncomment to enable YourKit profiling
+    #DEFAULT_JAVA_DEBUG_OPTS="-Xrunyjpagent"
+}
+
+init() {
+    # Determine if there is special OS handling we must perform
+    detectOS
+
+    # Unlimit the number of file descriptors if possible
+    unlimitFD
+
+    # Locate the Karaf home directory
+    locateHome
+
+    # Locate the Karaf base directory
+    locateBase
+
+    # Locate the Karaf data directory
+    locateData
+
+    # Locate the Karaf etc directory
+    locateEtc
+
+    # Setup the native library path
+    setupNativePath
+
+    # Locate the Java VM to execute
+    locateJava
+
+    # Determine the JVM vendor
+    detectJVM
+
+    # Setup default options
+    setupDefaults
+
+    # Install debug options
+    setupDebugOptions
+
+}
+
+run() {
+
+    CLASSPATH="${KARAF_HOME}/system/org/apache/karaf/instance/org.apache.karaf.instance.command/3.0.1/org.apache.karaf.instance.command-3.0.1.jar:${KARAF_HOME}/system/org/apache/karaf/instance/org.apache.karaf.instance.core/3.0.1/org.apache.karaf.instance.core-3.0.1.jar:${KARAF_HOME}/system/org/apache/karaf/shell/org.apache.karaf.shell.console/3.0.1/org.apache.karaf.shell.console-3.0.1.jar:${KARAF_HOME}/system/org/apache/karaf/shell/org.apache.karaf.shell.table/3.0.1/org.apache.karaf.shell.table-3.0.1.jar:${KARAF_HOME}/system/org/apache/aries/blueprint/org.apache.aries.blueprint.api/1.0.0/org.apache.aries.blueprint.api-1.0.0.jar:${KARAF_HOME}/system/org/apache/aries/blueprint/org.apache.aries.blueprint.core/1.4.0/org.apache.aries.blueprint.core-1.4.0.jar:${KARAF_HOME}/system/org/apache/aries/blueprint/org.apache.aries.blueprint.cm/1.0.3/org.apache.aries.blueprint.cm-1.0.3.jar:${KARAF_HOME}/system/org/ops4j/pax/logging/pax-logging-api/1.7.2/pax-logging-api-1.7.2.jar:${KARAF_HOME}/system/org/apache/felix/org.apache.felix.framework/4.2.1/org.apache.felix.framework-4.2.1.jar:${KARAF_HOME}/system/jline/jline/2.11/jline-2.11.jar:$CLASSPATH"
+
+    if $cygwin; then
+        KARAF_HOME=`cygpath --path --windows "$KARAF_HOME"`
+        KARAF_BASE=`cygpath --path --windows "$KARAF_BASE"`
+        KARAF_DATA=`cygpath --path --windows "$KARAF_DATA"`
+        KARAF_ETC=`cygpath --path --windows "$KARAF_ETC"`
+        CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+    fi
+
+    exec "$JAVA" $JAVA_OPTS -Dkaraf.instances="${KARAF_HOME}/instances" -Dkaraf.home="$KARAF_HOME" -Dkaraf.base="$KARAF_BASE" -Dkaraf.etc="$KARAF_ETC" -Djava.io.tmpdir="$KARAF_DATA/tmp" -Djava.util.logging.config.file="$KARAF_BASE/etc/java.util.logging.properties" $KARAF_OPTS $OPTS -classpath "$CLASSPATH" org.apache.karaf.instance.main.Execute "$@"
+}
+
+main() {
+    init
+    run "$@"
+}
+
+main "$@"
+
diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/instance.bat b/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/instance.bat
new file mode 100644 (file)
index 0000000..49c2c0f
--- /dev/null
@@ -0,0 +1,151 @@
+@echo off\r
+rem\r
+rem\r
+rem    Licensed to the Apache Software Foundation (ASF) under one or more\r
+rem    contributor license agreements.  See the NOTICE file distributed with\r
+rem    this work for additional information regarding copyright ownership.\r
+rem    The ASF licenses this file to You under the Apache License, Version 2.0\r
+rem    (the "License"); you may not use this file except in compliance with\r
+rem    the License.  You may obtain a copy of the License at\r
+rem\r
+rem       http://www.apache.org/licenses/LICENSE-2.0\r
+rem\r
+rem    Unless required by applicable law or agreed to in writing, software\r
+rem    distributed under the License is distributed on an "AS IS" BASIS,\r
+rem    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+rem    See the License for the specific language governing permissions and\r
+rem    limitations under the License.\r
+rem\r
+\r
+if not "%ECHO%" == "" echo %ECHO%\r
+\r
+setlocal\r
+set DIRNAME=%~dp0%\r
+set PROGNAME=%~nx0%\r
+set ARGS=%*\r
+\r
+rem Sourcing environment settings for karaf similar to tomcats setenv\r
+SET KARAF_SCRIPT="instance.bat"\r
+if exist "%DIRNAME%setenv.bat" (\r
+  call "%DIRNAME%setenv.bat"\r
+)\r
+\r
+rem Check console window title. Set to Karaf by default\r
+if not "%KARAF_TITLE%" == "" (\r
+    title %KARAF_TITLE%\r
+) else (\r
+    title Karaf\r
+)\r
+\r
+rem Check/Set up some easily accessible MIN/MAX params for JVM mem usage\r
+if "%JAVA_MIN_MEM%" == "" (\r
+    set JAVA_MIN_MEM=128M\r
+)\r
+if "%JAVA_MAX_MEM%" == "" (\r
+    set JAVA_MAX_MEM=512M\r
+)\r
+\r
+goto BEGIN\r
+\r
+:warn\r
+    echo %PROGNAME%: %*\r
+goto :EOF\r
+\r
+:BEGIN\r
+\r
+rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #\r
+\r
+if not "%KARAF_HOME%" == "" (\r
+    call :warn Ignoring predefined value for KARAF_HOME\r
+)\r
+set KARAF_HOME=%DIRNAME%..\r
+if not exist "%KARAF_HOME%" (\r
+    call :warn KARAF_HOME is not valid: "%KARAF_HOME%"\r
+    goto END\r
+)\r
+\r
+if not "%KARAF_BASE%" == "" (\r
+    if not exist "%KARAF_BASE%" (\r
+       call :warn KARAF_BASE is not valid: "%KARAF_BASE%"\r
+       goto END\r
+    )\r
+)\r
+if "%KARAF_BASE%" == "" (\r
+  set "KARAF_BASE=%KARAF_HOME%"\r
+)\r
+\r
+if not "%KARAF_DATA%" == "" (\r
+    if not exist "%KARAF_DATA%" (\r
+        call :warn KARAF_DATA is not valid: "%KARAF_DATA%"\r
+        goto END\r
+    )\r
+)\r
+if "%KARAF_DATA%" == "" (\r
+    set "KARAF_DATA=%KARAF_BASE%\data"\r
+)\r
+\r
+if not "%KARAF_ETC%" == "" (\r
+    if not exist "%KARAF_ETC%" (\r
+        call :warn KARAF_ETC is not valid: "%KARAF_ETC%"\r
+        goto END\r
+    )\r
+)\r
+if "%KARAF_ETC%" == "" (\r
+    set "KARAF_ETC=%KARAF_BASE%\etc"\r
+)\r
+\r
+set DEFAULT_JAVA_OPTS=\r
+set DEFAULT_JAVA_DEBUG_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005\r
+\r
+rem Support for loading native libraries\r
+set PATH=%PATH%;%KARAF_BASE%\lib;%KARAF_HOME%\lib\r
+\r
+rem Setup the Java Virtual Machine\r
+if not "%JAVA%" == "" goto :Check_JAVA_END\r
+    set JAVA=java\r
+    if "%JAVA_HOME%" == "" call :warn JAVA_HOME not set; results may vary\r
+    if not "%JAVA_HOME%" == "" set JAVA=%JAVA_HOME%\bin\java\r
+    if not exist "%JAVA_HOME%" (\r
+        call :warn JAVA_HOME is not valid: "%JAVA_HOME%"\r
+        goto END\r
+    )\r
+:Check_JAVA_END\r
+\r
+if "%JAVA_OPTS%" == "" set JAVA_OPTS=%DEFAULT_JAVA_OPTS%\r
+\r
+if "%KARAF_DEBUG%" == "" goto :KARAF_DEBUG_END\r
+    rem Use the defaults if JAVA_DEBUG_OPTS was not set\r
+    if "%JAVA_DEBUG_OPTS%" == "" set JAVA_DEBUG_OPTS=%DEFAULT_JAVA_DEBUG_OPTS%\r
+\r
+    set "JAVA_OPTS=%JAVA_DEBUG_OPTS% %JAVA_OPTS%"\r
+    call :warn Enabling Java debug options: %JAVA_DEBUG_OPTS%\r
+:KARAF_DEBUG_END\r
+\r
+rem Setup the classpath\r
+pushd "%KARAF_HOME%\lib"\r
+for %%G in (karaf*.jar) do call:APPEND_TO_CLASSPATH %%G\r
+popd\r
+goto CLASSPATH_END\r
+\r
+: APPEND_TO_CLASSPATH\r
+set filename=%~1\r
+set suffix=%filename:~-4%\r
+if %suffix% equ .jar set CLASSPATH=%CLASSPATH%;%KARAF_HOME%\lib\%filename%\r
+goto :EOF\r
+\r
+:CLASSPATH_END\r
+\r
+set CLASSPATH=%KARAF_HOME%\system\org\apache\karaf\instance\org.apache.karaf.instance.command\3.0.1\org.apache.karaf.instance.command-3.0.1.jar;%KARAF_HOME%\system\org\apache\karaf\instance\org.apache.karaf.instance.core\3.0.1\org.apache.karaf.instance.core-3.0.1.jar;%KARAF_HOME%\system\org\apache\karaf\shell\org.apache.karaf.shell.console\3.0.1\org.apache.karaf.shell.console-3.0.1.jar;%KARAF_HOME%\system\org\apache\karaf\shell\org.apache.karaf.shell.table\3.0.1\org.apache.karaf.shell.table-3.0.1.jar;%KARAF_HOME%\system\org\apache\aries\blueprint\org.apache.aries.blueprint.api\1.0.0\org.apache.aries.blueprint.api-1.0.0.jar;%KARAF_HOME%\system\org\apache\aries\blueprint\org.apache.aries.blueprint.core\1.4.0\org.apache.aries.blueprint.core-1.4.0.jar;%KARAF_HOME%\system\org\apache\aries\blueprint\org.apache.aries.blueprint.cm\1.0.3\org.apache.aries.blueprint.cm-1.0.3.jar;%KARAF_HOME%\system\org\ops4j\pax\logging\pax-logging-api\1.7.2\pax-logging-api-1.7.2.jar;%KARAF_HOME%\system\org\apache\felix\org.apache.felix.framework\4.2.1\org.apache.felix.framework-4.2.1.jar;%KARAF_HOME%\system\jline\jline\2.11\jline-2.11.jar;%CLASSPATH%\r
+\r
+:EXECUTE\r
+    if "%SHIFT%" == "true" SET ARGS=%2 %3 %4 %5 %6 %7 %8\r
+    if not "%SHIFT%" == "true" SET ARGS=%1 %2 %3 %4 %5 %6 %7 %8\r
+    rem Execute the Java Virtual Machine\r
+    "%JAVA%" %JAVA_OPTS% %OPTS% -classpath "%CLASSPATH%" -Dkaraf.instances="%KARAF_HOME%\instances" -Dkaraf.home="%KARAF_HOME%" -Dkaraf.base="%KARAF_BASE%" -Dkaraf.etc="%KARAF_ETC%" -Djava.io.tmpdir="%KARAF_DATA%\tmp" -Djava.util.logging.config.file="%KARAF_BASE%\etc\java.util.logging.properties" %KARAF_OPTS% org.apache.karaf.instance.main.Execute %ARGS%\r
+\r
+rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #\r
+\r
+:END\r
+\r
+endlocal\r
+\r
diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/karaf b/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/karaf
new file mode 100755 (executable)
index 0000000..cad052a
--- /dev/null
@@ -0,0 +1,418 @@
+#!/bin/sh
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+
+DIRNAME=`dirname $0`
+PROGNAME=`basename $0`
+
+#
+# Sourcing environment settings for karaf similar to tomcats setenv
+#
+KARAF_SCRIPT="karaf"
+export KARAF_SCRIPT
+if [ -f "$DIRNAME/setenv" ]; then
+  . "$DIRNAME/setenv"
+fi
+
+#
+# Set up some easily accessible MIN/MAX params for JVM mem usage
+#
+if [ "x$JAVA_MIN_MEM" = "x" ]; then
+    JAVA_MIN_MEM=128M
+    export JAVA_MIN_MEM
+fi
+if [ "x$JAVA_MAX_MEM" = "x" ]; then
+    JAVA_MAX_MEM=512M
+    export JAVA_MAX_MEM
+fi
+
+#
+# Check the mode that initiated the script
+#
+if [ "x$1" != "x" ]; then
+    MODE=$1
+fi
+
+warn() {
+    echo "${PROGNAME}: $*"
+}
+
+die() {
+    warn "$*"
+    exit 1
+}
+
+detectOS() {
+    # OS specific support (must be 'true' or 'false').
+    cygwin=false;
+    darwin=false;
+    aix=false;
+    os400=false;
+    case "`uname`" in
+        CYGWIN*)
+            cygwin=true
+            ;;
+        Darwin*)
+            darwin=true
+            ;;
+        AIX*)
+            aix=true
+            ;;
+        OS400*)
+            os400=true
+            ;;
+    esac
+    # For AIX, set an environment variable
+    if $aix; then
+         export LDR_CNTRL=MAXDATA=0xB0000000@DSA
+         echo $LDR_CNTRL
+    fi
+}
+
+unlimitFD() {
+    # Use the maximum available, or set MAX_FD != -1 to use that
+    if [ "x$MAX_FD" = "x" ]; then
+        MAX_FD="maximum"
+    fi
+
+    # Increase the maximum file descriptors if we can
+    if [ "$os400" = "false" ] && [ "$cygwin" = "false" ]; then
+        MAX_FD_LIMIT=`ulimit -H -n`
+        if [ "$MAX_FD_LIMIT" != 'unlimited' ]; then 
+            if [ $? -eq 0 ]; then
+                if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ]; then
+                    # use the system max
+                    MAX_FD="$MAX_FD_LIMIT"
+                fi
+
+                ulimit -n $MAX_FD > /dev/null
+                # echo "ulimit -n" `ulimit -n`
+                if [ $? -ne 0 ]; then
+                    warn "Could not set maximum file descriptor limit: $MAX_FD"
+                fi
+            else
+                warn "Could not query system maximum file descriptor limit: $MAX_FD_LIMIT"
+            fi
+        fi
+    fi
+}
+
+locateHome() {
+    if [ "x$KARAF_HOME" != "x" ]; then
+        warn "Ignoring predefined value for KARAF_HOME"
+    fi
+
+    # In POSIX shells, CDPATH may cause cd to write to stdout
+    (unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+    KARAF_HOME=`cd "$DIRNAME/.."; pwd`
+    if [ ! -d "$KARAF_HOME" ]; then
+        die "KARAF_HOME is not valid: $KARAF_HOME"
+    fi
+}
+
+locateBase() {
+    if [ "x$KARAF_BASE" != "x" ]; then
+        if [ ! -d "$KARAF_BASE" ]; then
+            die "KARAF_BASE is not valid: $KARAF_BASE"
+        fi
+    else
+        KARAF_BASE=$KARAF_HOME
+    fi
+}
+
+locateData() {
+    if [ "x$KARAF_DATA" != "x" ]; then
+        if [ ! -d "$KARAF_DATA" ]; then
+            die "KARAF_DATA is not valid: $KARAF_DATA"
+        fi
+    else
+        KARAF_DATA=$KARAF_BASE/data
+    fi
+}
+
+locateEtc() {
+    if [ "x$KARAF_ETC" != "x" ]; then
+        if [ ! -d "$KARAF_ETC" ]; then
+            die "KARAF_ETC is not valid: $KARAF_ETC"
+        fi
+    else
+        KARAF_ETC=$KARAF_BASE/etc
+    fi
+}
+
+setupNativePath() {
+    # Support for loading native libraries
+    LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:$KARAF_BASE/lib:$KARAF_HOME/lib"
+
+    # For Cygwin, set PATH from LD_LIBRARY_PATH
+    if $cygwin; then
+        LD_LIBRARY_PATH=`cygpath --path --windows "$LD_LIBRARY_PATH"`
+        PATH="$PATH;$LD_LIBRARY_PATH"
+        export PATH
+    fi
+    export LD_LIBRARY_PATH
+}
+
+pathCanonical() {
+    local dst="${1}"
+    while [ -h "${dst}" ] ; do
+        ls=`ls -ld "${dst}"`
+        link=`expr "$ls" : '.*-> \(.*\)$'`
+        if expr "$link" : '/.*' > /dev/null; then
+            dst="$link"
+        else
+            dst="`dirname "${dst}"`/$link"
+        fi
+    done
+    local bas=`basename "${dst}"`
+    local dir=`dirname "${dst}"`
+    if [ "$bas" != "$dir" ]; then
+      dst="`pathCanonical "$dir"`/$bas"
+    fi
+    echo "${dst}" | sed -e 's#//#/#g' -e 's#/./#/#g' -e 's#/[^/]*/../#/#g'
+}
+
+locateJava() {
+    # Setup the Java Virtual Machine
+    if $cygwin ; then
+        [ -n "$JAVA" ] && JAVA=`cygpath --unix "$JAVA"`
+        [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+    fi
+
+       if [ "x$JAVA_HOME" = "x" ] && [ "$darwin" = "true" ]; then
+               JAVA_HOME="$(/usr/libexec/java_home)"
+       fi
+    if [ "x$JAVA" = "x" ] && [ -r /etc/gentoo-release ] ; then
+        JAVA_HOME=`java-config --jre-home`
+    fi
+    if [ "x$JAVA" = "x" ]; then
+        if [ "x$JAVA_HOME" != "x" ]; then
+            if [ ! -d "$JAVA_HOME" ]; then
+                die "JAVA_HOME is not valid: $JAVA_HOME"
+            fi
+            JAVA="$JAVA_HOME/bin/java"
+        else
+            warn "JAVA_HOME not set; results may vary"
+            JAVA=`type java`
+            JAVA=`expr "$JAVA" : '.*is \(.*\)$'`
+            if [ "x$JAVA" = "x" ]; then
+                die "java command not found"
+            fi
+        fi
+    fi
+    if [ "x$JAVA_HOME" = "x" ]; then
+        JAVA_HOME="$(dirname $(dirname $(pathCanonical "$JAVA")))"
+    fi
+}
+
+detectJVM() {
+   #echo "`$JAVA -version`"
+   # This service should call `java -version`,
+   # read stdout, and look for hints
+   if $JAVA -version 2>&1 | grep "^IBM" ; then
+       JVM_VENDOR="IBM"
+   # on OS/400, java -version does not contain IBM explicitly
+   elif $os400; then
+       JVM_VENDOR="IBM"
+   else
+       JVM_VENDOR="SUN"
+   fi
+   # echo "JVM vendor is $JVM_VENDOR"
+}
+
+checkJvmVersion() {
+   # echo "`$JAVA -version`"
+   VERSION=`$JAVA -version 2>&1 | egrep '"([0-9].[0-9]\..*[0-9])"' | awk '{print substr($3,2,length($3)-2)}' | awk '{print substr($1, 3, 3)}' | sed -e 's;\.;;g'`
+   # echo $VERSION
+   if [ "$VERSION" -lt "60" ]; then
+       echo "JVM must be greater than 1.6"
+       exit 1;
+   fi
+}
+
+setupDebugOptions() {
+    if [ "x$JAVA_OPTS" = "x" ]; then
+        JAVA_OPTS="$DEFAULT_JAVA_OPTS"
+    fi
+    export JAVA_OPTS
+
+    # Set Debug options if enabled
+    if [ "x$KARAF_DEBUG" != "x" ]; then
+        # Ignore DEBUG in case of stop or client mode
+        if [ "x$MODE" = "xstop" ]; then
+            return
+        fi
+        if [ "x$MODE" = "xclient" ]; then
+            return
+        fi
+        # Use the defaults if JAVA_DEBUG_OPTS was not set
+        if [ "x$JAVA_DEBUG_OPTS" = "x" ]; then
+            JAVA_DEBUG_OPTS="$DEFAULT_JAVA_DEBUG_OPTS"
+        fi
+
+        JAVA_OPTS="$JAVA_DEBUG_OPTS $JAVA_OPTS"
+        warn "Enabling Java debug options: $JAVA_DEBUG_OPTS"
+    fi
+}
+
+setupDefaults() {
+    DEFAULT_JAVA_OPTS="-Xms$JAVA_MIN_MEM -Xmx$JAVA_MAX_MEM -XX:+UnlockDiagnosticVMOptions -XX:+UnsyncloadClass "
+
+    #Set the JVM_VENDOR specific JVM flags
+    if [ "$JVM_VENDOR" = "SUN" ]; then
+        #
+        # Check some easily accessible MIN/MAX params for JVM mem usage
+        #
+        if [ "x$JAVA_PERM_MEM" != "x" ]; then
+            DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS -XX:PermSize=$JAVA_PERM_MEM"
+        fi
+        if [ "x$JAVA_MAX_PERM_MEM" != "x" ]; then
+            DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS -XX:MaxPermSize=$JAVA_MAX_PERM_MEM"
+        fi
+        DEFAULT_JAVA_OPTS="-server $DEFAULT_JAVA_OPTS -Dcom.sun.management.jmxremote"
+    elif [ "$JVM_VENDOR" = "IBM" ]; then
+        if $os400; then
+            DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS"
+        elif $aix; then
+            DEFAULT_JAVA_OPTS="-Xverify:none -Xdump:heap -Xlp $DEFAULT_JAVA_OPTS"
+        else
+            DEFAULT_JAVA_OPTS="-Xverify:none $DEFAULT_JAVA_OPTS"
+        fi
+    fi
+
+    # Add the jars in the lib dir
+    for file in "$KARAF_HOME"/lib/karaf*.jar
+    do
+        if [ -z "$CLASSPATH" ]; then
+            CLASSPATH="$file"
+        else
+            CLASSPATH="$CLASSPATH:$file"
+        fi
+    done
+    DEFAULT_JAVA_DEBUG_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"
+
+    ##
+    ## TODO: Move to conf/profiler/yourkit.{sh|cmd}
+    ##
+    # Uncomment to enable YourKit profiling
+    #DEFAULT_JAVA_DEBUG_OPTS="-Xrunyjpagent"
+}
+
+init() {
+    # Determine if there is special OS handling we must perform
+    detectOS
+
+    # Unlimit the number of file descriptors if possible
+    unlimitFD
+
+    # Locate the Karaf home directory
+    locateHome
+
+    # Locate the Karaf base directory
+    locateBase
+
+    # Locate the Karaf data directory
+    locateData
+
+    # Locate the Karaf etc directory
+    locateEtc
+
+    # Setup the native library path
+    setupNativePath
+
+    # Locate the Java VM to execute
+    locateJava
+
+    # Determine the JVM vendor
+    detectJVM
+    
+    # Determine the JVM version >= 1.6
+    checkJvmVersion
+
+    # Setup default options
+    setupDefaults
+
+    # Install debug options
+    setupDebugOptions
+
+}
+
+run() {
+    OPTS="-Dkaraf.startLocalConsole=true -Dkaraf.startRemoteShell=true"
+    MAIN=org.apache.karaf.main.Main
+    while [ "$1" != "" ]; do
+        case $1 in
+            'clean')
+                rm -Rf "$KARAF_DATA"
+                shift
+                ;;
+            'debug')
+                if [ "x$JAVA_DEBUG_OPTS" = "x" ]; then
+                    JAVA_DEBUG_OPTS="$DEFAULT_JAVA_DEBUG_OPTS"
+                fi
+                JAVA_OPTS="$JAVA_DEBUG_OPTS $JAVA_OPTS"
+                shift
+                ;;
+            'status')
+                MAIN=org.apache.karaf.main.Status
+                shift
+                ;;
+            'stop')
+                MAIN=org.apache.karaf.main.Stop
+                shift
+                ;;
+            'console')
+                shift
+                ;;
+            'server')
+                OPTS="-Dkaraf.startLocalConsole=false -Dkaraf.startRemoteShell=true"
+                shift
+                ;;
+            'client')
+                OPTS="-Dkaraf.startLocalConsole=true -Dkaraf.startRemoteShell=false"
+                shift
+                ;;
+            *)
+                break
+                ;;
+        esac
+    done
+
+    JAVA_ENDORSED_DIRS="${JAVA_HOME}/jre/lib/endorsed:${JAVA_HOME}/lib/endorsed:${KARAF_HOME}/lib/endorsed"
+    JAVA_EXT_DIRS="${JAVA_HOME}/jre/lib/ext:${JAVA_HOME}/lib/ext:${KARAF_HOME}/lib/ext"
+    if $cygwin; then
+        KARAF_HOME=`cygpath --path --windows "$KARAF_HOME"`
+        KARAF_BASE=`cygpath --path --windows "$KARAF_BASE"`
+        KARAF_DATA=`cygpath --path --windows "$KARAF_DATA"`
+        KARAF_ETC=`cygpath --path --windows "$KARAF_ETC"`
+        CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+        JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+        JAVA_ENDORSED_DIRS=`cygpath --path --windows "$JAVA_ENDORSED_DIRS"`
+        JAVA_EXT_DIRS=`cygpath --path --windows "$JAVA_EXT_DIRS"`
+    fi
+    cd "$KARAF_BASE"
+
+    exec "$JAVA" $JAVA_OPTS -Djava.endorsed.dirs="${JAVA_ENDORSED_DIRS}" -Djava.ext.dirs="${JAVA_EXT_DIRS}" -Dkaraf.instances="${KARAF_HOME}/instances" -Dkaraf.home="$KARAF_HOME" -Dkaraf.base="$KARAF_BASE" -Dkaraf.data="$KARAF_DATA" -Dkaraf.etc="$KARAF_ETC" -Djava.io.tmpdir="$KARAF_DATA/tmp" -Djava.util.logging.config.file="$KARAF_BASE/etc/java.util.logging.properties" $KARAF_OPTS $OPTS -classpath "$CLASSPATH" $MAIN "$@"
+}
+
+main() {
+    init
+    run "$@"
+}
+
+main "$@"
diff --git a/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/karaf.bat b/opendaylight/distribution/opendaylight-karaf/src/main/resources/karaf/karaf.bat
new file mode 100644 (file)
index 0000000..a450877
--- /dev/null
@@ -0,0 +1,336 @@
+@echo off\r
+rem\r
+rem\r
+rem    Licensed to the Apache Software Foundation (ASF) under one or more\r
+rem    contributor license agreements.  See the NOTICE file distributed with\r
+rem    this work for additional information regarding copyright ownership.\r
+rem    The ASF licenses this file to You under the Apache License, Version 2.0\r
+rem    (the "License"); you may not use this file except in compliance with\r
+rem    the License.  You may obtain a copy of the License at\r
+rem\r
+rem       http://www.apache.org/licenses/LICENSE-2.0\r
+rem\r
+rem    Unless required by applicable law or agreed to in writing, software\r
+rem    distributed under the License is distributed on an "AS IS" BASIS,\r
+rem    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+rem    See the License for the specific language governing permissions and\r
+rem    limitations under the License.\r
+rem\r
+\r
+if not "%ECHO%" == "" echo %ECHO%\r
+\r
+setlocal\r
+set DIRNAME=%~dp0%\r
+set PROGNAME=%~nx0%\r
+set ARGS=%*\r
+\r
+rem Sourcing environment settings for karaf similar to tomcats setenv\r
+SET KARAF_SCRIPT="karaf.bat"\r
+if exist "%DIRNAME%setenv.bat" (\r
+  call "%DIRNAME%setenv.bat"\r
+)\r
+\r
+rem Check console window title. Set to Karaf by default\r
+if not "%KARAF_TITLE%" == "" (\r
+    title %KARAF_TITLE%\r
+) else (\r
+    title Karaf\r
+)\r
+\r
+rem Check/Set up some easily accessible MIN/MAX params for JVM mem usage\r
+if "%JAVA_MIN_MEM%" == "" (\r
+    set JAVA_MIN_MEM=128M\r
+)\r
+if "%JAVA_MAX_MEM%" == "" (\r
+    set JAVA_MAX_MEM=512M\r
+)\r
+\r
+goto BEGIN\r
+\r
+:warn\r
+    echo %PROGNAME%: %*\r
+goto :EOF\r
+\r
+:BEGIN\r
+\r
+rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #\r
+\r
+if not "%KARAF_HOME%" == "" (\r
+    call :warn Ignoring predefined value for KARAF_HOME\r
+)\r
+set KARAF_HOME=%DIRNAME%..\r
+if not exist "%KARAF_HOME%" (\r
+    call :warn KARAF_HOME is not valid: "%KARAF_HOME%"\r
+    goto END\r
+)\r
+\r
+if not "%KARAF_BASE%" == "" (\r
+    if not exist "%KARAF_BASE%" (\r
+       call :warn KARAF_BASE is not valid: "%KARAF_BASE%"\r
+       goto END\r
+    )\r
+)\r
+if "%KARAF_BASE%" == "" (\r
+  set "KARAF_BASE=%KARAF_HOME%"\r
+)\r
+\r
+if not "%KARAF_DATA%" == "" (\r
+    if not exist "%KARAF_DATA%" (\r
+        call :warn KARAF_DATA is not valid: "%KARAF_DATA%"\r
+        goto END\r
+    )\r
+)\r
+if "%KARAF_DATA%" == "" (\r
+    set "KARAF_DATA=%KARAF_BASE%\data"\r
+)\r
+\r
+if not "%KARAF_ETC%" == "" (\r
+    if not exist "%KARAF_ETC%" (\r
+        call :warn KARAF_ETC is not valid: "%KARAF_ETC%"\r
+        goto END\r
+    )\r
+)\r
+if "%KARAF_ETC%" == "" (\r
+    set "KARAF_ETC=%KARAF_BASE%\etc"\r
+)\r
+\r
+set LOCAL_CLASSPATH=%CLASSPATH%\r
+set JAVA_MODE=-server\r
+if not exist "%JAVA_HOME%\bin\server\jvm.dll" (\r
+    if not exist "%JAVA_HOME%\jre\bin\server\jvm.dll" (\r
+        echo WARNING: Running karaf on a Java HotSpot Client VM because server-mode is not available.\r
+        echo Install Java Developer Kit to fix this.\r
+        echo For more details see http://java.sun.com/products/hotspot/whitepaper.html#client\r
+        set JAVA_MODE=-client\r
+    )\r
+)\r
+set DEFAULT_JAVA_OPTS=%JAVA_MODE% -Xms%JAVA_MIN_MEM% -Xmx%JAVA_MAX_MEM% -Dderby.system.home="%KARAF_DATA%\derby" -Dderby.storage.fileSyncTransactionLog=true -Dcom.sun.management.jmxremote  -XX:+UnlockDiagnosticVMOptions -XX:+UnsyncloadClass\r
+\r
+rem Check some easily accessible MIN/MAX params for JVM mem usage\r
+if not "%JAVA_PERM_MEM%" == "" (\r
+    set DEFAULT_JAVA_OPTS=%DEFAULT_JAVA_OPTS% -XX:PermSize=%JAVA_PERM_MEM%\r
+)\r
+if not "%JAVA_MAX_PERM_MEM%" == "" (\r
+    set DEFAULT_JAVA_OPTS=%DEFAULT_JAVA_OPTS% -XX:MaxPermSize=%JAVA_MAX_PERM_MEM%\r
+)\r
+\r
+set CLASSPATH=%LOCAL_CLASSPATH%;%KARAF_BASE%\conf\r
+set DEFAULT_JAVA_DEBUG_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005\r
+\r
+if "%LOCAL_CLASSPATH%" == "" goto :KARAF_CLASSPATH_EMPTY\r
+    set CLASSPATH=%LOCAL_CLASSPATH%;%KARAF_BASE%\conf\r
+    goto :KARAF_CLASSPATH_END\r
+:KARAF_CLASSPATH_EMPTY\r
+    set CLASSPATH=%KARAF_BASE%\conf\r
+:KARAF_CLASSPATH_END\r
+\r
+rem Setup Karaf Home\r
+if exist "%KARAF_HOME%\conf\karaf-rc.cmd" call %KARAF_HOME%\conf\karaf-rc.cmd\r
+if exist "%HOME%\karaf-rc.cmd" call %HOME%\karaf-rc.cmd\r
+\r
+rem Support for loading native libraries\r
+set PATH=%PATH%;%KARAF_BASE%\lib;%KARAF_HOME%\lib\r
+\r
+rem Setup the Java Virtual Machine\r
+if not "%JAVA%" == "" goto :Check_JAVA_END\r
+    if not "%JAVA_HOME%" == "" goto :TryJDKEnd\r
+        call :warn JAVA_HOME not set; results may vary\r
+:TryJRE\r
+    start /w regedit /e __reg1.txt "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment"\r
+    if not exist __reg1.txt goto :TryJDK\r
+    type __reg1.txt | find "CurrentVersion" > __reg2.txt\r
+    if errorlevel 1 goto :TryJDK\r
+    for /f "tokens=2 delims==" %%x in (__reg2.txt) do set JavaTemp=%%~x\r
+    if errorlevel 1 goto :TryJDK\r
+    set JavaTemp=%JavaTemp%##\r
+    set JavaTemp=%JavaTemp:                ##=##%\r
+    set JavaTemp=%JavaTemp:        ##=##%\r
+    set JavaTemp=%JavaTemp:    ##=##%\r
+    set JavaTemp=%JavaTemp:  ##=##%\r
+    set JavaTemp=%JavaTemp: ##=##%\r
+    set JavaTemp=%JavaTemp:##=%\r
+    del __reg1.txt\r
+    del __reg2.txt\r
+    start /w regedit /e __reg1.txt "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\%JavaTemp%"\r
+    if not exist __reg1.txt goto :TryJDK\r
+    type __reg1.txt | find "JavaHome" > __reg2.txt\r
+    if errorlevel 1 goto :TryJDK\r
+    for /f "tokens=2 delims==" %%x in (__reg2.txt) do set JAVA_HOME=%%~x\r
+    if errorlevel 1 goto :TryJDK\r
+    del __reg1.txt\r
+    del __reg2.txt\r
+    goto TryJDKEnd\r
+:TryJDK\r
+    start /w regedit /e __reg1.txt "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit"\r
+    if not exist __reg1.txt (\r
+        goto TryRegJRE\r
+    )\r
+    type __reg1.txt | find "CurrentVersion" > __reg2.txt\r
+    if errorlevel 1 (\r
+        goto TryRegJRE\r
+    )\r
+    for /f "tokens=2 delims==" %%x in (__reg2.txt) do set JavaTemp=%%~x\r
+    if errorlevel 1 (\r
+        goto TryRegJRE\r
+    )\r
+    set JavaTemp=%JavaTemp%##\r
+    set JavaTemp=%JavaTemp:                ##=##%\r
+    set JavaTemp=%JavaTemp:        ##=##%\r
+    set JavaTemp=%JavaTemp:    ##=##%\r
+    set JavaTemp=%JavaTemp:  ##=##%\r
+    set JavaTemp=%JavaTemp: ##=##%\r
+    set JavaTemp=%JavaTemp:##=%\r
+    del __reg1.txt\r
+    del __reg2.txt\r
+    start /w regedit /e __reg1.txt "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit\%JavaTemp%"\r
+    if not exist __reg1.txt (\r
+        goto TryRegJRE\r
+    )\r
+    type __reg1.txt | find "JavaHome" > __reg2.txt\r
+    if errorlevel 1 (\r
+        goto TryRegJRE\r
+    )\r
+    for /f "tokens=2 delims==" %%x in (__reg2.txt) do set JAVA_HOME=%%~x\r
+    if errorlevel 1 (\r
+        goto TryRegJRE\r
+    )\r
+    del __reg1.txt\r
+    del __reg2.txt\r
+:TryRegJRE\r
+    rem try getting the JAVA_HOME from registry\r
+    FOR /F "usebackq tokens=3*" %%A IN (`REG QUERY "HKLM\Software\JavaSoft\Java Runtime Environment" /v CurrentVersion`) DO (\r
+       set JAVA_VERSION=%%A\r
+    )\r
+    FOR /F "usebackq tokens=3*" %%A IN (`REG QUERY "HKLM\Software\JavaSoft\Java Runtime Environment\%JAVA_VERSION%" /v JavaHome`) DO (\r
+       set JAVA_HOME=%%A %%B\r
+    )\r
+    if not exist "%JAVA_HOME%" (\r
+       goto TryRegJDK\r
+    )\r
+       goto TryJDKEnd\r
+:TryRegJDK\r
+    rem try getting the JAVA_HOME from registry\r
+    FOR /F "usebackq tokens=3*" %%A IN (`REG QUERY "HKLM\Software\JavaSoft\Java Development Kit" /v CurrentVersion`) DO (\r
+       set JAVA_VERSION=%%A\r
+    )\r
+    FOR /F "usebackq tokens=3*" %%A IN (`REG QUERY "HKLM\Software\JavaSoft\Java Development Kit\%JAVA_VERSION%" /v JavaHome`) DO (\r
+       set JAVA_HOME=%%A %%B\r
+    )\r
+    if not exist "%JAVA_HOME%" (\r
+       call :warn Unable to retrieve JAVA_HOME from Registry\r
+    )\r
+        goto TryJDKEnd\r
+:TryJDKEnd\r
+    if not exist "%JAVA_HOME%" (\r
+        call :warn JAVA_HOME is not valid: "%JAVA_HOME%"\r
+        goto END\r
+    )\r
+    set JAVA=%JAVA_HOME%\bin\java\r
+:Check_JAVA_END\r
+\r
+if "%JAVA_OPTS%" == "" set JAVA_OPTS=%DEFAULT_JAVA_OPTS%\r
+\r
+if "%KARAF_DEBUG%" == "" goto :KARAF_DEBUG_END\r
+    if "%1" == "stop" goto :KARAF_DEBUG_END\r
+    if "%1" == "client" goto :KARAF_DEBUG_END\r
+    rem Use the defaults if JAVA_DEBUG_OPTS was not set\r
+    if "%JAVA_DEBUG_OPTS%" == "" set JAVA_DEBUG_OPTS=%DEFAULT_JAVA_DEBUG_OPTS%\r
+\r
+    set "JAVA_OPTS=%JAVA_DEBUG_OPTS% %JAVA_OPTS%"\r
+    call :warn Enabling Java debug options: %JAVA_DEBUG_OPTS%\r
+:KARAF_DEBUG_END\r
+\r
+if "%KARAF_PROFILER%" == "" goto :KARAF_PROFILER_END\r
+    set KARAF_PROFILER_SCRIPT=%KARAF_HOME%\conf\profiler\%KARAF_PROFILER%.cmd\r
+\r
+    if exist "%KARAF_PROFILER_SCRIPT%" goto :KARAF_PROFILER_END\r
+    call :warn Missing configuration for profiler '%KARAF_PROFILER%': %KARAF_PROFILER_SCRIPT%\r
+    goto END\r
+:KARAF_PROFILER_END\r
+\r
+rem Setup the classpath\r
+pushd "%KARAF_HOME%\lib"\r
+for %%G in (karaf*.jar) do call:APPEND_TO_CLASSPATH %%G\r
+popd\r
+goto CLASSPATH_END\r
+\r
+: APPEND_TO_CLASSPATH\r
+set filename=%~1\r
+set suffix=%filename:~-4%\r
+if %suffix% equ .jar set CLASSPATH=%CLASSPATH%;%KARAF_HOME%\lib\%filename%\r
+goto :EOF\r
+\r
+:CLASSPATH_END\r
+\r
+rem Execute the JVM or the load the profiler\r
+if "%KARAF_PROFILER%" == "" goto :RUN\r
+    rem Execute the profiler if it has been configured\r
+    call :warn Loading profiler script: %KARAF_PROFILER_SCRIPT%\r
+    call %KARAF_PROFILER_SCRIPT%\r
+\r
+:RUN\r
+    SET OPTS=-Dkaraf.startLocalConsole=true -Dkaraf.startRemoteShell=true\r
+    SET MAIN=org.apache.karaf.main.Main\r
+    SET SHIFT=false\r
+\r
+:RUN_LOOP\r
+    if "%1" == "stop" goto :EXECUTE_STOP\r
+    if "%1" == "status" goto :EXECUTE_STATUS\r
+    if "%1" == "console" goto :EXECUTE_CONSOLE\r
+    if "%1" == "server" goto :EXECUTE_SERVER\r
+    if "%1" == "client" goto :EXECUTE_CLIENT\r
+    if "%1" == "clean" goto :EXECUTE_CLEAN\r
+    if "%1" == "debug" goto :EXECUTE_DEBUG\r
+    goto :EXECUTE\r
+\r
+:EXECUTE_STOP\r
+    SET MAIN=org.apache.karaf.main.Stop\r
+    shift\r
+    goto :RUN_LOOP\r
+\r
+:EXECUTE_STATUS\r
+    SET MAIN=org.apache.karaf.main.Status\r
+    shift\r
+    goto :RUN_LOOP\r
+\r
+:EXECUTE_CONSOLE\r
+    shift\r
+    goto :RUN_LOOP\r
+\r
+:EXECUTE_SERVER\r
+    SET OPTS=-Dkaraf.startLocalConsole=false -Dkaraf.startRemoteShell=true\r
+    shift\r
+    goto :RUN_LOOP\r
+\r
+:EXECUTE_CLIENT\r
+    SET OPTS=-Dkaraf.startLocalConsole=true -Dkaraf.startRemoteShell=false\r
+    shift\r
+    goto :RUN_LOOP\r
+\r
+:EXECUTE_CLEAN\r
+    rmdir /S /Q "%KARAF_DATA%"\r
+    shift\r
+    goto :RUN_LOOP\r
+\r
+:EXECUTE_DEBUG\r
+    if "%JAVA_DEBUG_OPTS%" == "" set JAVA_DEBUG_OPTS=%DEFAULT_JAVA_DEBUG_OPTS%\r
+    set "JAVA_OPTS=%JAVA_DEBUG_OPTS% %JAVA_OPTS%"\r
+    shift\r
+    goto :RUN_LOOP\r
+\r
+:EXECUTE\r
+    SET ARGS=%1 %2 %3 %4 %5 %6 %7 %8\r
+    rem Execute the Java Virtual Machine\r
+    cd "%KARAF_BASE%"\r
+    "%JAVA%" %JAVA_OPTS% %OPTS% -classpath "%CLASSPATH%" -Djava.endorsed.dirs="%JAVA_HOME%\jre\lib\endorsed;%JAVA_HOME%\lib\endorsed;%KARAF_HOME%\lib\endorsed" -Djava.ext.dirs="%JAVA_HOME%\jre\lib\ext;%JAVA_HOME%\lib\ext;%KARAF_HOME%\lib\ext" -Dkaraf.instances="%KARAF_HOME%\instances" -Dkaraf.home="%KARAF_HOME%" -Dkaraf.base="%KARAF_BASE%" -Dkaraf.etc="%KARAF_ETC%" -Djava.io.tmpdir="%KARAF_DATA%\tmp" -Dkaraf.data="%KARAF_DATA%" -Djava.util.logging.config.file="%KARAF_BASE%\etc\java.util.logging.properties" %KARAF_OPTS% %MAIN% %ARGS%\r
+\r
+rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #\r
+\r
+:END\r
+\r
+endlocal\r
+\r
+if not "%PAUSE%" == "" pause\r
+\r
+:END_NO_PAUSE\r
+\r
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RpcIsNotRoutedException.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RpcIsNotRoutedException.java
new file mode 100644 (file)
index 0000000..5317324
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.sal.binding.codegen;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * Exception is raised when supplied Bidning Aware
+ * RPCService class is not routed and was used in context
+ * where routed RPCs should only be used.
+ *
+ */
+public class RpcIsNotRoutedException extends IllegalStateException {
+
+    private static final long serialVersionUID = 1L;
+
+    public RpcIsNotRoutedException(final String message, final Throwable cause) {
+        super(Preconditions.checkNotNull(message), cause);
+    }
+
+    public RpcIsNotRoutedException(final String message) {
+        super(Preconditions.checkNotNull(message));
+    }
+}
index 9b7b8e2..c7c5f10 100644 (file)
@@ -84,8 +84,9 @@ public interface RuntimeCodeGenerator {
      *            - Subclass of RpcService for which Router is to be generated.
      * @return Instance of RpcService of provided serviceType which implements
      *         also {@link RpcRouter}<T> and {@link org.opendaylight.controller.sal.binding.spi.DelegateProxy}
+     * @throws RpcIsNotRoutedException
      */
-    <T extends RpcService> RpcRouter<T> getRouterFor(Class<T> serviceType,String name) throws IllegalArgumentException;
+    <T extends RpcService> RpcRouter<T> getRouterFor(Class<T> serviceType,String name) throws IllegalArgumentException, RpcIsNotRoutedException;
 
     NotificationInvokerFactory getInvokerFactory();
 }
index 9605a4d..8fa88ea 100644 (file)
@@ -19,8 +19,10 @@ import javax.annotation.concurrent.GuardedBy;
 
 import org.eclipse.xtext.xbase.lib.Extension;
 import org.opendaylight.controller.sal.binding.api.rpc.RpcRouter;
+import org.opendaylight.controller.sal.binding.codegen.RpcIsNotRoutedException;
 import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory;
 import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.NotificationListener;
 import org.opendaylight.yangtools.yang.binding.RpcService;
@@ -56,11 +58,11 @@ abstract class AbstractRuntimeCodeGenerator implements org.opendaylight.controll
     protected abstract <T extends RpcService> Supplier<T> directProxySupplier(final Class<T> serviceType);
     protected abstract <T extends RpcService> Supplier<T> routerSupplier(final Class<T> serviceType, RpcServiceMetadata metadata);
 
-    private RpcServiceMetadata getRpcMetadata(final CtClass iface) throws ClassNotFoundException, NotFoundException {
+    private RpcServiceMetadata getRpcMetadata(final CtClass iface) throws ClassNotFoundException, NotFoundException, RpcIsNotRoutedException {
         final RpcServiceMetadata metadata = new RpcServiceMetadata();
 
         for (CtMethod method : iface.getMethods()) {
-            if (iface.equals(method.getDeclaringClass()) && method.getParameterTypes().length == 1) {
+            if (isRpcMethodWithInput(iface, method)) {
                 final RpcMetadata routingPair = getRpcMetadata(method);
                 if (routingPair != null) {
                     metadata.addContext(routingPair.getContext());
@@ -81,6 +83,8 @@ abstract class AbstractRuntimeCodeGenerator implements org.opendaylight.controll
                      *        remains to be investigated.
                      */
                     Thread.currentThread().getContextClassLoader().loadClass(routingPair.getInputType().getName());
+                } else {
+                    throw new RpcIsNotRoutedException("RPC " + method.getName() + " from "+ iface.getName() +" is not routed");
                 }
             }
         }
@@ -88,6 +92,18 @@ abstract class AbstractRuntimeCodeGenerator implements org.opendaylight.controll
         return metadata;
     }
 
+
+    private boolean isRpcMethodWithInput(final CtClass iface, final CtMethod method) throws NotFoundException {
+        if(iface.equals(method.getDeclaringClass())
+                && method.getParameterTypes().length == 1) {
+            final CtClass onlyArg = method.getParameterTypes()[0];
+            if(onlyArg.isInterface() && onlyArg.getName().endsWith(BindingMapping.RPC_INPUT_SUFFIX)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private RpcMetadata getRpcMetadata(final CtMethod method) throws NotFoundException {
         final CtClass inputClass = method.getParameterTypes()[0];
         return rpcMethodMetadata(inputClass, inputClass, method.getName());
@@ -152,7 +168,7 @@ abstract class AbstractRuntimeCodeGenerator implements org.opendaylight.controll
     }
 
     @Override
-    public final <T extends RpcService> RpcRouter<T> getRouterFor(final Class<T> serviceType, final String name) {
+    public final <T extends RpcService> RpcRouter<T> getRouterFor(final Class<T> serviceType, final String name) throws RpcIsNotRoutedException {
         final RpcServiceMetadata metadata = ClassLoaderUtils.withClassLoader(serviceType.getClassLoader(), new Supplier<RpcServiceMetadata>() {
             @Override
             public RpcServiceMetadata get() {
index c61ec49..f2e4670 100644 (file)
@@ -9,16 +9,14 @@ package org.opendaylight.controller.sal.binding.impl;
 
 import static com.google.common.base.Preconditions.checkState;
 
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-
 import java.util.EventListener;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
-import java.util.WeakHashMap;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
@@ -29,6 +27,7 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistr
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier;
 import org.opendaylight.controller.sal.binding.api.rpc.RpcRouter;
+import org.opendaylight.controller.sal.binding.codegen.RpcIsNotRoutedException;
 import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeGenerator;
 import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper;
 import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
@@ -41,6 +40,13 @@ import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Throwables;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.util.concurrent.UncheckedExecutionException;
+
 public class RpcProviderRegistryImpl implements RpcProviderRegistry, RouteChangePublisher<RpcContextIdentifier, InstanceIdentifier<?>> {
 
     private RuntimeCodeGenerator rpcFactory = SingletonHolder.RPC_GENERATOR_IMPL;
@@ -56,7 +62,9 @@ public class RpcProviderRegistryImpl implements RpcProviderRegistry, RouteChange
                 }
             });
 
-    private final Map<Class<? extends RpcService>, RpcRouter<?>> rpcRouters = new WeakHashMap<>();
+    private final Cache<Class<? extends RpcService>, RpcRouter<?>> rpcRouters = CacheBuilder.newBuilder().weakKeys()
+            .build();
+
     private final ListenerRegistry<RouteChangeListener<RpcContextIdentifier, InstanceIdentifier<?>>> routeChangeListeners = ListenerRegistry
             .create();
     private final ListenerRegistry<RouterInstantiationListener> routerInstantiationListener = ListenerRegistry.create();
@@ -85,12 +93,20 @@ public class RpcProviderRegistryImpl implements RpcProviderRegistry, RouteChange
     @Override
     public final <T extends RpcService> RpcRegistration<T> addRpcImplementation(final Class<T> type, final T implementation)
             throws IllegalStateException {
-        @SuppressWarnings("unchecked")
-        RpcRouter<T> potentialRouter = (RpcRouter<T>) rpcRouters.get(type);
-        if (potentialRouter != null) {
+
+        // FIXME: This should be well documented - addRpcImplementation for
+        // routed RPCs
+        try {
+            // Note: If RPC is really global, expected count of registrations
+            // of this method is really low.
+            RpcRouter<T> potentialRouter = getRpcRouter(type);
             checkState(potentialRouter.getDefaultService() == null,
-                    "Default service for routed RPC already registered.");
+                        "Default service for routed RPC already registered.");
             return potentialRouter.registerDefaultService(implementation);
+        } catch (RpcIsNotRoutedException e) {
+            // NOOP - we could safely continue, since RPC is not routed
+            // so we fallback to global routing.
+            LOG.debug("RPC is not routed. Using global registration.",e);
         }
         T publicProxy = getRpcService(type);
         RpcService currentDelegate = RuntimeCodeHelper.getDelegate(publicProxy);
@@ -107,28 +123,37 @@ public class RpcProviderRegistryImpl implements RpcProviderRegistry, RouteChange
         return (T) publicProxies.getUnchecked(type);
     }
 
-    @SuppressWarnings({ "unchecked", "rawtypes" })
+
     public <T extends RpcService> RpcRouter<T> getRpcRouter(final Class<T> type) {
-        RpcRouter<?> potentialRouter = rpcRouters.get(type);
-        if (potentialRouter != null) {
-            return (RpcRouter<T>) potentialRouter;
-        }
-        synchronized (this) {
-            /**
-             * Potential Router could be instantiated by other thread while we
-             * were waiting for the lock.
-             */
-            potentialRouter = rpcRouters.get(type);
-            if (potentialRouter != null) {
-                return (RpcRouter<T>) potentialRouter;
+        try {
+            final AtomicBoolean created = new AtomicBoolean(false);
+            @SuppressWarnings( "unchecked")
+            // LoadingCache is unsuitable for RpcRouter since we need to distinguish
+            // first creation of RPC Router, so that is why
+            // we are using normal cache with load API and shared AtomicBoolean
+            // for this call, which will be set to true if router was created.
+            RpcRouter<T> router = (RpcRouter<T>) rpcRouters.get(type,new Callable<RpcRouter<?>>() {
+
+                @Override
+                public org.opendaylight.controller.sal.binding.api.rpc.RpcRouter<?> call()  {
+                    RpcRouter<?> router = rpcFactory.getRouterFor(type, name);
+                    router.registerRouteChangeListener(new RouteChangeForwarder<T>(type));
+                    LOG.debug("Registering router {} as global implementation of {} in {}", router, type.getSimpleName(), this);
+                    RuntimeCodeHelper.setDelegate(getRpcService(type), router.getInvocationProxy());
+                    created.set(true);
+                    return router;
+                }
+            });
+            if(created.get()) {
+                notifyListenersRoutedCreated(router);
             }
-            RpcRouter<T> router = rpcFactory.getRouterFor(type, name);
-            router.registerRouteChangeListener(new RouteChangeForwarder(type));
-            LOG.debug("Registering router {} as global implementation of {} in {}", router, type.getSimpleName(), this);
-            RuntimeCodeHelper.setDelegate(getRpcService(type), router.getInvocationProxy());
-            rpcRouters.put(type, router);
-            notifyListenersRoutedCreated(router);
             return router;
+        } catch (ExecutionException | UncheckedExecutionException e) {
+            // We rethrow Runtime Exceptions which were wrapped by
+            // Execution Exceptions
+            // otherwise we throw IllegalStateException with original
+            Throwables.propagateIfPossible(e.getCause());
+            throw new IllegalStateException("Could not load RPC Router for "+type.getName(),e);
         }
     }
 
@@ -159,7 +184,7 @@ public class RpcProviderRegistryImpl implements RpcProviderRegistry, RouteChange
             final RouterInstantiationListener listener) {
         ListenerRegistration<RouterInstantiationListener> reg = routerInstantiationListener.register(listener);
         try {
-            for (RpcRouter<?> router : rpcRouters.values()) {
+            for (RpcRouter<?> router : rpcRouters.asMap().values()) {
                 listener.onRpcRouterCreated(router);
             }
         } catch (Exception e) {
@@ -225,7 +250,7 @@ public class RpcProviderRegistryImpl implements RpcProviderRegistry, RouteChange
                 try {
                     listener.getInstance().onRouteChange(toPublish);
                 } catch (Exception e) {
-                    e.printStackTrace();
+                    LOG.error("Unhandled exception during invoking listener",listener.getInstance(),e);
                 }
             }
         }
index 110e5b4..8782046 100644 (file)
@@ -23,6 +23,7 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcR
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
 import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier;
 import org.opendaylight.controller.sal.binding.api.rpc.RpcRouter;
+import org.opendaylight.controller.sal.binding.codegen.RpcIsNotRoutedException;
 import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.bi.ba.rpcservice.rev140701.OpendaylightTestRpcServiceService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
@@ -77,6 +78,28 @@ public class RpcProviderRegistryTest {
         assertNotNull(regTwo);
     }
 
+    @Test
+    public void routedRpcRegisteredUsingGlobalAsDefaultInstance() throws Exception {
+        OpendaylightTestRoutedRpcService def = Mockito.mock(OpendaylightTestRoutedRpcService.class);
+        rpcRegistry.addRpcImplementation(OpendaylightTestRoutedRpcService.class, def);
+        RpcRouter<OpendaylightTestRoutedRpcService> router = rpcRegistry.getRpcRouter(OpendaylightTestRoutedRpcService.class);
+        assertEquals(def, router.getDefaultService());
+    }
+
+    @Test
+    public void nonRoutedRegisteredAsRouted() {
+        OpendaylightTestRpcServiceService one = Mockito.mock(OpendaylightTestRpcServiceService.class);
+        try {
+            rpcRegistry.addRoutedRpcImplementation(OpendaylightTestRpcServiceService.class, one);
+            fail("RpcIsNotRoutedException should be thrown");
+        } catch (RpcIsNotRoutedException e) {
+            assertNotNull(e.getMessage());
+        } catch (Exception e) {
+            fail("RpcIsNotRoutedException should be thrown");
+        }
+
+    }
+
     @Test
     public void testRpcRouterInstance() throws Exception  {
         OpendaylightTestRoutedRpcService def = Mockito.mock(OpendaylightTestRoutedRpcService.class);
index 4c5e3ab..148b33b 100644 (file)
@@ -37,6 +37,8 @@ public abstract class AbstractRpcExecutor implements RpcExecutor {
             throw new RestconfDocumentedException(e.getMessage(), ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
         } catch (UnsupportedOperationException e) {
             throw new RestconfDocumentedException(e.getMessage(), ErrorType.RPC, ErrorTag.OPERATION_NOT_SUPPORTED);
+        } catch (RestconfDocumentedException e) {
+            throw e;
         } catch (Exception e) {
             throw new RestconfDocumentedException("The operation encountered an unexpected error while executing.", e);
         }