Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpdobrev2008-02-13 08:41:38 +0000
committerpdobrev2008-02-13 08:41:38 +0000
commit23aa191052aa8547480db22bd674c867b1807a54 (patch)
tree69ad49a97174af89f7d037e82dcbe5b6fec7768c /bundles/org.eclipse.equinox.wireadmin
parentd4d5d549560c5f9b38512843b96c82af2721ad73 (diff)
downloadrt.equinox.bundles-23aa191052aa8547480db22bd674c867b1807a54.tar.gz
rt.equinox.bundles-23aa191052aa8547480db22bd674c867b1807a54.tar.xz
rt.equinox.bundles-23aa191052aa8547480db22bd674c867b1807a54.zip
Graduation of the bundle from the equinox.incubator
Diffstat (limited to 'bundles/org.eclipse.equinox.wireadmin')
-rw-r--r--bundles/org.eclipse.equinox.wireadmin/.classpath3
-rw-r--r--bundles/org.eclipse.equinox.wireadmin/.settings/org.eclipse.jdt.core.prefs53
-rw-r--r--bundles/org.eclipse.equinox.wireadmin/.settings/org.eclipse.jdt.ui.prefs51
-rw-r--r--bundles/org.eclipse.equinox.wireadmin/.settings/org.eclipse.pde.core.prefs3
-rw-r--r--bundles/org.eclipse.equinox.wireadmin/META-INF/MANIFEST.MF20
-rw-r--r--bundles/org.eclipse.equinox.wireadmin/OSGI-INF/permissions.perm1
-rw-r--r--bundles/org.eclipse.equinox.wireadmin/about.html28
-rw-r--r--bundles/org.eclipse.equinox.wireadmin/build.properties6
-rw-r--r--bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/Activator.java147
-rw-r--r--bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/EventDispatcher.java260
-rw-r--r--bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/NotificationEvent.java38
-rw-r--r--bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/TracerMap.java51
-rw-r--r--bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/WireAdminImpl.java596
-rw-r--r--bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/WireImpl.java846
-rw-r--r--bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/WireProperties.java40
-rw-r--r--bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/WireReDispatcher.java308
16 files changed, 2438 insertions, 13 deletions
diff --git a/bundles/org.eclipse.equinox.wireadmin/.classpath b/bundles/org.eclipse.equinox.wireadmin/.classpath
index acad1c22..755d49bc 100644
--- a/bundles/org.eclipse.equinox.wireadmin/.classpath
+++ b/bundles/org.eclipse.equinox.wireadmin/.classpath
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/OSGi%Minimum-1.0"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/bundles/org.eclipse.equinox.wireadmin/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.equinox.wireadmin/.settings/org.eclipse.jdt.core.prefs
index 8e08123e..d304116c 100644
--- a/bundles/org.eclipse.equinox.wireadmin/.settings/org.eclipse.jdt.core.prefs
+++ b/bundles/org.eclipse.equinox.wireadmin/.settings/org.eclipse.jdt.core.prefs
@@ -1,23 +1,49 @@
-#Mon Feb 26 10:38:55 EST 2007
+#Thu Aug 16 11:00:59 EDT 2007
eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.4
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=1000
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
-org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=error
org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
@@ -25,7 +51,6 @@ org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
-org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
@@ -37,16 +62,17 @@ org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled
org.eclipse.jdt.core.compiler.problem.unusedImport=error
-org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
-org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=enabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.3
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
@@ -292,9 +318,14 @@ org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.jdt.core.formatter.lineSplit=800
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false
org.eclipse.jdt.core.formatter.tabulation.char=tab
org.eclipse.jdt.core.formatter.tabulation.size=4
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
diff --git a/bundles/org.eclipse.equinox.wireadmin/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.equinox.wireadmin/.settings/org.eclipse.jdt.ui.prefs
index c621f7d2..023a27a6 100644
--- a/bundles/org.eclipse.equinox.wireadmin/.settings/org.eclipse.jdt.ui.prefs
+++ b/bundles/org.eclipse.equinox.wireadmin/.settings/org.eclipse.jdt.ui.prefs
@@ -1,8 +1,57 @@
-#Mon Feb 26 10:46:21 EST 2007
+#Tue Aug 21 11:19:11 CDT 2007
eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
formatter_profile=_core
formatter_settings_version=11
org.eclipse.jdt.ui.ignorelowercasenames=true
org.eclipse.jdt.ui.importorder=;
org.eclipse.jdt.ui.ondemandthreshold=3
org.eclipse.jdt.ui.staticondemandthreshold=99
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=false
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=false
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/bundles/org.eclipse.equinox.wireadmin/.settings/org.eclipse.pde.core.prefs b/bundles/org.eclipse.equinox.wireadmin/.settings/org.eclipse.pde.core.prefs
new file mode 100644
index 00000000..5e91ab0f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.wireadmin/.settings/org.eclipse.pde.core.prefs
@@ -0,0 +1,3 @@
+#Thu Mar 29 10:31:31 EEST 2007
+eclipse.preferences.version=1
+pluginProject.extensions=false
diff --git a/bundles/org.eclipse.equinox.wireadmin/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.wireadmin/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..8eb597e0
--- /dev/null
+++ b/bundles/org.eclipse.equinox.wireadmin/META-INF/MANIFEST.MF
@@ -0,0 +1,20 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Wire Admin Service
+Bundle-SymbolicName: org.eclipse.equinox.wireadmin
+Bundle-Version: 0.1.0.qualifier
+Bundle-Vendor: Eclipse
+Bundle-Description: This bundle provides utility classes for Producer and Consumer services.
+Bundle-Activator: org.eclipse.equinox.internal.wireadmin.Activator
+Import-Package: org.eclipse.equinox.internal.util.hash;version="1.0.0",
+ org.eclipse.equinox.internal.util.ref;version="1.0.0",
+ org.osgi.framework,
+ org.osgi.service.cm;version="1.2",
+ org.osgi.service.event;version="1.1",
+ org.osgi.service.wireadmin;version="1.0",
+ org.osgi.util.measurement;version="1.0",
+ org.osgi.util.tracker;version="1.3"
+Export-Package: org.eclipse.equinox.internal.wireadmin; x-internal:=true
+Bundle-RequiredExecutionEnvironment: OSGi/Minimum-1.0,
+ CDC-1.0/Foundation-1.0,
+ J2SE-1.3
diff --git a/bundles/org.eclipse.equinox.wireadmin/OSGI-INF/permissions.perm b/bundles/org.eclipse.equinox.wireadmin/OSGI-INF/permissions.perm
new file mode 100644
index 00000000..acbf7723
--- /dev/null
+++ b/bundles/org.eclipse.equinox.wireadmin/OSGI-INF/permissions.perm
@@ -0,0 +1 @@
+(java.security.AllPermission "*" "*")
diff --git a/bundles/org.eclipse.equinox.wireadmin/about.html b/bundles/org.eclipse.equinox.wireadmin/about.html
new file mode 100644
index 00000000..40e147d9
--- /dev/null
+++ b/bundles/org.eclipse.equinox.wireadmin/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>January 15, 2008</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
diff --git a/bundles/org.eclipse.equinox.wireadmin/build.properties b/bundles/org.eclipse.equinox.wireadmin/build.properties
new file mode 100644
index 00000000..9cbab3c1
--- /dev/null
+++ b/bundles/org.eclipse.equinox.wireadmin/build.properties
@@ -0,0 +1,6 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ about.html
+src.includes = about.html
diff --git a/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/Activator.java b/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/Activator.java
new file mode 100644
index 00000000..19e209d1
--- /dev/null
+++ b/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/Activator.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 1997-2007 by ProSyst Software GmbH
+ * http://www.prosyst.com
+ * 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
+ *
+ * Contributors:
+ * ProSyst Software GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.wireadmin;
+
+import org.eclipse.equinox.internal.util.ref.Log;
+import org.osgi.framework.*;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.wireadmin.*;
+
+/**
+ * @author Pavlin Dobrev
+ * @version 1.0
+ */
+
+public class Activator implements BundleActivator, ServiceListener, ServiceFactory {
+
+ static final String PREFIX = "[WireAdmin]: ";
+
+ public static boolean LOG_DEBUG;
+ static Log log;
+
+ private WireAdminImpl wireAdmin;
+ private ServiceReference cmRef;
+
+ public static BundleContext bc;
+
+ WireReDispatcher wireReDispatcher;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext bc) throws Exception {
+ Activator.bc = bc;
+ log = new Log(bc, false);
+ log.setPrintOnConsole(getBoolean("equinox.services.wireadmin.console"));
+
+ LOG_DEBUG = getBoolean("equinox.services.wireadmin.debug");
+ log.setDebug(LOG_DEBUG);
+
+ cmRef = bc.getServiceReference(ConfigurationAdmin.class.getName());
+
+ ConfigurationAdmin cm = null;
+ if (cmRef != null) {
+ cm = (ConfigurationAdmin) bc.getService(cmRef);
+ }
+
+ try {
+ bc.addServiceListener(this, '(' + Constants.OBJECTCLASS + '=' + ConfigurationAdmin.class.getName() + ')');
+ } catch (InvalidSyntaxException ise) {
+ /* syntax is valid */
+ }
+
+ wireAdmin = new WireAdminImpl(bc, cm);
+
+ try {
+ bc.addServiceListener(wireAdmin, "(|(" + Constants.OBJECTCLASS + '=' + WireAdminListener.class.getName() + ')' + '(' + Constants.OBJECTCLASS + '=' + Consumer.class.getName() + ')' + '(' + Constants.OBJECTCLASS + '=' + Producer.class.getName() + "))");
+ } catch (InvalidSyntaxException ise) {
+ /* syntax is valid */
+ // ise.printStackTrace();
+ }
+ wireReDispatcher = new WireReDispatcher();
+ wireReDispatcher.start(bc);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext bc) throws Exception {
+ if (wireReDispatcher != null) {
+ wireReDispatcher.stop();
+ wireReDispatcher = null;
+ }
+
+ wireAdmin.unregister();
+
+ bc.removeServiceListener(wireAdmin);
+ bc.removeServiceListener(this);
+
+ if (cmRef != null) {
+ bc.ungetService(cmRef);
+ cmRef = null;
+ }
+
+ log.close();
+ log = null;
+
+ wireAdmin = null;
+
+ bc = null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+ */
+ public void serviceChanged(ServiceEvent e) {
+ switch (e.getType()) {
+ case ServiceEvent.MODIFIED :
+ case ServiceEvent.REGISTERED :
+ this.cmRef = e.getServiceReference();
+ wireAdmin.cm = (ConfigurationAdmin) bc.getService(cmRef);
+ break;
+ case ServiceEvent.UNREGISTERING :
+ this.cmRef = null;
+ wireAdmin.cm = null;
+ break;
+ }
+ }
+
+ public Object getService(Bundle bundle, ServiceRegistration registration) {
+ return null;
+ }
+
+ public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
+ }
+
+ public static boolean getBoolean(String property) {
+ String prop = (bc != null) ? bc.getProperty(property) : System.getProperty(property);
+ return ((prop != null) && prop.equalsIgnoreCase("true"));
+ }
+
+ public static int getInteger(String property, int defaultValue) {
+ String prop = (bc != null) ? bc.getProperty(property) : System.getProperty(property);
+ if (prop != null) {
+ try {
+ return Integer.decode(prop).intValue();
+ } catch (NumberFormatException e) {
+ //do nothing
+ }
+ }
+ return defaultValue;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/EventDispatcher.java b/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/EventDispatcher.java
new file mode 100644
index 00000000..027325f4
--- /dev/null
+++ b/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/EventDispatcher.java
@@ -0,0 +1,260 @@
+/*******************************************************************************
+ * Copyright (c) 1997-2007 by ProSyst Software GmbH
+ * http://www.prosyst.com
+ * 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
+ *
+ * Contributors:
+ * ProSyst Software GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.wireadmin;
+
+import java.util.*;
+import org.osgi.framework.*;
+import org.osgi.service.wireadmin.*;
+
+/**
+ * This class is responsible for dispatching notifications to WireAdminListeners
+ * and Consumers and Producers.
+ *
+ * @author Stoyan Boshev
+ * @author Pavlin Dobrev
+ *
+ * @version 1.0
+ */
+public class EventDispatcher implements Runnable {
+
+ private BundleContext bc;
+
+ private WireAdminImpl wa;
+
+ private Hashtable refToList;
+
+ private Vector events;
+
+ private Object synch = new Object();
+ private Object listenersLock = new Object();
+
+ private boolean running = true;
+
+ private Thread dispatcher;
+
+ public EventDispatcher(BundleContext bc, WireAdminImpl wa) {
+ this.bc = bc;
+ this.wa = wa;
+ this.refToList = new Hashtable(5);
+ this.events = new Vector(5, 5);
+
+ ServiceReference[] sRefs = null;
+
+ try {
+ sRefs = bc.getServiceReferences(WireAdminListener.class.getName(), null);
+ } catch (InvalidSyntaxException ise) {
+ /* filter is null */
+ }
+
+ if (sRefs != null) {
+ WireAdminListener listener;
+
+ for (int i = 0; i < sRefs.length; i++) {
+ listener = (WireAdminListener) bc.getService(sRefs[i]);
+
+ if (listener != null) {
+ refToList.put(sRefs[i], listener);
+ }
+ }
+ }
+ dispatcher = new Thread(this, "[WireAdmin] - Event Dispatcher");
+ dispatcher.start();
+ }
+
+ void addEvent(WireAdminEvent evt) {
+ if (dispatcher == null) {
+ // synchronous
+ notifyListeners(new EventData(evt, refToList));
+ } else {
+ // synchronized (listenersLock) { //because it does not change the
+ // Hashtable;
+ events.addElement(new EventData(evt, refToList));
+ // }
+ synchronized (synch) {
+ synch.notify();
+ }
+ }
+ }
+
+ void addNotificationEvent(NotificationEvent ne) {
+ if (dispatcher == null) {
+ // synchronous
+ notifyConsumerProducer(ne);
+ } else {
+ events.addElement(ne);
+ synchronized (synch) {
+ synch.notify();
+ }
+ }
+ }
+
+ private String printWires(Wire[] wires) {
+ if (wires != null) {
+ StringBuffer buff = new StringBuffer(100);
+ buff.append("\n");
+ for (int i = 0; i < wires.length; i++) {
+ buff.append(wires[i]).append("\n");
+ }
+ return buff.toString();
+ }
+ return "null";
+ }
+
+ private void notifyConsumerProducer(NotificationEvent ne) {
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug("Notification event " + ((ne.producer != null) ? "; Producer " + ne.producer : "; Consumer " + ne.consumer) + "; source: " + ne.source + "; wires " + printWires(ne.wires), null);
+
+ Activator.log.debug(0, 10001, ((dispatcher != null) ? "asynchronous" : "synchronous"), null, false);
+ }
+ if (ne.producer != null) {
+ try {
+ ne.producer.consumersConnected(ne.wires);
+ } catch (Throwable t) {
+ wa.notifyListeners(ne.source, WireAdminEvent.PRODUCER_EXCEPTION, t);
+ }
+ } else if (ne.consumer != null) {
+ try {
+ ne.consumer.producersConnected(ne.wires);
+ } catch (Throwable t) {
+ wa.notifyListeners(ne.source, WireAdminEvent.CONSUMER_EXCEPTION, t);
+ }
+ }
+ }
+
+ private void notifyListeners(EventData event) {
+ WireAdminEvent evt = (WireAdminEvent) event.event;
+ Hashtable refToList = event.listeners;
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(0, 10002, getEvent(evt.getType()) + evt.getWire(), evt.getThrowable(), false);
+ Activator.log.debug(0, 10001, ((dispatcher != null) ? "asynchronous" : "synchronous"), null, false);
+ }
+
+ for (Enumeration en = refToList.keys(); running && en.hasMoreElements();) {
+ ServiceReference current = (ServiceReference) en.nextElement();
+ Integer accepts = (Integer) current.getProperty(WireConstants.WIREADMIN_EVENTS);
+ if ((accepts != null) && ((accepts.intValue() & evt.getType()) == evt.getType())) {
+ try {
+ ((WireAdminListener) refToList.get(current)).wireAdminEvent(evt);
+ } catch (Throwable t) {
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(0, 10003, ((WireAdminListener) refToList.get(current)).toString(), t, false);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @param ref
+ */
+ public void removeListener(ServiceReference ref) {
+ if (refToList.containsKey(ref)) {
+ synchronized (listenersLock) {
+ refToList = (Hashtable) refToList.clone();
+ if (refToList.remove(ref) != null) {
+ bc.ungetService(ref);
+ }
+ }
+ }
+ }
+
+ /**
+ * @param ref
+ * @param object
+ */
+ public void addListener(ServiceReference ref, Object object) {
+ synchronized (listenersLock) {
+ refToList = (Hashtable) refToList.clone();
+ refToList.put(ref, object);
+ }
+ }
+
+ public void run() {
+ while (running) {
+ synchronized (synch) {
+ while (running && events.size() == 0) {
+ try {
+ synch.wait();
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+
+ EventData evt = null;
+ NotificationEvent ne = null;
+ while (running && events.size() > 0) {
+ Object event = events.elementAt(0);
+ events.removeElementAt(0);
+ if (event instanceof EventData) {
+ evt = (EventData) event;
+ notifyListeners(evt);
+ } else {
+ ne = (NotificationEvent) event;
+ notifyConsumerProducer(ne);
+ }
+ }
+ }
+ }
+
+ void terminate() {
+ running = false;
+
+ if (dispatcher != null) {
+ synchronized (synch) {
+ synch.notify();
+ }
+ }
+
+ synchronized (listenersLock) {
+ for (Enumeration en = refToList.keys(); en.hasMoreElements();) {
+ bc.ungetService((ServiceReference) en.nextElement());
+ }
+ refToList.clear();
+ refToList = null;
+ }
+ events.removeAllElements();
+ events = null;
+ }
+
+ private String getEvent(int type) {
+ switch (type) {
+ case WireAdminEvent.WIRE_CREATED :
+ return "WIRE_CREATED";
+ case WireAdminEvent.WIRE_CONNECTED :
+ return "WIRE_CONNECTED";
+ case WireAdminEvent.WIRE_UPDATED :
+ return "WIRE_UPDATED";
+ case WireAdminEvent.WIRE_TRACE :
+ return "WIRE_TRACE";
+ case WireAdminEvent.WIRE_DISCONNECTED :
+ return "WIRE_DISCONNECTED";
+ case WireAdminEvent.WIRE_DELETED :
+ return "WIRE_DELETED";
+ case WireAdminEvent.PRODUCER_EXCEPTION :
+ return "PRODUCER_EXCEPTION";
+ case WireAdminEvent.CONSUMER_EXCEPTION :
+ return "CONSUMER_EXCEPTION";
+ default :
+ return null;
+ }
+ }
+
+ class EventData {
+ Object event;
+ Hashtable listeners;
+
+ public EventData(Object event, Hashtable listenersData) {
+ this.event = event;
+ listeners = listenersData;
+ }
+ }
+}
diff --git a/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/NotificationEvent.java b/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/NotificationEvent.java
new file mode 100644
index 00000000..679beaca
--- /dev/null
+++ b/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/NotificationEvent.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 1997-2007 by ProSyst Software GmbH
+ * http://www.prosyst.com
+ * 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
+ *
+ * Contributors:
+ * ProSyst Software GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.wireadmin;
+
+import org.osgi.service.wireadmin.*;
+
+/**
+ * This class holds the producer and consumer which have to be notified for
+ * changes in their wires
+ *
+ * @author Stoyan Boshev
+ * @author Pavlin Dobrev
+ * @version 1.0
+ */
+public class NotificationEvent {
+
+ Producer producer;
+ Consumer consumer;
+ Wire source;
+ Wire[] wires;
+
+ public NotificationEvent(Producer pr, Consumer cm, Wire source, Wire[] wires) {
+ producer = pr;
+ consumer = cm;
+ this.source = source;
+ this.wires = wires;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/TracerMap.java b/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/TracerMap.java
new file mode 100644
index 00000000..8324ac90
--- /dev/null
+++ b/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/TracerMap.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 1997-2007 by ProSyst Software GmbH
+ * http://www.prosyst.com
+ * 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
+ *
+ * Contributors:
+ * ProSyst Software GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.wireadmin;
+
+import org.eclipse.equinox.internal.util.hash.HashIntObjNS;
+
+/**
+ * @author Lubomir Mitev
+ * @author Pavlin Dobrev
+ * @version 1.0
+ */
+public class TracerMap {
+
+ public static HashIntObjNS getMap() {
+ HashIntObjNS map = new HashIntObjNS(18);
+
+ map.put(0, "WireAdmin");
+ map.put(10001, "Event model is ");
+ map.put(10002, "Event type / source : ");
+ map.put(10003, "Exception while notifying WireAdminListener: ");
+ map.put(10004, "Will create wire producerPID/consumerPID/props : ");
+ map.put(10005, "I/O error creating a configuration!");
+ map.put(10006, "Found case variants while updating wire properties");
+ map.put(10007, "deleting wire with pid ");
+ map.put(10008, "deleting complete");
+ map.put(10009, "Updating properties for wire with pid=");
+ map.put(10011, "Will set new properties for wire ");
+ map.put(10012, "Filter doesn't match value : ");
+ map.put(10013, "Wire started : ");
+ map.put(10014, "Disconnecting ");
+ map.put(10015, "Service is not connected to any producer/consumer : ");
+ map.put(10016, "The producer and consumer could not interoperate using wire ");
+ map.put(10017, "No ServiceReference for Wire events! event: ");
+ map.put(10018, "WireAdminEvent redispatched: ");
+
+ return map;
+ }
+
+ public static HashIntObjNS getStarts() {
+ return null;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/WireAdminImpl.java b/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/WireAdminImpl.java
new file mode 100644
index 00000000..4a04869f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/WireAdminImpl.java
@@ -0,0 +1,596 @@
+/*******************************************************************************
+ * Copyright (c) 1997-2007 by ProSyst Software GmbH
+ * http://www.prosyst.com
+ * 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
+ *
+ * Contributors:
+ * ProSyst Software GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.wireadmin;
+
+import java.io.IOException;
+import java.util.*;
+import org.osgi.framework.*;
+import org.osgi.service.cm.*;
+import org.osgi.service.wireadmin.*;
+
+/**
+ * Wire Admin service implementation
+ *
+ * @author Pavlin Dobrev
+ * @author Stoyan Boshev
+ * @version 1.0
+ */
+class WireAdminImpl implements WireAdmin, ManagedServiceFactory, ServiceListener {
+
+ private EventDispatcher evtDisp;
+
+ private static final String PID_PREFIX = "WA_GENERATED_PID_";
+ private static final String FACTORY_PID = "equinox.wireadmin.fpid";
+
+ private BundleContext bc;
+
+ ConfigurationAdmin cm;
+
+ private Hashtable wires; // maps wire pid to the WireImpl object
+ private ServiceRegistration regWireAdmin;
+ private ServiceRegistration regManagedFactory;
+
+ private Vector waitForUpdate = new Vector();
+
+ /**
+ * Constructs an <code>WireAdminImpl</code> object, which provides
+ * Framework with methods for manipulating a <code>Wire</code> objects.
+ * Initialazed are hashtables for storing created wires, wires per
+ * <code>Producer</code>, and wires per <code>Consumer</code>.
+ *
+ * @param bc
+ * is the BundleContext object used for interaction with
+ * Framework.
+ */
+
+ WireAdminImpl(BundleContext bc, ConfigurationAdmin cm) {
+ this.bc = bc;
+ this.cm = cm;
+ wires = new Hashtable();
+ evtDisp = new EventDispatcher(bc, this);
+
+ Hashtable props = new Hashtable(2, 1.0f);
+ props.put(Constants.SERVICE_PID, FACTORY_PID);
+ props.put("service.factoryPid", FACTORY_PID);
+
+ if (cm != null) {
+ try {
+ Configuration[] all = cm.listConfigurations("(service.factoryPid=" + FACTORY_PID + ")");
+ if (all != null) {
+ WireImpl wire;
+
+ for (int i = 0; i < all.length; i++) {
+ Dictionary properties = all[i].getProperties();
+ String pid = (String) properties.get(WireConstants.WIREADMIN_PID);
+
+ if (pid == null) {
+ pid = all[i].getPid();
+ properties.put(WireConstants.WIREADMIN_PID, pid);
+ }
+
+ wire = new WireImpl(bc, this, properties);
+ wires.put(pid, wire);
+ wire.start();
+ }
+ }
+ } catch (IOException ioe) {
+ /* blocking won't be made */
+ } catch (InvalidSyntaxException ise) {
+ /* syntax is valid */
+ }
+ }
+
+ // register as ManagedServiceFactory after loading the current config
+ // values and creating the wires !!!!!!!!
+ // This will not lead to bugs because of updating wire props while wire
+ // is not preloaded
+ regManagedFactory = bc.registerService(ManagedServiceFactory.class.getName(), this, props);
+ regWireAdmin = bc.registerService(WireAdmin.class.getName(), this, props);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.wireadmin.WireAdmin#createWire(java.lang.String,
+ * java.lang.String, java.util.Dictionary)
+ */
+ public Wire createWire(String producerPID, String consumerPID, Dictionary props) {
+ return createWire(producerPID, consumerPID, props, null);
+ }
+
+ private Wire createWire(String producerPID, String consumerPID, Dictionary props, String pid) {
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(0, 10004, producerPID + " / " + consumerPID + " / =" + props, null, false);
+ }
+
+ if ((pid == null) && (producerPID == null || consumerPID == null)) {
+ throw new IllegalArgumentException("PIDs can not be null");
+ }
+
+ if (props == null) {
+ props = new Hashtable(7, 1.0f);
+ } else if (caseVariants(props)) {
+ throw new IllegalArgumentException("Illegal wire properties. Two or more keys with the same value, or incorrect key type!");
+ }
+
+ if (pid == null) {
+ // put the keys
+ props.put(WireConstants.WIREADMIN_PRODUCER_PID, producerPID);
+ props.put(WireConstants.WIREADMIN_CONSUMER_PID, consumerPID);
+ }
+ WireImpl wire = null;
+
+ if (pid != null) {
+ wire = new WireImpl(bc, this, props);
+ wires.put(pid, wire);
+ wire.start();
+ } else if (cm != null) {
+ try {
+ Configuration config = cm.createFactoryConfiguration(FACTORY_PID);
+ props.put(WireConstants.WIREADMIN_PID, config.getPid());
+ wire = new WireImpl(bc, this, props);
+ /* Object oldWire = */wires.put(config.getPid(), wire);
+ // if (oldWire != null) {
+ // System.out.println("\n\n@@@@@@@@@@@@@@@@@@ Old wire lost!!!!
+ // Wire is "+oldWire);
+ // System.out.println("@@@@@@@@@@@@@@@@@@ New Wire is "+wire);
+ // }
+ wire.start();
+ waitForUpdate.addElement(wire);
+ config.update(props);
+ } catch (IOException ioe) {
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(0, 10005, null, ioe, false);
+ }
+ }
+ } else {
+ String wirePID = getNextPID();
+ props.put(WireConstants.WIREADMIN_PID, wirePID);
+ props.put("service.factoryPid", "equinox.wireadmin.fpid");
+ wire = new WireImpl(bc, this, props);
+ wires.put(wirePID, wire);
+ wire.start();
+
+ Activator.log.info(Activator.PREFIX + "CM not available! The created wire from Producer=" + producerPID + " and Consumer=" + consumerPID + " won't be presistently stored!");
+
+ }
+
+ notifyListeners(wire, WireAdminEvent.WIRE_CREATED, null);
+ return wire;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.wireadmin.WireAdmin#updateWire(org.osgi.service.wireadmin.Wire,
+ * java.util.Dictionary)
+ */
+ public void updateWire(Wire wire, Dictionary properties) {
+ WireImpl wireImpl = (WireImpl) wire;
+
+ if (wireImpl == null || !wireImpl.isValid) {// fix #1064
+ return;
+ }
+
+ if (properties == null) {
+ properties = new Hashtable(7, 1.0f);
+ }
+
+ for (Enumeration en = properties.keys(); en.hasMoreElements();) {
+ if (!(en.nextElement() instanceof String)) {
+ throw new IllegalArgumentException("Illegal keys, must be String type");
+ }
+ }
+
+ if (caseVariants(properties)) {
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(0, 10006, null, null, false);
+ }
+ throw new IllegalArgumentException("Found case variants in properties' keys");
+ }
+
+ String wirePID = (String) wire.getProperties().get(WireConstants.WIREADMIN_PID);
+
+ if ((cm != null) && (wirePID.charAt(0) != 'W')) {
+ // CM is available and this wire was not created
+ // when the CM was not available
+
+ wireImpl.setProperties(properties);
+ wires.put(wirePID, wire);
+ waitForUpdate.addElement(wire);
+
+ try {
+ Configuration conf = cm.getConfiguration(wirePID);
+ conf.update(properties);
+ } catch (IOException ioe) {
+ Activator.log.error(Activator.PREFIX + "I/O error updating configuration!", ioe);
+ }
+
+ } else {
+ // either CM is not available, or
+ // this wire was created when CM was not available
+ wires.remove(wirePID);
+ wireImpl.setProperties(properties);
+ wires.put(wirePID, wire);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.wireadmin.WireAdmin#deleteWire(org.osgi.service.wireadmin.Wire)
+ */
+ public void deleteWire(Wire wire) {
+ WireImpl wireImpl = (WireImpl) wire;
+ try {
+ if (cm != null) {
+ Configuration current = cm.getConfiguration(wireImpl.getWirePID());
+ if (current != null) {
+ current.delete();
+ }
+ } else {
+ disconnectWire(wireImpl);
+ }
+ } catch (IOException ioe) {
+ Activator.log.error(Activator.PREFIX + "I/O error getting a configuration!", ioe);
+ }
+ }
+
+ private Wire[] getWires(String pid, boolean isProducer) throws InvalidSyntaxException {
+ if (isProducer) {
+ return getWires('(' + WireConstants.WIREADMIN_PRODUCER_PID + '=' + WireImpl.escapeSpecialCharacters(pid) + ')');
+ }
+
+ return getWires('(' + WireConstants.WIREADMIN_CONSUMER_PID + '=' + WireImpl.escapeSpecialCharacters(pid) + ')');
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.wireadmin.WireAdmin#getWires(java.lang.String)
+ */
+ public Wire[] getWires(String filterString) throws InvalidSyntaxException {
+ if (filterString == null) {
+ return getAllWires();
+ }
+
+ Filter filter = bc.createFilter(filterString);
+
+ if (filter == null) {
+ return getAllWires();
+ }
+
+ Vector tmp = new Vector();
+
+ synchronized (wires) {
+ for (Enumeration en = wires.elements(); en.hasMoreElements();) {
+ Wire wire = (Wire) en.nextElement();
+ Dictionary wireProps = wire.getProperties();
+
+ if (wire.isValid() && filter.match(wireProps)) {
+ tmp.addElement(wire);
+ }
+ }
+ }
+
+ if (tmp.size() == 0) {
+ return null;
+ }
+
+ Wire[] allWires = new Wire[tmp.size()];
+ tmp.copyInto(allWires);
+ return allWires;
+ }
+
+ private Wire[] getAllWires() {
+ if (wires.isEmpty()) {
+ return null;
+ }
+
+ Vector tmp = new Vector();
+
+ synchronized (wires) {
+ for (Enumeration en = wires.elements(); en.hasMoreElements();) {
+ Wire wire = (Wire) en.nextElement();
+ if (wire.isValid()) {
+ tmp.addElement(wire);
+ }
+ }
+ }
+
+ if (tmp.size() == 0) {
+ return null;
+ }
+
+ Wire[] allWires = new Wire[tmp.size()];
+ tmp.copyInto(allWires);
+ return allWires;
+ }
+
+ private void disconnectWire(WireImpl wire) {
+ if (wires == null) {
+ return;
+ }
+ Object result = wires.remove(wire.getWirePID());// Property(WireConstants.WIREADMIN_PID));
+ if (result != null) { // the wire existed
+ boolean wasConnected = wire.isConnected();
+ wire.stop();
+ if (wasConnected) {
+ notifyListeners(wire, WireAdminEvent.WIRE_DISCONNECTED, null);
+ }
+ notifyListeners(wire, WireAdminEvent.WIRE_DELETED, null);
+ }
+ }
+
+ Wire[] getConnected(String key, String value) {
+ if (key == null || value == null || wires.isEmpty()) {
+ return null;
+ }
+
+ Vector connected = new Vector();
+
+ synchronized (wires) {
+ for (Enumeration en = wires.elements(); en.hasMoreElements();) {
+ WireImpl w = (WireImpl) en.nextElement();
+ if (w.isValid() && w.isConnected() && value.equals(w.getProperties().get(key))) {
+ connected.addElement(w);
+ }
+ }
+ }
+
+ if (connected.isEmpty()) {
+ return null;
+ }
+
+ Wire[] cw = new Wire[connected.size()];
+ connected.copyInto(cw);
+ return cw;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.cm.ManagedServiceFactory#deleted(java.lang.String)
+ */
+ public void deleted(String pid) {
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(0, 10007, pid, null, false);
+ }
+
+ if (wires == null) {
+ return;
+ }
+ WireImpl wire = (WireImpl) wires.get(pid);
+ disconnectWire(wire);
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(0, 10008, null, null, false);
+ }
+ }
+
+ public String getName() {
+ return "WireAdmin Configuration Factory";
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.cm.ManagedServiceFactory#updated(java.lang.String,
+ * java.util.Dictionary)
+ */
+ public void updated(String pid, Dictionary properties) throws ConfigurationException {
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(0, 10009, pid, null, false);
+ Activator.log.debug(Activator.PREFIX + " " + properties, null);
+ }
+
+ String consumerPID = (String) properties.get(WireConstants.WIREADMIN_CONSUMER_PID);
+
+ if (consumerPID == null) {
+ throw new ConfigurationException(WireConstants.WIREADMIN_CONSUMER_PID, "is not provided");
+ }
+
+ String producerPID = (String) properties.get(WireConstants.WIREADMIN_PRODUCER_PID);
+
+ if (producerPID == null) {
+ throw new ConfigurationException(WireConstants.WIREADMIN_PRODUCER_PID, "is not provided");
+ }
+
+ properties.put(WireConstants.WIREADMIN_PID, pid);
+
+ if (wires == null) {
+ return;
+ }
+
+ WireImpl wire = (WireImpl) wires.get(pid);
+
+ if (wire != null) {
+ if (waitForUpdate.contains(wire)) {
+ // skip the first update after the wire was created
+ // or after the wire properties were updated
+ waitForUpdate.removeElement(wire);
+ } else {
+ // updating properties
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(0, 10011, wire.toString(), null, false);
+ }
+ wire.setProperties(properties);
+ }
+ } else {
+ createWire(producerPID, consumerPID, properties, pid);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+ */
+ public void serviceChanged(ServiceEvent event) {
+ int type = event.getType();
+ ServiceReference ref = event.getServiceReference();
+
+ if (type == ServiceEvent.UNREGISTERING) {
+ // presume that the unregistered service is a WireAdminListener
+ // service
+ evtDisp.removeListener(ref);
+ return;
+ }
+
+ Object service = bc.getService(ref);
+
+ if (type == ServiceEvent.REGISTERED) {
+ if (service instanceof WireAdminListener) {
+ evtDisp.addListener(ref, bc.getService(ref));
+ }
+
+ if (service instanceof Producer) {
+ Wire[] wires = null;
+ try {
+ wires = getWires((String) ref.getProperty(Constants.SERVICE_PID), true);
+ } catch (InvalidSyntaxException ise) {
+ /* syntax is valid */
+ }
+ boolean doNotify = true;
+ if (wires != null) {
+ // there are wires, which may become connected
+ for (int i = 0; i < wires.length; i++) {
+ if (((WireImpl) wires[i]).consumerRef != null) {
+ // there is wire which will become (or is) connected
+ doNotify = false;
+ }
+ }
+ }
+ if (doNotify) {
+ notifyConsumerProducer(new NotificationEvent((Producer) service, null, null, null));
+ }
+ }
+
+ if (service instanceof Consumer) {
+ Wire[] wires = null;
+ try {
+ wires = getWires((String) ref.getProperty(Constants.SERVICE_PID), false);
+ } catch (InvalidSyntaxException ise) {
+ /* syntax is valid */
+ }
+
+ boolean doNotify = true;
+ if (wires != null) {
+ // there are wires, which may become connected
+ for (int i = 0; i < wires.length; i++) {
+ if (((WireImpl) wires[i]).producerRef != null) {
+ // there is wire which will become (or is) connected
+ doNotify = false;
+ }
+ }
+ }
+ if (doNotify) {
+ notifyConsumerProducer(new NotificationEvent(null, (Consumer) service, null, null));
+ }
+ }
+ }
+ }
+
+ // Utility methods
+ /**
+ * Sends a <code>WireAdminEvent</code> to all services registered as
+ * <code>WireAdminListener</code>
+ *
+ * @param type
+ * is the type of the <code>WireAdminEvent</code> that must be
+ * sent.
+ */
+ void notifyListeners(Wire src, int type, Throwable t) {
+ if (regWireAdmin == null) {
+ return;
+ }
+ evtDisp.addEvent(new WireAdminEvent(regWireAdmin.getReference(), type, src, t));
+ }
+
+ void notifyConsumerProducer(NotificationEvent ne) {
+ evtDisp.addNotificationEvent(ne);
+ }
+
+ void unregister() {
+
+ if (regWireAdmin != null) {
+ regWireAdmin.unregister();
+ regWireAdmin = null;
+ }
+ if (regManagedFactory != null) {
+ regManagedFactory.unregister();
+ regManagedFactory = null;
+ }
+
+ // disconnect all running wires
+ synchronized (wires) {
+ for (Enumeration en = wires.elements(); en.hasMoreElements();) {
+ disconnectWire((WireImpl) en.nextElement());
+ }
+ }
+
+ // stop event dispatcher
+ evtDisp.terminate();
+
+ cm = null;
+ wires.clear();
+ wires = null;
+ bc = null;
+ }
+
+ private static boolean caseVariants(Dictionary props) {
+ int k = 0;
+ int size = props.size();
+ String[] keys = new String[size];
+
+ try {
+ for (Enumeration en = props.keys(); en.hasMoreElements();) {
+ keys[k] = (String) en.nextElement();
+ k++;
+ }
+ } catch (ClassCastException cce) {
+ return true;
+ }
+ int j;
+
+ for (int i = 0; i < size; i++) {
+ for (j = i + 1; j < size; j++) {
+ if (keys[i].equalsIgnoreCase(keys[j])) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static String getNextPID() {
+ return PID_PREFIX + System.currentTimeMillis();
+ }
+
+ boolean hasAConnectedWire(boolean isProducer, String pid) {
+ String cPid;
+ synchronized (wires) {
+ for (Enumeration en = wires.elements(); en.hasMoreElements();) {
+ WireImpl wire = (WireImpl) en.nextElement();
+
+ if (wire.isValid() && wire.isConnected()) {
+ cPid = (String) wire.getProperties().get(isProducer ? WireConstants.WIREADMIN_PRODUCER_PID : WireConstants.WIREADMIN_CONSUMER_PID);
+ if (cPid.equals(pid)) {
+ return true;
+ }
+ }
+ }
+ }
+ // none of the wires in wich this service takes part
+ // will become connected after it's registering
+ return false;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/WireImpl.java b/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/WireImpl.java
new file mode 100644
index 00000000..d039602f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/WireImpl.java
@@ -0,0 +1,846 @@
+/*******************************************************************************
+ * Copyright (c) 1997-2007 by ProSyst Software GmbH
+ * http://www.prosyst.com
+ * 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
+ *
+ * Contributors:
+ * ProSyst Software GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.wireadmin;
+
+import java.util.*;
+import org.osgi.framework.*;
+import org.osgi.service.wireadmin.*;
+
+/**
+ * @author Pavlin Dobrev
+ * @version 1.0
+ */
+
+class WireImpl implements Wire, ServiceListener {
+
+ private BundleContext bc;
+
+ /** Holds all the properties associated with this <code>Wire</code> object */
+ private WireProperties properties;
+
+ /** Holds a service reference to the associated <code>Producer</code> */
+ ServiceReference producerRef;
+
+ /** Holds a service reference to the associated <code>Consumer</code> */
+ ServiceReference consumerRef;
+
+ private Producer producer;
+ private Consumer consumer;
+
+ private Class[] flavors;
+
+ /** Holds the last value passed through this <code>Wire</code>. */
+ private Object lastValue;
+
+ private Vector envelopes;
+
+ /**
+ * <code>WireAdmin</code> object whit which this <code>Wire</code> was
+ * created.
+ */
+ private WireAdminImpl parent;
+
+ private Filter filter = null;
+
+ /** Holds the time of last <code>Consumer</code> update in milliseconds */
+ private long lastUpdateTime = -1;
+
+ /** Holds the available wire values (filter attributes) */
+ private Hashtable wireValues;
+
+ /* holds a list of scopes */
+ private String[] scope;
+
+ /** Indicates that this <code>Wire</code> object has been deleted */
+ boolean isValid = true;
+
+ private boolean interoperate = true;
+
+ private boolean allAccepted = true;
+
+ /**
+ * Creates a <code>Wire</code> object, representing a connection between a
+ * <code>Producer</code> and <code>Consumer</code>.
+ *
+ * @param bc
+ * is the Wiring <code>BundleContext</code>.
+ * @param parent
+ * is the <code>WireAdmin</code> which is the creator of this
+ * <code>Wire</code>.
+ * @param wirePID
+ * is a <code>String</code> holding a unique presistent
+ * identifier of this <code>Wire</code>, generated by the
+ * parent <code>WireAdmin</code>.
+ * @param properties
+ * is a collection of the initial wire properties.
+ */
+ WireImpl(BundleContext bc, WireAdminImpl parent, Dictionary properties) {
+ this.bc = bc;
+ this.parent = parent;
+ this.properties = new WireProperties();
+
+ for (Enumeration en = properties.keys(); en.hasMoreElements();) {
+ Object key = en.nextElement();
+ this.properties.put0(key, properties.get(key));
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.wireadmin.Wire#isValid()
+ */
+ public boolean isValid() {
+ return isValid;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.wireadmin.Wire#getFlavors()
+ */
+ public Class[] getFlavors() {
+ return isConnected() ? flavors : null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.wireadmin.Wire#getProperties()
+ */
+ public Dictionary getProperties() {
+ return properties;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.wireadmin.Wire#getLastValue()
+ */
+ public synchronized Object getLastValue() {
+ return lastValue;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.wireadmin.Wire#update(java.lang.Object)
+ */
+ public synchronized void update(Object value) {
+ if (!isConnected() || !interoperate || !isAcceptable(value)) {
+ return;
+ }
+
+ if (value instanceof Envelope) {
+ Envelope e = (Envelope) value;
+ if (!hasScope(e.getScope())) {
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(Activator.PREFIX + "Try to pass a value in an Envelop without permission, silent return.", null);
+ }
+ return;
+ }
+ }
+
+ if (filter != null) {
+
+ wireValues.put(WireConstants.WIREVALUE_CURRENT, value);
+
+ // #3329
+ if (lastValue != null) {
+ wireValues.put(WireConstants.WIREVALUE_PREVIOUS, lastValue);
+ wireValues.put(WireConstants.WIREVALUE_ELAPSED, new Long(System.currentTimeMillis() - lastUpdateTime));
+ }
+
+ if (Number.class.isInstance(value) && Number.class.isInstance(lastValue)) {
+ double val = ((Number) value).doubleValue();
+ double lastVal = ((Number) lastValue).doubleValue();
+
+ wireValues.put(WireConstants.WIREVALUE_DELTA_ABSOLUTE, new Double(Math.abs(val - lastVal)));
+ // #3328
+ wireValues.put(WireConstants.WIREVALUE_DELTA_RELATIVE, new Double(Math.abs(1 - lastVal / val)));
+ } else {
+ wireValues.remove(WireConstants.WIREVALUE_DELTA_ABSOLUTE);
+ wireValues.remove(WireConstants.WIREVALUE_DELTA_RELATIVE);
+ }
+
+ if (!filter.match(wireValues)) {
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(0, 10012, filter + " / " + value, null, false);
+ }
+ return;
+ }
+ }
+
+ if (consumer != null) {
+ try {
+ consumer.updated(this, value);
+ } catch (Throwable t) {
+ parent.notifyListeners(this, WireAdminEvent.CONSUMER_EXCEPTION, t);
+ return;
+ }
+ lastValue = value;
+ lastUpdateTime = System.currentTimeMillis();
+ parent.notifyListeners(this, WireAdminEvent.WIRE_TRACE, null);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.wireadmin.Wire#poll()
+ */
+ public synchronized Object poll() {
+ Object value = null;
+ if (isConnected() && interoperate) {
+ try {
+ value = producer.polled(this);
+ } catch (Throwable t) {
+ // no exception in the Producer must prevent correct Wire
+ // functioning
+ parent.notifyListeners(this, WireAdminEvent.PRODUCER_EXCEPTION, t);
+ return null;
+ }
+ parent.notifyListeners(this, WireAdminEvent.WIRE_TRACE, null);
+ if (!isAcceptable(value) && (!(value instanceof Envelope[]))) {
+ value = null;
+ }
+ }
+
+ if (value != null) {
+ lastValue = value;
+ if (value instanceof Envelope[]) {
+
+ if (allAccepted) {
+ return value;
+ }
+ Envelope[] envs = (Envelope[]) value;
+ if (scope == null) {
+ return value;
+ }
+
+ if (envelopes == null) {
+ envelopes = new Vector(envs.length);
+ }
+ boolean changed = false;
+ for (int i = 0; i < envs.length; i++) {
+ if (hasScope(envs[i].getScope())) {
+ envelopes.addElement(envs[i]);
+ } else {
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ value = new Envelope[envelopes.size()];
+ envelopes.copyInto((Envelope[]) value);
+ envelopes.removeAllElements();
+ }
+ }
+ }
+ return value;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.wireadmin.Wire#isConnected()
+ */
+ public boolean isConnected() {
+ return isValid && (consumerRef != null) && (producerRef != null);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.wireadmin.Wire#getScope()
+ */
+ public synchronized String[] getScope() {
+ return scope;
+ }
+
+ private void setScope() {
+ if ((producerRef == null) || (consumerRef == null)) {
+ return;
+ }
+
+ Vector prodScope = checkPermission((String[]) producerRef.getProperty(WireConstants.WIREADMIN_PRODUCER_SCOPE), WirePermission.PRODUCE, producerRef.getBundle());
+
+ Vector consScope = checkPermission((String[]) consumerRef.getProperty(WireConstants.WIREADMIN_CONSUMER_SCOPE), WirePermission.CONSUME, consumerRef.getBundle());
+
+ if ((prodScope == null) || (consScope == null)) {
+ return;
+ }
+
+ if ((consScope.size() == 1) && consScope.elementAt(0).equals("*")) {
+ scope = new String[prodScope.size()];
+ prodScope.copyInto(scope);
+ return;
+ }
+
+ if ((prodScope.size() != ((String[]) producerRef.getProperty(WireConstants.WIREADMIN_PRODUCER_SCOPE)).length) || (consScope.size() != ((String[]) consumerRef.getProperty(WireConstants.WIREADMIN_CONSUMER_SCOPE)).length)) {
+ this.allAccepted = false;
+ }
+
+ Vector cloning = (Vector) prodScope.clone();
+
+ for (Enumeration en = cloning.elements(); en.hasMoreElements();) {
+ Object next = en.nextElement();
+ if (!consScope.contains(next)) {
+ prodScope.removeElement(next);
+ this.allAccepted = false;
+ }
+ }
+
+ scope = new String[prodScope.size()];
+ prodScope.copyInto(scope);
+ }
+
+ private static Vector checkPermission(String[] scope, String action, Bundle b) {
+ if (scope == null) {
+ return null;
+ }
+
+ Vector v = new Vector();
+ for (int i = 0; i < scope.length; i++) {
+ WirePermission wp = new WirePermission(scope[i], action);
+ if (b.hasPermission(wp)) {
+ v.addElement(scope[i]);
+ }
+ }
+ return v;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.wireadmin.Wire#hasScope(java.lang.String)
+ */
+ public boolean hasScope(String name) {
+ if ((scope == null) || ((scope.length == 1) && scope[0].equals("*"))) {
+ return true;
+ }
+
+ for (int i = 0; i < scope.length; i++) {
+ if (name.equals(scope[i]) || scope[i].equals(WireConstants.WIREADMIN_SCOPE_ALL[0])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Utility methods
+ /**
+ * Creates a string representation for this <code>Wire</code>
+ *
+ * @return a string representation of this object.
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer(100);
+ sb.append("Wire[PID=");
+ sb.append(properties.get(WireConstants.WIREADMIN_PID));
+ sb.append(";prodPID=");
+ sb.append(properties.get(WireConstants.WIREADMIN_PRODUCER_PID));
+ sb.append(";consPID=");
+ sb.append(properties.get(WireConstants.WIREADMIN_CONSUMER_PID));
+ sb.append(";connected=");
+ sb.append(isConnected());
+ // sb.append(";valid=");
+ // sb.append(isValid());
+ // sb.append(";Scope={");
+ // if (scope == null) {
+ // sb.append("null");
+ // } else {
+ // for (int i = 0; i < scope.length; i++) {
+ // sb.append(scope[i]);
+ // if (i != scope.length - 2) {
+ // sb.append(", ");
+ // }
+ // }
+ // }
+ sb.append("}]");
+
+ return sb.toString();
+ }
+
+ /**
+ * This method starts tracking of
+ * <code>Producer</code> <code>Consumer</code>services associated with
+ * this <code>Wire</code> object. First we check if there are already such
+ * services started on the framework, after that two
+ * <code>ServiceTracker</code> objects are created to handle
+ * <code>Producer</code> and <code>Consumer</code> service tracking.
+ */
+ synchronized void start() {
+ String producerPID = (String) properties.get(WireConstants.WIREADMIN_PRODUCER_PID);
+ String consumerPID = (String) properties.get(WireConstants.WIREADMIN_CONSUMER_PID);
+ updateListenerFilter();
+ // check if there are such services already started
+ ServiceReference ref = getSingleRef(Producer.class.getName(), producerPID);
+
+ if (ref != null) {
+ serviceRegistered(ref);
+ }
+
+ ref = getSingleRef(Consumer.class.getName(), consumerPID);
+
+ if (ref != null) {
+ serviceRegistered(ref);
+ }
+
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(0, 10013, properties.get(WireConstants.WIREADMIN_PID).toString(), null, false);
+ }
+ }
+
+ void updateListenerFilter() {
+ String producerPID = escapeSpecialCharacters((String) properties.get(WireConstants.WIREADMIN_PRODUCER_PID));
+ String consumerPID = escapeSpecialCharacters((String) properties.get(WireConstants.WIREADMIN_CONSUMER_PID));
+
+ try {
+ // Create filter for tracking services regstered as Consumer's with
+ // the current
+ // WIRE_CONSUMER_PID and as Producer's with current
+ // WIRE_PRODUCER_PID
+ // escaping *, ) and ( in the pid.
+ StringBuffer sb = new StringBuffer();// "(");
+ sb.append('(');
+ sb.append('|');
+
+ sb.append('(').append('&');
+ sb.append('(').append(Constants.SERVICE_PID).append('=').append(consumerPID).append(')');
+ sb.append('(').append(Constants.OBJECTCLASS).append('=').append(Consumer.class.getName()).append(')');
+ sb.append(')');
+
+ sb.append('(').append('&');
+ sb.append('(').append(Constants.SERVICE_PID).append('=').append(producerPID).append(')');
+ sb.append('(').append(Constants.OBJECTCLASS).append('=').append(Producer.class.getName()).append(')');
+ sb.append(')');
+
+ if (consumerRef != null) {// in case service.pid changes
+ Long id = (Long) consumerRef.getProperty(Constants.SERVICE_ID);
+ sb.append('(').append(Constants.SERVICE_ID).append('=').append(id).append(')');
+ }
+
+ if (producerRef != null) {// in case service.pid changes
+ Long id = (Long) producerRef.getProperty(Constants.SERVICE_ID);
+ sb.append('(').append(Constants.SERVICE_ID).append('=').append(id).append(')');
+ }
+
+ sb.append(')');
+
+ // System.out.println("Filter is: " + sb.toString());
+
+ bc.addServiceListener(this, sb.toString());
+ } catch (InvalidSyntaxException ise) {
+ /* Syntax is valid */
+ }
+
+ }
+
+ private ServiceReference getSingleRef(String clazz, String pid) {
+ ServiceReference[] ref = null;
+
+ try {
+ ref = bc.getServiceReferences(clazz, "(" + Constants.SERVICE_PID + "=" + escapeSpecialCharacters(pid) + ")");
+ } catch (InvalidSyntaxException e) {
+ }
+
+ if (ref != null) {
+ if (ref.length > 1) {
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(Activator.PREFIX + "Found more than one " + clazz + " services registered with the same pid: " + pid + "Wire was not created, please unregister all services which duplicate the pid.", null);
+ }
+
+ parent.deleteWire(this);
+ } else if (ref.length == 1) {
+ return ref[0];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Stops service tracking, removes this <code>Wire</code> from the wire
+ * lists of the associated Consumer and Producer services and informs them
+ * for disconnecting.
+ */
+ synchronized void stop() {
+ if (!isValid)
+ return; // already stopped
+
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(0, 10014, this.toString(), null, false);
+ }
+ bc.removeServiceListener(this);
+ if ((producerRef != null) && (consumerRef != null)) {
+ // if this wire was connected
+ isValid = false;
+ informServices();
+ }
+ isValid = false;
+
+ if (producerRef != null) {
+ bc.ungetService(producerRef);
+ }
+ if (consumerRef != null) {
+ bc.ungetService(consumerRef);
+ }
+
+ // let gc do his work
+ producerRef = null;
+ consumerRef = null;
+
+ producer = null;
+ consumer = null;
+
+ lastValue = null;
+ parent = null;
+ filter = null;
+ wireValues = null;
+ scope = null;
+ bc = null;
+ }
+
+ /**
+ * This method is invoked when the Wiring tracker detects a service
+ * registration or when the Wire is created The service type is determined
+ * (Producer or Consumer) and added to this <code>Wire</code>. Both
+ * Consumer and Producer (if available) are informed for connecting.
+ *
+ * @param sRef
+ * the service reference of the wire's producer or consumer
+ * @param notifyService
+ * specifies whether notification of the Producer/Consumer is
+ * necessary if it is the only one available part.
+ */
+ private void serviceRegistered(ServiceReference sRef) {
+ String pid = (String) sRef.getProperty(Constants.SERVICE_PID);
+
+ if (pid.equals(properties.get(WireConstants.WIREADMIN_PRODUCER_PID))) {
+ if (producerRef == null) {
+ this.producerRef = sRef;
+ this.producer = (Producer) bc.getService(producerRef);
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(Activator.PREFIX + "Wire " + properties.get(WireConstants.WIREADMIN_PID) + " detected producer " + pid, null);
+ }
+ } else
+ return;
+ } else {
+ if (consumerRef == null) {
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(Activator.PREFIX + "Wire " + properties.get(WireConstants.WIREADMIN_PID) + " detected consumer " + pid, null);
+ }
+ this.consumerRef = sRef;
+ this.consumer = (Consumer) bc.getService(consumerRef);
+ try {
+ this.flavors = (Class[]) consumerRef.getProperty(WireConstants.WIREADMIN_CONSUMER_FLAVORS);
+ } catch (ClassCastException cce) {
+ /* won't be initialized */
+ }
+ } else
+ return;
+ }
+
+ if (isConnected()) {
+ // inform the Producer/Consumer for connecting
+ setScope();
+ informServices();
+ parent.notifyListeners(this, WireAdminEvent.WIRE_CONNECTED, null);
+ checkInteroperability();
+ } else if (!parent.hasAConnectedWire(pid.equals(properties.get(WireConstants.WIREADMIN_PRODUCER_PID)), pid)) {
+ // this service has no connected wire objects attached to it
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(0, 10015, pid, null, false);
+ }
+ // if (notifyService) { // The service is notified if it is only
+ // just registered
+ // informServices();
+ // }
+ }
+
+ updateListenerFilter();
+ checkWireFilter();
+ }
+
+ private void checkWireFilter() {
+ boolean performFiltering = ((producerRef != null) && producerRef.getProperty(WireConstants.WIREADMIN_PRODUCER_FILTERS) == null) && (properties.get(WireConstants.WIREADMIN_FILTER) != null);
+
+ if (performFiltering) {
+ if ((wireValues == null)) {
+ wireValues = new Hashtable(6, 1.0f);
+ }
+
+ try {
+ filter = bc.createFilter((String) properties.get(WireConstants.WIREADMIN_FILTER));
+ } catch (InvalidSyntaxException ise) {
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(Activator.PREFIX + "Filter syntax is invalid, filtering won't be made", null);
+ }
+ }
+ } else {
+ filter = null;
+ }
+ }
+
+ private void serviceModified(ServiceReference sRef) { // fix #1073
+ String pid = (String) sRef.getProperty(Constants.SERVICE_PID);
+
+ if (sRef.equals(producerRef)) {
+ String currentPID = (String) properties.get(WireConstants.WIREADMIN_PRODUCER_PID);
+
+ if (!currentPID.equals(pid)) {
+ // System.out.println("The pid of the PRODUCER is changed");
+ serviceUnregistered(sRef);
+ return;
+ }
+ }
+
+ if (sRef.equals(consumerRef)) {
+ String currentPID = (String) properties.get(WireConstants.WIREADMIN_CONSUMER_PID);
+
+ if (!currentPID.equals(pid)) {
+ serviceUnregistered(sRef);
+ // System.out.println("The pid of the CONSUMER is changed");
+ return;
+ }
+ try {
+ this.flavors = (Class[]) consumerRef.getProperty(WireConstants.WIREADMIN_CONSUMER_FLAVORS);
+ } catch (ClassCastException cce) {
+ /* won't be initialized */
+ }
+ }
+
+ if (producerRef == null || consumerRef == null) {
+ // System.out.println("Check if PID is BACK");
+ serviceRegistered(sRef);
+ return;
+ }
+
+ if (!isConnected()) {
+ return;
+ }
+
+ setScope();
+ checkInteroperability();
+ checkWireFilter();
+ }
+
+ private void checkInteroperability() {
+ String[] p = (String[]) producerRef.getProperty(WireConstants.WIREADMIN_PRODUCER_COMPOSITE);
+ String[] c = (String[]) consumerRef.getProperty(WireConstants.WIREADMIN_CONSUMER_COMPOSITE);
+
+ if ((p != null) && (c != null)) {
+ for (int i = 0; i < p.length; i++) {
+ for (int j = 0; j < c.length; j++) {
+ if (p[i].equals(c[j])) {
+ // found at least one match
+ interoperate = true;
+ return;
+ }
+ }
+ }
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(0, 10016, this.toString(), null, false);
+ }
+ interoperate = false;
+ } else {
+ interoperate = true;
+ }
+ }
+
+ private void serviceUnregistered(ServiceReference sRef) {
+ boolean lastStatus = isConnected();
+
+ if (sRef.equals(producerRef)) {
+ this.producerRef = null;
+ this.producer = null;
+ } else if (sRef.equals(consumerRef)) {
+ this.consumerRef = null;
+ this.consumer = null;
+ this.flavors = null;
+ } else {
+ if (Activator.LOG_DEBUG) {
+ Activator.log.debug(Activator.PREFIX + "Unregistering another consumer with the same pid, ignoring it ...", null);
+ }
+ return;
+ }
+
+ updateListenerFilter();
+
+ if (lastStatus) {
+ // last wire state was connected - now it is disconnected
+ informServices();
+ parent.notifyListeners(this, WireAdminEvent.WIRE_DISCONNECTED, null);
+ }
+ if (bc != null) {
+ bc.ungetService(sRef);
+ }
+
+ }
+
+ /**
+ * This method checks if the given String contains one of the characters *, (,
+ * and ) which have a special meaning for the LDAP search filters. If there
+ * are such characters they are escaped with the backslash character ('\').
+ */
+ static String escapeSpecialCharacters(String s) {
+ char[] content = s.toCharArray();
+ StringBuffer result = new StringBuffer(s);
+ int offset = 0;
+
+ for (int i = 0; i < content.length; i++) {
+ if ((content[i] == 40) || (content[i] == 41) || (content[i] == 42)) {
+ result.insert(i + offset, "\\"); // fix #1078
+ offset++;
+ }
+ }
+ return result.toString();
+ }
+
+ /**
+ * Change the properties of this wire. If the changes concern one of the
+ * properties WIRE_PRODUCER_PID and WIRE_CONSUMER_PID this wire must be
+ * stopped and started again to begin tracking of the new Services.
+ */
+ void setProperties(Dictionary newProps) {
+ if (newProps != null) {
+ String newConsPID = (String) newProps.get(WireConstants.WIREADMIN_CONSUMER_PID);
+ String newProdPID = (String) newProps.get(WireConstants.WIREADMIN_PRODUCER_PID);
+
+ String oldConsPID = (String) properties.get(WireConstants.WIREADMIN_CONSUMER_PID);
+ String oldProdPID = (String) properties.get(WireConstants.WIREADMIN_PRODUCER_PID);
+
+ boolean restart = false;
+
+ if (newConsPID == null) {
+ newProps.put(WireConstants.WIREADMIN_CONSUMER_PID, oldConsPID);
+ } else if (!newConsPID.equals(oldConsPID)) {
+ restart = true;
+ }
+
+ if (newProdPID == null) {
+ newProps.put(WireConstants.WIREADMIN_PRODUCER_PID, oldProdPID);
+ } else if (!newProdPID.equals(oldProdPID)) {
+ restart = true;
+ }
+ // fix #1074
+ if (newProps.get(WireConstants.WIREADMIN_PID) == null) {
+ newProps.put(WireConstants.WIREADMIN_PID, properties.get(WireConstants.WIREADMIN_PID));
+ }
+
+ // WireProperties wprops = new WireProperties();
+ properties.clear();
+
+ for (Enumeration en = newProps.keys(); en.hasMoreElements();) {
+ Object key = en.nextElement();
+ properties.put0(key, newProps.get(key));
+ }
+
+ checkWireFilter();
+
+ if (restart) {
+ // One of the Consumer or Producer has been changed so restart
+ // the wire
+ stop();
+ start();
+ return;
+ }
+ }
+
+ if (isConnected()) {
+ informServices();
+ }
+
+ parent.notifyListeners(this, WireAdminEvent.WIRE_UPDATED, null);
+ }
+
+ private boolean isAcceptable(Object value) {
+ Class[] flavors = getFlavors();
+
+ if (flavors == null) {
+ return true;
+ }
+
+ for (int i = 0; i < flavors.length; i++) {
+ if (flavors[i].isInstance(value)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+ */
+ public void serviceChanged(ServiceEvent evt) {
+ if (bc == null) {
+ return;
+ }
+ switch (evt.getType()) {
+ case ServiceEvent.REGISTERED :
+ // System.out.println("E V E N T : registered");
+ serviceRegistered(evt.getServiceReference());
+ break;
+
+ case ServiceEvent.UNREGISTERING :
+ // System.out.println("E V E N T : unregistering");
+ serviceUnregistered(evt.getServiceReference());
+ break;
+
+ case ServiceEvent.MODIFIED :
+ // System.out.println("E V E N T : modified");
+ serviceModified(evt.getServiceReference());
+ }
+ }
+
+ String getWirePID() {
+ return (String) properties.get(WireConstants.WIREADMIN_PID);
+ }
+
+ /**
+ * This method simply informs both Producer and Consumer with the methods
+ * consumersConnected, producersConnected if a wire bacames connected and
+ * the remaining service if the wire becames disconnected.
+ */
+ private void informServices() {
+ if (producerRef != null) {
+ String producerPID = (String) properties.get(WireConstants.WIREADMIN_PRODUCER_PID);
+ NotificationEvent ne = new NotificationEvent(producer, null, this, parent.getConnected(WireConstants.WIREADMIN_PRODUCER_PID, producerPID));
+ parent.notifyConsumerProducer(ne);
+
+ // try {
+ // producer.consumersConnected(parent.getConnected(WireConstants.WIREADMIN_PRODUCER_PID,
+ // producerPID));
+ // } catch (Exception ex) {
+ // parent.notifyListeners(this, WireAdminEvent.PRODUCER_EXCEPTION ,
+ // ex);
+ // }
+ }
+
+ if (consumerRef != null) {
+ String consumerPID = (String) properties.get(WireConstants.WIREADMIN_CONSUMER_PID);
+ NotificationEvent ne = new NotificationEvent(null, consumer, this, parent.getConnected(WireConstants.WIREADMIN_CONSUMER_PID, consumerPID));
+ parent.notifyConsumerProducer(ne);
+
+ // try {
+ // consumer.producersConnected(parent.getConnected(WireConstants.WIREADMIN_CONSUMER_PID,
+ // consumerPID));
+ // } catch (Exception ex) {
+ // parent.notifyListeners(this, WireAdminEvent.CONSUMER_EXCEPTION ,
+ // ex);
+ // }
+ }
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/WireProperties.java b/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/WireProperties.java
new file mode 100644
index 00000000..b5f6115b
--- /dev/null
+++ b/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/WireProperties.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 1997-2007 by ProSyst Software GmbH
+ * http://www.prosyst.com
+ * 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
+ *
+ * Contributors:
+ * ProSyst Software GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.wireadmin;
+
+import java.util.Hashtable;
+
+/**
+ * @author Pavlin Dobrev
+ * @version 1.0
+ */
+
+class WireProperties extends Hashtable {
+
+ static final long serialVersionUID = -8836718065933570367L;
+
+ public synchronized Object put(Object key, Object value) {
+ throw new RuntimeException("Unsupported operation");
+ }
+
+ public synchronized Object remove(Object key) {
+ throw new RuntimeException("Unsupported operation");
+ }
+
+ Object put0(Object key, Object value) {
+ return super.put(key, value);
+ }
+
+ Object remove0(Object key) {
+ return super.remove(key);
+ }
+}
diff --git a/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/WireReDispatcher.java b/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/WireReDispatcher.java
new file mode 100644
index 00000000..56246c79
--- /dev/null
+++ b/bundles/org.eclipse.equinox.wireadmin/src/org/eclipse/equinox/internal/wireadmin/WireReDispatcher.java
@@ -0,0 +1,308 @@
+/*******************************************************************************
+ * Copyright (c) 1997-2007 by ProSyst Software GmbH
+ * http://www.prosyst.com
+ * 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
+ *
+ * Contributors:
+ * ProSyst Software GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.wireadmin;
+
+import java.util.Hashtable;
+import org.eclipse.equinox.internal.util.ref.Log;
+import org.osgi.framework.*;
+import org.osgi.service.event.*;
+import org.osgi.service.wireadmin.*;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * This is an implementation of log events redispatching.
+ *
+ * /**
+ *
+ * @author Pavlin Dobrev
+ * @version 1.0
+ */
+public class WireReDispatcher implements WireAdminListener {
+
+ static final String BUNDLE = "bundle";
+ static final String BUNDLE_ID = "bundle.id";
+ static final String BUNDLE_SYMBOLICNAME = "bundle.symbolicName";
+ static final String EVENT = "event";
+ static final String EXCEPTION = "exception";
+ static final String EXCEPTION_CLASS = "exception.class";
+ static final String EXCEPTION_MESSAGE = "exception.message";
+ static final String SERVICE = "service";
+ static final String SERVICE_ID = "service.id";
+ static final String SERVICE_OBJECTCLASS = "service.objectClass";
+ static final String SERVICE_PID = "service.pid";
+ static final char TOPIC_SEPARATOR = '/';
+ /* ///////WIRE ADMIN EVENTS////////// */
+ static final String WIRE_HEADER = "org/osgi/service/wireadmin/WireAdminEvent";
+ static final String WIRE_CREATED = "WIRE_CREATED";
+ static final String WIRE_CONNECTED = "WIRE_CONNECTED";
+ static final String WIRE_UPDATED = "WIRE_UPDATED";
+ static final String WIRE_TRACE = "WIRE_TRACE";
+ static final String WIRE_DISCONNECTED = "WIRE_DISCONNECTED";
+ static final String WIRE_DELETED = "WIRE_DELETED";
+ static final String PRODUCER_EXCEPTION = "PRODUCER_EXCEPTION";
+ static final String CONSUMER_EXCEPTION = "CONSUMER_EXCEPTION";
+ static final String WIRE_ENTRY = "wire.entry";
+ static final String WA_WIRE = "wire";
+ static final String WA_WIRE_FLAVORS = "wire.flavors";
+ static final String WA_WIRE_SCOPE = "wire.scope";
+ static final String WA_WIRE_CONNECTED = "wire.connected";
+ static final String WA_WIRE_VALID = "wire.valid";
+
+ BundleContext bc;
+ ServiceRegistration waReg;
+ Log log;
+ ServiceTracker eventAdminTracker;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext bc) throws Exception {
+ this.bc = bc;
+ log = new Log(bc, false);
+ log.setDebug(Activator.getBoolean("equinox.wireadmin.redispatcher.debug"));
+ log.setPrintOnConsole(Activator.getBoolean("equinox.wireadmin.redispatcher.console"));
+
+ Hashtable props = new Hashtable(3);
+ props.put(WireConstants.WIREADMIN_EVENTS, new Integer(Integer.MAX_VALUE));
+ waReg = bc.registerService(WireAdminListener.class.getName(), this, props);
+
+ eventAdminTracker = new ServiceTracker(bc, EventAdmin.class.getName(), null);
+ eventAdminTracker.open();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop() throws Exception {
+ if (eventAdminTracker != null) {
+ eventAdminTracker.close();
+ eventAdminTracker = null;
+ }
+ if (waReg != null) {
+ waReg.unregister();
+ waReg = null;
+ }
+ log.close();
+ this.bc = null;
+ }
+
+ /* ////////UTILITY METHODS//////// */
+
+ /*
+ * Add exception properties needed in event by EventAdmin specification.
+ */
+ void addExceptionProps(Hashtable props, Throwable t) {
+ props.put(EXCEPTION, t);
+ props.put(EXCEPTION_CLASS, t.getClass().getName());
+ String message = t.getMessage();
+ if (message != null) {
+ props.put(EXCEPTION_MESSAGE, t.getMessage());
+ }
+ }
+
+ /*
+ * Add service properties needed in event by EventAdmin specification.
+ */
+ void addServiceProps(Hashtable props, ServiceReference ref) {
+ props.put(SERVICE, ref);
+ props.put(SERVICE_ID, ref.getProperty(Constants.SERVICE_ID));
+ Object tmp = ref.getProperty(Constants.SERVICE_PID);
+ if (tmp != null && tmp instanceof String) {
+ props.put(SERVICE_PID, tmp);
+ }
+ tmp = ref.getProperty(Constants.OBJECTCLASS);
+ if (tmp != null && tmp instanceof String[]) {
+ props.put(SERVICE_OBJECTCLASS, tmp);
+ }
+ }
+
+ /* ////////LISTENER METHODS//////// */
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.wireadmin.WireAdminListener#wireAdminEvent(org.osgi.service.wireadmin.WireAdminEvent)
+ */
+ public void wireAdminEvent(WireAdminEvent event) {
+ ServiceTracker st = eventAdminTracker;
+ EventAdmin eventAdmin = st == null ? null : ((EventAdmin) st.getService());
+ if (eventAdmin != null) {
+ ServiceReference ref = event.getServiceReference();
+ if (ref == null) {
+ throw new RuntimeException("Wire Admin ServiceReference is null");
+ }
+ String topicSuffix = null;
+ switch (event.getType()) {
+ case WireAdminEvent.WIRE_CREATED :
+ topicSuffix = WIRE_CREATED;
+ break;
+ case WireAdminEvent.WIRE_CONNECTED :
+ topicSuffix = WIRE_CONNECTED;
+ break;
+ case WireAdminEvent.WIRE_UPDATED :
+ topicSuffix = WIRE_UPDATED;
+ break;
+ case WireAdminEvent.WIRE_TRACE :
+ topicSuffix = WIRE_TRACE;
+ break;
+ case WireAdminEvent.WIRE_DISCONNECTED :
+ topicSuffix = WIRE_DISCONNECTED;
+ break;
+ case WireAdminEvent.WIRE_DELETED :
+ topicSuffix = WIRE_DELETED;
+ break;
+ case WireAdminEvent.PRODUCER_EXCEPTION :
+ topicSuffix = PRODUCER_EXCEPTION;
+ break;
+ case WireAdminEvent.CONSUMER_EXCEPTION :
+ topicSuffix = CONSUMER_EXCEPTION;
+ break;
+ default : /* ignore: unknown/new events */
+ return;
+ }
+ String topic = WIRE_HEADER + TOPIC_SEPARATOR + topicSuffix;
+ if (!hasServiceReferences(topic)) {
+ if (Activator.LOG_DEBUG)
+ log.debug(0, 10017, event.toString(), null, false);
+ return; /*
+ * no service references for this topic do not bother
+ * EventAdmin
+ */
+ }
+ Hashtable props = new Hashtable();
+ addServiceProps(props, ref);
+ Wire wire = event.getWire();
+ if (wire != null) {
+ props.put(WA_WIRE, wire);
+ props.put(WA_WIRE_CONNECTED, new Boolean(wire.isConnected()));
+ if (wire.getFlavors() != null) {
+ props.put(WA_WIRE_FLAVORS, wire.getFlavors());
+ }
+ if (wire.getScope() != null) {
+ props.put(WA_WIRE_SCOPE, wire.getScope());
+ }
+ props.put(WA_WIRE_VALID, new Boolean(wire.isValid()));
+ }
+ Throwable throwable = event.getThrowable();
+ if (throwable != null) {
+ addExceptionProps(props, throwable);
+ }
+ props.put(EVENT, event);
+ eventAdmin.postEvent(new Event(topic, props));
+ if (Activator.LOG_DEBUG)
+ log.debug(0, 10018, event.toString(), null, false);
+ }
+ }
+
+ /**
+ * This will return true if has at least one ServiceReference which match
+ * given topic.
+ *
+ * @param topic
+ * @return
+ */
+ protected boolean hasServiceReferences(String topic) {
+ BundleContext l_bc = bc;
+ if (l_bc == null) {
+ return false;
+ }
+ ServiceReference[] sr = null;
+ try {/* get all handlers */
+ sr = l_bc.getServiceReferences(EventHandler.class.getName(), null);
+ } catch (InvalidSyntaxException e) {
+ return false;
+ }
+ if (sr != null && sr.length > 0) {
+ TopicPermission perm = new TopicPermission(topic, TopicPermission.SUBSCRIBE);
+ for (int i = 0; i < sr.length; i++) {
+ try {
+ ServiceReference sRef = sr[i];
+ Bundle bundle = sRef.getBundle();
+ if (bundle != null && (bundle.getState() != Bundle.UNINSTALLED) && bundle.hasPermission(perm)) {
+ Object reftopic = sRef.getProperty(EventConstants.EVENT_TOPIC);
+ if (reftopic != null) { /*
+ * otherwise means will receive
+ * no events
+ */
+ if (reftopic instanceof String[]) { /*
+ * even with one
+ * element it
+ * must be
+ * String[]
+ */
+ String topics[] = (String[]) reftopic;
+ for (int j = 0; j < topics.length; j++) {
+ if (matchTopic(topics[j], topic)) {
+ return true;
+ }
+ }
+ }
+ }
+ }/* check permission */
+ } catch (Throwable t) {
+ log.error("Error while checking bundle permissions", t);
+ }
+ }/* for */
+ }/* sr != null && sr.length > 0 */
+ return false;
+ }
+
+ /**
+ * Checks if a topic filter string matches the target topic string.
+ *
+ * @param pattern
+ * A topic filter like "company/product/*"
+ * @param topic
+ * Target topic to be checked against like
+ * "company/product/topicA"
+ * @return true if topicProperty matches topic, false if otherwise.
+ */
+ protected static boolean matchTopic(String pattern, String topic) {
+ // //two fast checks
+ if (pattern.length() > topic.length())
+ return false;
+ if ("*".equals(pattern) || pattern.equals(topic))
+ return true;
+
+ // //assume pattern is not NULL ... or check!
+ int index = pattern.indexOf(TOPIC_SEPARATOR);
+ if (index == -1 || index == 0 || index == pattern.length() - 1) {
+ // //syntax problem
+ // //we have no '/' or starts with '/' or ends with '/'
+ return false;
+ }
+
+ for (index = 0; index < pattern.length(); index++) {
+ if (pattern.charAt(index) == '*') {
+ // //wildcard!!!
+ if (pattern.charAt(index - 1) != TOPIC_SEPARATOR)
+ return false; // we have not '/' before '*'
+ if (index != pattern.length() - 1)
+ return false; // we have something after the '*'
+ return true;
+ }
+ if (pattern.charAt(index) != topic.charAt(index))
+ return false;
+ }
+
+ if (index != topic.length())
+ return false;
+ if (pattern.charAt(index - 1) == TOPIC_SEPARATOR)
+ return false;
+ return true;
+ }
+
+}

Back to the top