summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Campo2008-01-16 11:40:54 (EST)
committerChristian Campo2008-01-16 11:40:54 (EST)
commitdc7deb1814ed05c7d349569d8139dfaf5c6886bf (patch)
tree5a395b202774ed258cfeeadbce67595ddfee1a41
downloadorg.eclipse.riena-dc7deb1814ed05c7d349569d8139dfaf5c6886bf.zip
org.eclipse.riena-dc7deb1814ed05c7d349569d8139dfaf5c6886bf.tar.gz
org.eclipse.riena-dc7deb1814ed05c7d349569d8139dfaf5c6886bf.tar.bz2
initial checkin
-rw-r--r--org.eclipse.riena.core/.classpath7
-rw-r--r--org.eclipse.riena.core/.project28
-rw-r--r--org.eclipse.riena.core/.settings/org.eclipse.pde.core.prefs4
-rw-r--r--org.eclipse.riena.core/META-INF/MANIFEST.MF24
-rw-r--r--org.eclipse.riena.core/about.html24
-rw-r--r--org.eclipse.riena.core/build.properties5
-rw-r--r--org.eclipse.riena.core/plugin.xml5
-rw-r--r--org.eclipse.riena.core/schema/managedService.exsd124
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/cache/CacheFailure.java64
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/cache/GenericObjectCache.java335
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/cache/IGenericObjectCache.java152
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/cache/LRUCache.java199
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/cache/internal/GlobalSoftCacheEntry.java168
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/cache/internal/ICacheEntry.java41
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/cache/internal/SimpleCacheEntry.java46
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/cache/internal/SoftCacheEntry.java72
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/config/ConfigUtility.java74
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/contract/PostCondition.java221
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/contract/PostConditionException.java33
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/contract/PreCondition.java98
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/contract/PreConditionException.java33
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/exception/ExceptionFailure.java41
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/exception/ExceptionHelper.java459
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/exception/Failure.java444
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/exception/IExceptionHandler.java81
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/exception/IExceptionHandlerManager.java116
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/extension/util/ExtensionUtility.java106
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/logging/AlwaysFilter.java22
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/logging/Log4jLogListener.java28
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/logging/LogUtil.java113
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/logging/NullLogger.java44
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/logging/SysoLogListener.java34
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/marker/AbstractMarker.java112
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/marker/IMarkable.java60
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/marker/IMarker.java86
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/marker/IMarkerAttributeChangeListener.java24
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/marker/Markable.java82
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/service/ServiceInjector.java270
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/util/CloneHelper.java104
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/util/ContainerModel.java42
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/util/InvocationTargetFailure.java51
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/util/Iter.java134
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/util/PropertiesUtils.java39
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/util/ReflectionFailure.java42
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/util/ReflectionUtils.java522
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/core/util/UtilFailure.java43
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/internal/core/Activator.java95
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/internal/core/config/ConfigAdminHandler.java89
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/internal/core/config/ConfigFromExtensions.java46
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/internal/core/config/ConfigProxy.java93
-rw-r--r--org.eclipse.riena.core/src/org/eclipse/riena/internal/core/config/ConfigSymbolReplace.java108
51 files changed, 5287 insertions, 0 deletions
diff --git a/org.eclipse.riena.core/.classpath b/org.eclipse.riena.core/.classpath
new file mode 100644
index 0000000..751c8f2
--- /dev/null
+++ b/org.eclipse.riena.core/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.riena.core/.project b/org.eclipse.riena.core/.project
new file mode 100644
index 0000000..134d919
--- /dev/null
+++ b/org.eclipse.riena.core/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.riena.core</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.riena.core/.settings/org.eclipse.pde.core.prefs b/org.eclipse.riena.core/.settings/org.eclipse.pde.core.prefs
new file mode 100644
index 0000000..f9d850a
--- /dev/null
+++ b/org.eclipse.riena.core/.settings/org.eclipse.pde.core.prefs
@@ -0,0 +1,4 @@
+#Thu Dec 27 15:16:42 CET 2007
+eclipse.preferences.version=1
+pluginProject.extensions=true
+resolve.requirebundle=false
diff --git a/org.eclipse.riena.core/META-INF/MANIFEST.MF b/org.eclipse.riena.core/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..e4044a1
--- /dev/null
+++ b/org.eclipse.riena.core/META-INF/MANIFEST.MF
@@ -0,0 +1,24 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Riena Core (Incubation)
+Bundle-SymbolicName: org.eclipse.riena.core;singleton:=true
+Bundle-Version: 0.0.1
+Bundle-Activator: org.eclipse.riena.internal.core.Activator
+Eclipse-LazyStart: true
+Import-Package: org.eclipse.equinox.log,
+ org.osgi.framework;version="1.3.0",
+ org.osgi.service.cm;version="1.2.0",
+ org.osgi.service.log;version="1.3.0"
+Export-Package: org.eclipse.riena.core.cache,
+ org.eclipse.riena.core.config,
+ org.eclipse.riena.core.contract,
+ org.eclipse.riena.core.exception,
+ org.eclipse.riena.core.extension.util,
+ org.eclipse.riena.core.logging,
+ org.eclipse.riena.core.marker,
+ org.eclipse.riena.core.service,
+ org.eclipse.riena.core.util
+Require-Bundle: org.eclipse.core.runtime,
+ org.apache.log4j,
+ org.eclipse.equinox.log,
+ org.eclipse.equinox.cm
diff --git a/org.eclipse.riena.core/about.html b/org.eclipse.riena.core/about.html
new file mode 100644
index 0000000..fc81119
--- /dev/null
+++ b/org.eclipse.riena.core/about.html
@@ -0,0 +1,24 @@
+<!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>June 5, 2006</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL"). 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, "Program" 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 ("Redistributor") 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>
+
+<div style="position: absolute; width: 28px; height: 28px; z-index: 1000; display: none;"></div><img style="position: absolute; width: 35px; height: 29px; z-index: 1000; display: none;" src="about-Dateien/launch.png"></body></html> \ No newline at end of file
diff --git a/org.eclipse.riena.core/build.properties b/org.eclipse.riena.core/build.properties
new file mode 100644
index 0000000..e9863e2
--- /dev/null
+++ b/org.eclipse.riena.core/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml
diff --git a/org.eclipse.riena.core/plugin.xml b/org.eclipse.riena.core/plugin.xml
new file mode 100644
index 0000000..8b63710
--- /dev/null
+++ b/org.eclipse.riena.core/plugin.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<plugin>
+ <extension-point id="org.eclipse.riena.config.managedService" name="managedService" schema="schema/managedService.exsd"/>
+</plugin>
diff --git a/org.eclipse.riena.core/schema/managedService.exsd b/org.eclipse.riena.core/schema/managedService.exsd
new file mode 100644
index 0000000..b0c99bd
--- /dev/null
+++ b/org.eclipse.riena.core/schema/managedService.exsd
@@ -0,0 +1,124 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.riena.config">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.eclipse.riena.config" id="managedService" name="managedService"/>
+ </appInfo>
+ <documentation>
+ [Enter description of this extension point.]
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <complexType>
+ <sequence>
+ <element ref="config"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="property">
+ <complexType>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="value" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="config">
+ <complexType>
+ <sequence minOccurs="1" maxOccurs="unbounded">
+ <element ref="property" minOccurs="1" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="servicepid" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+ [Enter the first release in which this extension point appears.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+ [Enter extension point usage example here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiInfo"/>
+ </appInfo>
+ <documentation>
+ [Enter API information here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+ [Enter information about supplied implementation of this extension point.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/CacheFailure.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/CacheFailure.java
new file mode 100644
index 0000000..8c8ec76
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/CacheFailure.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.cache;
+
+import org.eclipse.riena.core.exception.Failure;
+
+/**
+ * Failure for all GenericObjectCache related Failures
+ *
+ * @author Christian Campo
+ */
+public class CacheFailure extends Failure {
+
+ /**
+ * @param msg
+ */
+ public CacheFailure(String msg) {
+ super(msg);
+ }
+
+ /**
+ * @param msg
+ * @param arg1
+ * @param arg2
+ * @param cause
+ */
+ public CacheFailure(String msg, Object arg1, Object arg2, Throwable cause) {
+ super(msg, arg1, arg2, cause);
+ }
+
+ /**
+ * @param msg
+ * @param arg1
+ * @param cause
+ */
+ public CacheFailure(String msg, Object arg1, Throwable cause) {
+ super(msg, arg1, cause);
+ }
+
+ /**
+ * @param msg
+ * @param args
+ * @param cause
+ */
+ public CacheFailure(String msg, Object[] args, Throwable cause) {
+ super(msg, args, cause);
+ }
+
+ /**
+ * @param msg
+ * @param cause
+ */
+ public CacheFailure(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+}
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/GenericObjectCache.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/GenericObjectCache.java
new file mode 100644
index 0000000..c0d85d4
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/GenericObjectCache.java
@@ -0,0 +1,335 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.cache;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.util.HashMap;
+import java.util.LinkedList;
+
+import org.eclipse.equinox.log.Logger;
+import org.eclipse.riena.core.cache.internal.GlobalSoftCacheEntry;
+import org.eclipse.riena.core.cache.internal.ICacheEntry;
+import org.eclipse.riena.core.cache.internal.SoftCacheEntry;
+import org.eclipse.riena.internal.core.Activator;
+import org.osgi.service.log.LogService;
+
+/**
+ * Class implements a generic object cache.
+ *
+ * @author Christian Campo
+ */
+public class GenericObjectCache implements IGenericObjectCache {
+
+ private static final String SPIRIT_CORE_BASE_INTERNAL_REFERENCE_QUEUE = "spirit.core.base.internal.ReferenceQueue";
+ private static final String SPIRIT_CORE_BASE_INTERNAL_HARD_LINKS = "spirit.core.base.internal.HardLinks";
+ private final static Logger LOGGER = Activator.getDefault().getLogger(GenericObjectCache.class.getName());
+ private HashMap cacheEntries;
+ /** timeout in milliseconds * */
+ private long timeout;
+ /** minimum count of entries to keep * */
+ private int minimumSize;
+ private LinkedList hardLinks;
+ /** Reference queue for cleared SoftReference objects. */
+ private ReferenceQueue queue;
+ private int statHit;
+ private int statNotFound;
+ private int statMiss;
+ private int statTimeout;
+ private static int statDisplayCount;
+ private boolean globalCache; // default = false
+ private String name = "Cache : ";
+
+ /**
+ * Constructor.
+ */
+ public GenericObjectCache() {
+ super();
+ LOGGER.log(LogService.LOG_DEBUG, "creating new GenericObjectCache instance");
+ cacheEntries = new HashMap();
+ queue = new ReferenceQueue();
+ hardLinks = new LinkedList();
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#setHashMap(java.util.HashMap)
+ */
+ public void setHashMap(HashMap map) {
+ cacheEntries = map;
+ globalCache = true;
+ synchronized (map) {
+ // if we get a global non empty map, get other global instances that
+ // are stored their
+ if (map.size() > 0) {
+ hardLinks = (LinkedList) map.get(SPIRIT_CORE_BASE_INTERNAL_HARD_LINKS);
+ queue = (ReferenceQueue) map.get(SPIRIT_CORE_BASE_INTERNAL_REFERENCE_QUEUE);
+ } else {
+ // else store your local vars in there so the next instance can
+ // find them
+ map.put(SPIRIT_CORE_BASE_INTERNAL_HARD_LINKS, hardLinks);
+ map.put(SPIRIT_CORE_BASE_INTERNAL_REFERENCE_QUEUE, queue);
+ }
+ }
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#setName(java.lang.String)
+ */
+ public void setName(String name) {
+ this.name = name + " : ";
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#isGlobalCache()
+ */
+ public boolean isGlobalCache() {
+ return globalCache;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#get(java.lang.Object)
+ */
+ public Object get(Object key) {
+ // PreCondition.assertTrue("get with single parameter cannot be used for
+ // global caches. use two parameter
+ // version ", !isGlobalCache());
+ return get(key, GenericObjectCache.class);
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#get(Object,Class)
+ */
+ public Object get(Object key, Class callingClass) {
+ LOGGER.log(LogService.LOG_DEBUG, "get = " + key);
+ long timestamp = 0;
+ Object value = null;
+ synchronized (cacheEntries) {
+ Object tempEntry = cacheEntries.get(key);
+ /** do we find the entry * */
+ if (tempEntry == null) {
+ statNotFound++;
+ printStat();
+ return null;
+ }
+ // now proxy the entry if we have a global cache because the
+ // instance could be from a different classloader
+ // if tempEntry is from my webclasspath cast it directly otherwise
+ // create a proxy
+ if (!(tempEntry instanceof ICacheEntry)) {
+ try {
+ // timestamp = ((Long)
+ // ReflectionUtils.invokeHidden(tempEntry, "getTimestamp",
+ // new
+ // Object[0])).longValue();
+ } catch (Throwable e) {
+ // this should not happen
+ }
+ } else {
+ ICacheEntry entry = (ICacheEntry) tempEntry;
+ timestamp = entry.getTimestamp();
+ }
+
+ long timePassed = System.currentTimeMillis() - timestamp;
+ /** is the entry expired * */
+ if (timePassed > timeout) {
+ remove(key);
+ statTimeout++;
+ printStat();
+ return null;
+ }
+ // only get the value if its not timed out (see previous IF)
+ if (!(tempEntry instanceof ICacheEntry)) {
+ try {
+ // value = ReflectionUtils.invokeHidden(tempEntry,
+ // "getValue", new Object[] {
+ // callingClass.getClassLoader() });
+ } catch (Throwable e) {
+ // this should not happen
+ }
+ } else {
+ if (globalCache) {
+ GlobalSoftCacheEntry entry = (GlobalSoftCacheEntry) tempEntry;
+ value = entry.getValue(callingClass.getClassLoader());
+ } else {
+ ICacheEntry entry = (ICacheEntry) tempEntry;
+ value = entry.getValue();
+ }
+ }
+ }
+
+ /** does the soft reference still point anywhere * */
+ if (value != null) {
+ /** if a minimum size is required * */
+ touchValue(value);
+ statHit++;
+ printStat();
+ return value;
+ } else {
+ /** if not remove the key * */
+ remove(key);
+ statMiss++;
+ printStat();
+ return null;
+ }
+ }
+
+ private void printStat() {
+ statDisplayCount++;
+ if (statDisplayCount > 100) {
+ LOGGER
+ .log(LogService.LOG_INFO, name + "Hit / NotFound / Miss / Timeout " + statHit + " / " + statNotFound + " / " + statMiss + " / "
+ + statTimeout);
+ statDisplayCount = 0;
+ }
+ }
+
+ public String getStatistic() {
+ return name + "Hit / NotFound / Miss / Timeout " + statHit + " / " + statNotFound + " / " + statMiss + " / " + statTimeout;
+ }
+
+ private void touchValue(Object value) {
+ if (minimumSize > 0) {
+ synchronized (hardLinks) {
+ hardLinks.addFirst(value);
+ if (hardLinks.size() > minimumSize) {
+ // Remove the last entry if list longer than minimumSize
+ hardLinks.removeLast();
+ }
+ }
+ }
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#put(Object,
+ * java.lang.Object)
+ */
+ public void put(Object key, Object value) {
+ // PreCondition.assertTrue("objects in global caches must be
+ // serializable", (!globalCache) || value instanceof
+ // Serializable);
+ LOGGER.log(LogService.LOG_DEBUG, "put = " + key + " , " + value + "");
+ processQueue();
+ ICacheEntry entry;
+ if (globalCache) {
+ entry = new GlobalSoftCacheEntry(value, key, queue);
+ } else {
+ entry = new SoftCacheEntry(value, key, queue);
+ }
+ synchronized (cacheEntries) {
+ cacheEntries.put(key, entry);
+ }
+ touchValue(value);
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#clear()
+ */
+ public void clear() {
+ LOGGER.log(LogService.LOG_DEBUG, "clear");
+ synchronized (hardLinks) {
+ hardLinks.clear();
+ }
+ processQueue();
+ synchronized (cacheEntries) {
+ cacheEntries.clear();
+ }
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#remove(Object)
+ */
+ public void remove(Object key) {
+ LOGGER.log(LogService.LOG_DEBUG, "remove = " + key);
+ processQueue();
+ synchronized (cacheEntries) {
+ cacheEntries.remove(key);
+ }
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#size()
+ */
+ public int size() {
+ processQueue();
+ synchronized (cacheEntries) {
+ LOGGER.log(LogService.LOG_DEBUG, "size returned = " + cacheEntries.size());
+ return cacheEntries.size();
+ }
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#setTimeout(int)
+ */
+ public void setTimeout(int milliseconds) {
+ LOGGER.log(LogService.LOG_DEBUG, "setTimeout = " + milliseconds);
+ timeout = milliseconds;
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#getTimeout()
+ */
+ public int getTimeout() {
+ return (int) timeout;
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#getMinimumSize()
+ */
+ public int getMinimumSize() {
+ return minimumSize;
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#getSize()
+ */
+ public int getSize() {
+ return size();
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#setMinimumSize(int)
+ */
+ public void setMinimumSize(int minSize) {
+ LOGGER.log(LogService.LOG_DEBUG, "setMinSize = " + minSize);
+ minimumSize = minSize;
+ }
+
+ private void processQueue() {
+ LOGGER.log(LogService.LOG_DEBUG, "processQueue");
+ SoftReference ref;
+ Object tempEntry;
+ Object key = null;
+ int count = 0;
+ synchronized (cacheEntries) {
+ while ((ref = (SoftReference) queue.poll()) != null) {
+ tempEntry = ref.get();
+ if (tempEntry instanceof ICacheEntry) {
+ key = ((ICacheEntry) tempEntry).getKey();
+ } else {
+ try {
+ // key = ReflectionUtils.invokeHidden(tempEntry,
+ // "getKey", new Object[0]);
+ } catch (Throwable e) {
+ // should not happen
+ }
+ }
+ cacheEntries.remove(key);
+ count++;
+ }
+ }
+ if (count > 0) {
+ LOGGER.log(LogService.LOG_INFO, "processQueue removed " + count + " entries");
+ }
+ }
+
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/IGenericObjectCache.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/IGenericObjectCache.java
new file mode 100644
index 0000000..c4a2162
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/IGenericObjectCache.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.cache;
+
+import java.util.HashMap;
+
+/**
+ * The GenericObjectCache is a multipurpose object for storing data without
+ * locking all your memory. It works like a regular HashMap with some
+ * differences. Item can be removed from the GenericObjectCache under certain
+ * conditions:
+ * <ul>
+ * <li>timeout: xxxx milliseconds after the timeout, an item is no longer valid
+ * if found in the cache and automatically removed.</li>
+ * <li>GC: if garbage collection is started because of low memory in the JVM,
+ * it can remove any entry in the GenericObjectCache.</li>
+ * <li>minSize: minSize specifies a number of minimum entries that are held in
+ * the cache even if garbage collection occurs. However these minSize entries
+ * will still be checked against the timeout.</li>
+ * </ul>
+ *
+ * @author Christian Campo
+ */
+public interface IGenericObjectCache {
+
+ String ID = IGenericObjectCache.class.getName();
+
+ /**
+ * returns true if this is a global cache
+ *
+ * @return true if cache is global
+ */
+ boolean isGlobalCache();
+
+ /**
+ * Get an object by key. Cannot be called for global caches. There you have
+ * to use get(Object,Class), see below.
+ *
+ * @param key
+ * the key to look up object.
+ * @return the object looked up.
+ * @pre (isGlobalCache()==false)
+ */
+ Object get(Object key);
+
+ /**
+ * Get an object by key in the context of the calling class
+ *
+ * @param key
+ * @param callingClass
+ * @return
+ */
+ Object get(Object key, Class callingClass);
+
+ /**
+ * Put some object <code>value</code> with <code>key</code> into the
+ * cache.
+ *
+ * @param key
+ * the key for looking up the object.
+ * @param value
+ * the value. If this is a globalCache the value must implement
+ * Serializable
+ * @pre !isGlobalCache() || value instanceof Serializable
+ */
+ void put(Object key, Object value);
+
+ /**
+ * Remove object with <code>key</code> from the cache.
+ *
+ * @param key
+ * the key.
+ */
+ void remove(Object key);
+
+ /**
+ * Clear the cache.
+ */
+ void clear();
+
+ /**
+ * Set the timeout for cached objects.
+ *
+ * @param milliseconds
+ * the timeout in milliseconds.
+ */
+ void setTimeout(int milliseconds);
+
+ /**
+ * Return mumber of cached objects.
+ *
+ * @return the mumber of cached objects.
+ */
+ int size();
+
+ /**
+ * Set the minimum number of entries that are held in the cache.
+ *
+ * @param minSize
+ * the minimum number of entries.
+ */
+ void setMinimumSize(int minSize);
+
+ /**
+ * Returns the currently set timeout value
+ *
+ * @return
+ */
+ int getTimeout();
+
+ /**
+ * Returns the currently set minimum size
+ *
+ * @return
+ */
+ int getMinimumSize();
+
+ /**
+ * Sets a global HashMap resource that is used for this GenericObjectCache.
+ * A type is required for Caches with global HashMap
+ *
+ * @param map
+ */
+ void setHashMap(HashMap map);
+
+ /**
+ * Descriptive name for this cache (shown in logs)
+ *
+ * @param name
+ */
+ void setName(String name);
+
+ /**
+ * Returns the current size of the GenericObjectCache
+ *
+ * @return
+ */
+ int getSize();
+
+ /**
+ * @return
+ */
+ String getStatistic();
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/LRUCache.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/LRUCache.java
new file mode 100644
index 0000000..42153f5
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/LRUCache.java
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.cache;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.eclipse.equinox.log.Logger;
+import org.eclipse.riena.core.cache.internal.ICacheEntry;
+import org.eclipse.riena.core.cache.internal.SimpleCacheEntry;
+import org.eclipse.riena.internal.core.Activator;
+import org.osgi.service.log.LogService;
+
+/**
+ * LRU=(Last Recently Used) Implementation for IGenericObjectCache (alternative
+ * to GenericObjectCache)
+ *
+ * @author Christian Campo
+ */
+public class LRUCache implements IGenericObjectCache {
+
+ private final static Logger LOGGER = Activator.getDefault().getLogger(GenericObjectCache.class.getName());
+ private LinkedHashMap lruMap = null;
+ private long timeout;
+ /** minimum count of entries to keep * */
+ private int minimumSize;
+ private int statHit;
+ private int statNotFound;
+ private int statTimeout;
+ private static int statDisplayCount;
+ private String name = "LRUCache : ";
+
+ /**
+ *
+ */
+ public LRUCache() {
+ super();
+ LOGGER.log(LogService.LOG_INFO, "creating new LRUCache instance");
+ }
+
+ public void setHashMap(HashMap map) {
+ if (!(map instanceof LRUHashMap)) {
+ throw new RuntimeException("global Hashmap must be a LRUHashMap");
+ }
+ lruMap = (LRUHashMap) map;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#isGlobalCache()
+ */
+ public boolean isGlobalCache() {
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#setName(java.lang.String)
+ */
+ public void setName(String name) {
+ this.name = name + " : ";
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#setTimeout(int)
+ */
+ public void setTimeout(int milliseconds) {
+ LOGGER.log(LogService.LOG_INFO, "setTimeout = " + milliseconds);
+ timeout = milliseconds;
+ }
+
+ public int getTimeout() {
+ return (int) timeout;
+ }
+
+ public synchronized Object get(Object key) {
+ LOGGER.log(LogService.LOG_DEBUG, "get = " + key);
+ ICacheEntry entry = (SimpleCacheEntry) lruMap.get(key);
+ /** do we find the entry * */
+ if (entry == null) {
+ statNotFound++;
+ printStat();
+ return null;
+ }
+ long timePassed = System.currentTimeMillis() - entry.getTimestamp();
+ /** is the entry expired * */
+ if (timePassed < timeout) {
+ /** does the soft reference still point anywhere * */
+ statHit++;
+ printStat();
+ return entry.getValue();
+ } else {
+ remove(key);
+ statTimeout++;
+ printStat();
+ return null;
+ }
+ }
+
+ public synchronized Object get(Object key, Class callingClass) {
+ return get(key);
+ }
+
+ private void printStat() {
+ statDisplayCount++;
+ if (statDisplayCount > 100) {
+ LOGGER.log(LogService.LOG_INFO, name + "Hit / NotFound / Timeout " + statHit + " / " + statNotFound + " / " + statTimeout);
+ statDisplayCount = 0;
+ }
+ }
+
+ public String getStatistic() {
+ return name + "Hit / NotFound / Miss / Timeout " + statHit + " / " + statNotFound + " / " + statTimeout;
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#put(Object,
+ * java.lang.Object)
+ */
+ public synchronized void put(Object key, Object value) {
+ LOGGER.log(LogService.LOG_DEBUG, "put = " + key + ", " + value);
+ lruMap.put(key, new SimpleCacheEntry(value, key));
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#clear()
+ */
+ public synchronized void clear() {
+ LOGGER.log(LogService.LOG_DEBUG, "clear");
+ lruMap.clear();
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#remove(Object)
+ */
+ public synchronized void remove(Object key) {
+ LOGGER.log(LogService.LOG_DEBUG, "remove = " + key);
+ lruMap.remove(key);
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#size()
+ */
+ public synchronized int size() {
+ LOGGER.log(LogService.LOG_DEBUG, "size <= " + lruMap.size());
+ return lruMap.size();
+ }
+
+ public int getSize() {
+ return size();
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.IGenericObjectCache#setMinimumSize(int)
+ */
+ public void setMinimumSize(int minSize) {
+ LOGGER.log(LogService.LOG_INFO, "setMinSize = " + minSize);
+ minimumSize = minSize;
+ lruMap = new LRUHashMap(minSize);
+ }
+
+ public int getMinimumSize() {
+ return minimumSize;
+ }
+
+ /**
+ * HashMap that implements a Last Recently Used schema on a LinkedHashMap
+ */
+ public static class LRUHashMap extends LinkedHashMap {
+ private int minSize;
+
+ /**
+ * @param minSize
+ */
+ public LRUHashMap(int minSize) {
+ super(minSize, .75F, true);
+ this.minSize = minSize;
+ }
+
+ /**
+ * @see java.util.LinkedHashMap#removeEldestEntry(java.util.Map.Entry)
+ */
+ public boolean removeEldestEntry(Map.Entry eldest) {
+ return size() > minSize;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/internal/GlobalSoftCacheEntry.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/internal/GlobalSoftCacheEntry.java
new file mode 100644
index 0000000..8d1391f
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/internal/GlobalSoftCacheEntry.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.cache.internal;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+
+import org.eclipse.riena.core.cache.CacheFailure;
+
+/**
+ * CacheEntry for global use
+ *
+ * @author Christian Campo
+ */
+public class GlobalSoftCacheEntry extends SoftCacheEntry implements ICacheEntry {
+
+ private ArrayList<SoftReference<?>> values;
+ private SoftReference<?> serializedValue;
+ private ReferenceQueue<?> queue;
+
+ /**
+ * @param value
+ * @param key
+ * @param queue
+ */
+ @SuppressWarnings("unchecked")
+ public GlobalSoftCacheEntry(Object value, Object key, ReferenceQueue<?> queue) {
+ // do not store the value
+ super(key);
+ this.queue = queue;
+ values = new ArrayList<SoftReference<?>>();
+ values.add(new SoftReference(value, queue));
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.internal.ICacheEntry#getValue()
+ */
+ public Object getValue() {
+ return getValue(this.getClass().getClassLoader());
+ }
+
+ /**
+ * @param classLoader
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public Object getValue(ClassLoader classLoader) {
+ for (SoftReference<?> softRef : values) {
+ Object obj = softRef.get();
+ if (obj == null) {
+ return null;
+ }
+ if (obj.getClass().getClassLoader() == null) {
+ return obj;
+ }
+ ClassLoader parmCurrentCL = classLoader;
+ while (parmCurrentCL != null) {
+ if (obj.getClass().getClassLoader() == parmCurrentCL) {
+ return obj;
+ }
+ parmCurrentCL = parmCurrentCL.getParent();
+ }
+ }
+ byte[] byteArray;
+ // if we need the value and put value was never serialized
+ if (serializedValue == null) {
+ // why on earth would the first value be NULL ??
+ if (values.get(0) == null) {
+ return null;
+ }
+ SoftReference<?> ref = values.get(0);
+ Object value = ref.get();
+ // if the garbage collector has removed the value in the meantime,
+ // we don't check the others but
+ // rather decide that the whole value is gone (highly unlikly, since
+ // this was checked above, but you never
+ // know)
+ if (value == null) {
+ return null;
+ }
+ try {
+ // serialize the value
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+ new ObjectOutputStream(byteStream).writeObject(value);
+ byteArray = byteStream.toByteArray();
+ serializedValue = new SoftReference(new SerializedValue(byteArray), queue);
+ } catch (IOException e) {
+ throw new CacheFailure("error creating cache value", e);
+ }
+ } else {
+ SerializedValue value = (SerializedValue) serializedValue.get();
+ if (value == null) {
+ return null;
+ }
+ byteArray = value.getSerializedContent();
+ }
+
+ try {
+ Object obj = new MyObjectInputStream(classLoader, new ByteArrayInputStream(byteArray)).readObject();
+ values.add(new SoftReference(obj, queue));
+ return obj;
+ } catch (Exception e) {
+ throw new CacheFailure("error creating cache value", e);
+ }
+ }
+
+ /**
+ * Object for the SerializedValue
+ */
+ static class SerializedValue {
+
+ private byte[] serializedContent;
+
+ /**
+ * Constructor for serializedValue
+ *
+ * @param serializedContent
+ */
+ public SerializedValue(byte[] serializedContent) {
+ super();
+ this.serializedContent = serializedContent;
+ }
+
+ /**
+ * Return the byte[] of the serialized content
+ *
+ * @return byte[] of serialized content
+ */
+ public byte[] getSerializedContent() {
+ return serializedContent;
+ }
+ }
+
+ static class MyObjectInputStream extends java.io.ObjectInputStream {
+ private ClassLoader myLoader = null;
+
+ /**
+ * @param newLoader
+ * @param theStream
+ * @throws IOException
+ */
+ public MyObjectInputStream(ClassLoader newLoader, InputStream theStream) throws IOException {
+ super(theStream);
+ myLoader = newLoader;
+ }
+
+ protected Class<?> resolveClass(ObjectStreamClass osc) throws IOException, ClassNotFoundException {
+
+ return Class.forName(osc.getName(), true, myLoader);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/internal/ICacheEntry.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/internal/ICacheEntry.java
new file mode 100644
index 0000000..8d6150f
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/internal/ICacheEntry.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.cache.internal;
+
+/**
+ * Interface for cache entries in the various cache implementations
+ *
+ * @author christian campo
+ */
+public interface ICacheEntry {
+
+ /**
+ * Returns the value that is hold in the cache, null if no value was found
+ *
+ * @return value
+ */
+ Object getValue();
+
+ /**
+ * Returns the key of the cache entry
+ *
+ * @return key
+ */
+ Object getKey();
+
+ /**
+ * Returns the timestamp of the cache entry, when it was last put or
+ * touched.
+ *
+ * @return timestamp
+ */
+ long getTimestamp();
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/internal/SimpleCacheEntry.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/internal/SimpleCacheEntry.java
new file mode 100644
index 0000000..d32a6dd
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/internal/SimpleCacheEntry.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.cache.internal;
+
+/**
+ * A simple cache entry that is store in GenericObjectCache
+ *
+ * @author Christian Campo
+ */
+public class SimpleCacheEntry implements ICacheEntry {
+ private Object value;
+ private Object key;
+ private long timestamp;
+
+ /**
+ * @param value
+ * @param key
+ * @param queue
+ */
+ public SimpleCacheEntry(Object value, Object key) {
+ super();
+ this.value = value;
+ this.key = key;
+ timestamp = System.currentTimeMillis();
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public Object getKey() {
+ return key;
+ }
+
+ public long getTimestamp() {
+ return timestamp;
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/internal/SoftCacheEntry.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/internal/SoftCacheEntry.java
new file mode 100644
index 0000000..55ba5bd
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/cache/internal/SoftCacheEntry.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.cache.internal;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+
+/**
+ * CacheEntry with SoftReference (=values can be garbage collected)
+ *
+ * @author Christian Campo
+ */
+public class SoftCacheEntry implements ICacheEntry {
+ private Object key;
+ private long timestamp;
+ private SoftReference<? extends Object> value;
+
+ /**
+ * Create a new Cache Entry without value (for subclasses which have their
+ * own implementation for that)
+ *
+ * @param key
+ */
+ public SoftCacheEntry(Object key) {
+ super();
+ this.key = key;
+ timestamp = System.currentTimeMillis();
+ }
+
+ /**
+ * Creates a new Cache Entry
+ *
+ * @param value
+ * @param key
+ * @param queue
+ */
+ public <T> SoftCacheEntry(T value, Object key, ReferenceQueue<T> queue) {
+ this(key);
+ if (value != null) {
+ this.value = new SoftReference<T>(value, queue);
+ }
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.internal.ICacheEntry#getValue()
+ */
+ public Object getValue() {
+ return value.get();
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.internal.ICacheEntry#getKey()
+ */
+ public Object getKey() {
+ return key;
+ }
+
+ /**
+ * @see org.eclipse.riena.core.cache.internal.ICacheEntry#getTimestamp()
+ */
+ public long getTimestamp() {
+ return timestamp;
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/config/ConfigUtility.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/config/ConfigUtility.java
new file mode 100644
index 0000000..76e3b02
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/config/ConfigUtility.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.config;
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+import org.eclipse.riena.internal.core.config.ConfigProxy;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ManagedService;
+
+/**
+ * This class makes configuration a regular Java POJO easier. It creates a proxy around a business Java POJO. All
+ * configuration that is sent by ConfigAdmin is converted into setter calls.
+ *
+ */
+public class ConfigUtility {
+
+ private BundleContext context;
+
+ /**
+ * standard constructor
+ *
+ * @param context
+ */
+ public ConfigUtility(BundleContext context) {
+ this.context = context;
+ }
+
+ /**
+ * create proxy for business Java POJO
+ *
+ * @param bObject
+ * @param pid
+ */
+ public void createConfigProxy(Object bObject, String pid) {
+ ConfigProxy ms = new ConfigProxy(bObject);
+ Hashtable<String, String> ht = new Hashtable<String, String>();
+ ht.put(Constants.SERVICE_PID, pid);
+ context.registerService(ManagedService.class.getName(), ms, ht);
+ }
+
+ /**
+ * easy access to configuration for a SERVICE_PID
+ *
+ * @param pid
+ * @return
+ */
+ public Configuration getConfig(String pid) {
+ ServiceReference ref = context.getServiceReference(ConfigurationAdmin.class.getName());
+ ConfigurationAdmin cfgAdmin = (ConfigurationAdmin) context.getService(ref);
+ // get config
+ Configuration cfg;
+ try {
+ cfg = cfgAdmin.getConfiguration(pid);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ return cfg;
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/contract/PostCondition.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/contract/PostCondition.java
new file mode 100644
index 0000000..46f5592
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/contract/PostCondition.java
@@ -0,0 +1,221 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.contract;
+
+/**
+ * Collection of static methods to perform postcondition checks due to design by
+ * contract conventions.
+ *
+ */
+public final class PostCondition {
+
+ /**
+ * version ID (controlled by CVS).
+ */
+ public static final String VERSION_ID = "$Id$";
+
+ private PostCondition() {
+ // Utility
+ }
+
+ /**
+ * check a given boolean condition and throw an exception if the condition
+ * is false.
+ *
+ * Example: assertTrue("Age is lower than 18",age >= 18);
+ *
+ * @param message
+ * the message text to be inserted into the exception.
+ * @param condition
+ * the condition.
+ *
+ * @throws PostConditionException
+ * thrown if condition is false.
+ *
+ * @see de.compeople.spirit.core.base.contract.PostConditionException
+ */
+ public static void assertTrue(String message, boolean condition) {
+ if (!condition) {
+ throw new PostConditionException(message);
+ }
+ }
+
+ /**
+ * check a given boolean condition and throw an exception if the condition
+ * is false. If the condition is true return with the object reference
+ * passed.
+ *
+ * Example: return assertTrueAndReturn("Age is lower than
+ * 18",person.getAge() >= 18,person);
+ *
+ * @param message
+ * the message text to be inserted into the exception.
+ * @param condition
+ * the condition.
+ * @param returnValue
+ * any return value.
+ *
+ * @return return with the <code>retObj</code> passed.
+ *
+ * @throws PostConditionException
+ * thrown if condition is false.
+ *
+ * @see de.compeople.spirit.core.base.contract.PostConditionException
+ */
+ public static <T> T assertTrueAndReturn(String message, boolean condition, T returnValue) {
+ assertTrue(message, condition);
+ return returnValue;
+ }
+
+ // /**
+ // * check a given boolean condition and throw an exception if the condition
+ // is false. If the condition is true return with the object reference
+ // passed.
+ // *
+ // * Example: return assertTrueAndReturn("Age is lower than 18",age >=
+ // 18,age);
+ // *
+ // * @param message the message text to be inserted into the exception.
+ // * @param condition the condition.
+ // * @param returnValue any return value.
+ // *
+ // * @return return with the <code>retVal</code> passed.
+ // *
+ // * @throws PostConditionException thrown if condition is false.
+ // *
+ // * @see de.compeople.spirit.core.base.contract.PostConditionException
+ // */
+ // public static int assertTrueAndReturn( String message, boolean condition,
+ // int returnValue ) {
+ // assertTrue( message, condition );
+ // return returnValue;
+ // }
+ //
+ // /**
+ // * check a given boolean condition and throw an exception if the condition
+ // is false. If the condition is true return with the object reference
+ // passed.
+ // *
+ // * Example: return assertTrueAndReturn("Age is lower than 18",age >=
+ // 18,age);
+ // *
+ // * @param message the message text to be inserted into the exception.
+ // * @param condition the condition.
+ // * @param returnValue any return value.
+ // *
+ // * @return return with the <code>retVal</code> passed.
+ // *
+ // * @throws PostConditionException thrown if condition is false.
+ // *
+ // * @see de.compeople.spirit.core.base.contract.PostConditionException
+ // */
+ // public static long assertTrueAndReturn( String message, boolean
+ // condition, long returnValue ) {
+ // assertTrue( message, condition );
+ // return returnValue;
+ // }
+
+ /**
+ * check an object reference for not null and throw an exception if it is
+ * null.
+ *
+ * Example: assertNotNull("Customer", customer);
+ *
+ * @param objectName
+ * the parameter name to be used in the error message.
+ * @param objectToCheck
+ * the object to check.
+ *
+ * @throws PostConditionException
+ * thrown if condition is false.
+ *
+ * @see de.compeople.spirit.core.base.contract.PostConditionException
+ */
+ public static void assertNotNull(String objectName, Object objectToCheck) {
+ // Optimized in order to concatenate Strings only if necessary.
+ // See problem #278
+ if (objectToCheck == null) {
+ throw new PostConditionException("Object reference is null: " + objectName);
+ }
+ }
+
+ /**
+ * check an object reference for not null and throw an exception if it is
+ * null. If the object isn't null return with the object reference.
+ *
+ * Example: return assertNotNullAndReturn("Customer",customer);
+ *
+ * @param objectName
+ * the parameter name to be used in the error message.
+ * @param objectToCheck
+ * the object to check.
+ *
+ * @return return with the <code>objectToCheck</code> passed and checked.
+ *
+ * @throws PostConditionException
+ * thrown if condition is false.
+ *
+ * @see de.compeople.spirit.core.base.contract.PostConditionException
+ */
+ public static <T> T assertNotNullAndReturn(String objectName, T objectToCheck) {
+ assertNotNull(objectName, objectToCheck);
+ return objectToCheck;
+ }
+
+ /**
+ * Check a string reference for not null and not zero length. throw an
+ * exception if the string reference doesn't fulfill this requirements.
+ *
+ * Example: assertNotNullAndNotZeroLength("Customer name", custName);
+ *
+ * @param objectName
+ * the parameter name to be used in the error message.
+ * @param objectToCheck
+ * the object to check.
+ *
+ * @throws PostConditionException
+ * thrown if condition is false.
+ *
+ * @see de.compeople.spirit.core.base.contract.PostConditionException
+ */
+ public static void assertNotNullAndNotZeroLength(String objectName, String objectToCheck) {
+ // Optimized in order to concatenate Strings only if necessary.
+ // See problem #278
+ if ((objectToCheck == null) || (objectToCheck.trim().length() == 0)) {
+ throw new PostConditionException("String is null or has zero-length: " + objectName);
+ }
+ }
+
+ /**
+ * Check a string reference for not null and not zero length. throw an
+ * exception if the string reference doesn't fulfill this requirements. If
+ * the String has been checked successful it's reference will be returned.
+ *
+ * Example: return assertNotNullAndNotZeroLengthAndReturn("Customer
+ * name",custName);
+ *
+ * @param objectName
+ * the parameter name to be used in the error message.
+ * @param objectToCheck
+ * the object to check.
+ *
+ * @return the reference of the string just checked.
+ *
+ * @throws PostConditionException
+ * thrown if condition is false.
+ *
+ * @see de.compeople.spirit.core.base.contract.PostConditionException
+ */
+ public static String assertNotNullAndNotZeroLengthAndReturn(String objectName, String objectToCheck) {
+ assertNotNullAndNotZeroLength(objectName, objectToCheck);
+ return objectToCheck;
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/contract/PostConditionException.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/contract/PostConditionException.java
new file mode 100644
index 0000000..71c77ab
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/contract/PostConditionException.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.contract;
+
+/**
+ * Runtime exception which indicates post condition violation.
+ *
+ */
+public class PostConditionException extends RuntimeException {
+
+ /**
+ * version ID (controlled by CVS).
+ */
+ public static final String VERSION_ID = "$Id$";
+
+ /**
+ * constructor.
+ *
+ * @param msgText
+ * the message text.
+ */
+ public PostConditionException(String msgText) {
+ super(msgText);
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/contract/PreCondition.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/contract/PreCondition.java
new file mode 100644
index 0000000..1653c86
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/contract/PreCondition.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.contract;
+
+/**
+ * Collection of static methods to perform precondition check due to design by
+ * contract conventions.
+ *
+ */
+public final class PreCondition {
+
+ /**
+ * version ID (controlled by CVS).
+ */
+ public static final String VERSION_ID = "$Id$";
+
+ private PreCondition() {
+ // utility class
+ }
+
+ /**
+ * check a given boolean condition and throw an exception if the condition
+ * is false.
+ *
+ * Example: assertTrue("Age is lower than 18",age >= 18);
+ *
+ * @param message
+ * the message text to be inserted into the exception.
+ * @param condition
+ * the condition to check.
+ *
+ * @throws PreConditionException
+ * thrown if condition is false.
+ *
+ * @see de.compeople.spirit.core.base.contract.PreConditionException
+ */
+ public static void assertTrue(String message, boolean condition) {
+ if (!condition) {
+ throw new PreConditionException(message);
+ }
+ }
+
+ /**
+ * check an object reference for not null and throw an exception if it is
+ * null.
+ *
+ * Example: assertNotNull("Customer",customer);
+ *
+ * @param objectName
+ * the parameter name to be used in the error message.
+ * @param objectToCheck
+ * the object to check.
+ *
+ * @throws PreConditionException
+ * thrown if condition is false.
+ *
+ * @see de.compeople.spirit.core.base.contract.PreConditionException
+ */
+ public static void assertNotNull(String objectName, Object objectToCheck) {
+ // Optimized in order to concatenate Strings only if necessary.
+ // See problem #278
+ if (objectToCheck == null) {
+ throw new PreConditionException("Object reference is null: " + objectName);
+ }
+ }
+
+ /**
+ * Check an string reference for not null and not zero length. throw an
+ * exception if the string reference doesn't fulfill this requirements.
+ *
+ * Example: assertNotNullAndNotZeroLength("Customer name",custName);
+ *
+ * @param objectName
+ * the parameter name to be used in the error message.
+ * @param objectToCheck
+ * the string to check.
+ *
+ * @throws PreConditionException
+ * thrown if condition is false.
+ *
+ * @see de.compeople.spirit.core.base.contract.PreConditionException
+ */
+ public static void assertNotNullAndNotZeroLength(String objectName, String objectToCheck) {
+ // Optimized in order to concatenate Strings only if necessary.
+ // See problem #278
+ if ((objectToCheck == null) || (objectToCheck.trim().length() == 0)) {
+ throw new PreConditionException("String argument is null or has zero-length: " + objectName);
+ }
+ }
+}
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/contract/PreConditionException.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/contract/PreConditionException.java
new file mode 100644
index 0000000..c697133
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/contract/PreConditionException.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.contract;
+
+/**
+ * Runtime exception which indicates pre condition violation.
+ *
+ */
+public class PreConditionException extends RuntimeException {
+
+ /**
+ * version ID (controlled by CVS).
+ */
+ public static final String VERSION_ID = "$Id$";
+
+ /**
+ * constructor.
+ *
+ * @param msgText
+ * the message text.
+ */
+ public PreConditionException(String msgText) {
+ super(msgText);
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/exception/ExceptionFailure.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/exception/ExceptionFailure.java
new file mode 100644
index 0000000..420f4d5
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/exception/ExceptionFailure.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.exception;
+
+/**
+ * Failure class for exception handler specific failures.
+ *
+ * @author Stefan Liebig
+ */
+public class ExceptionFailure extends Failure {
+
+ /**
+ * Failure with a simple message.
+ *
+ * @param msg
+ * the message.
+ */
+ public ExceptionFailure(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Failure with a simple message and a cause.
+ *
+ * @param msg
+ * the message.
+ * @param cause
+ * the cause.
+ */
+ public ExceptionFailure(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/exception/ExceptionHelper.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/exception/ExceptionHelper.java
new file mode 100644
index 0000000..0db98bb
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/exception/ExceptionHelper.java
@@ -0,0 +1,459 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.exception;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.riena.core.contract.PostConditionException;
+import org.eclipse.riena.core.contract.PreCondition;
+import org.eclipse.riena.core.contract.PreConditionException;
+
+/**
+ * This class provides several static methods needed by the exception handling
+ * classes.
+ *
+ */
+public final class ExceptionHelper {
+
+ /*
+ * Note: The usage of the LOGGER has been completely removed, because
+ * creating the logger via hivemind caused in some situations throwing an
+ * ExceptionInInitializerError!!!
+ */
+
+ private static final String DOT_STR = ".";
+
+ /**
+ * version ID (controlled by CVS).
+ */
+ public static final String VERSION_ID = "$Id$";
+
+ private static final String EMPTY_STR = "";
+ private static final String LINE_SEPARATOR = "\n";
+ private static final String ITEM_SEPARATOR = ",";
+ private static final String UNKNOWN = "<unknown>";
+ private static final String CALLER_CLASS_NOT_FOUND = "<caller class not found>";
+ private static final String DEFAULT_CLIENT_MSG = "Es ist ein Systemfehler aufgetreten - Referenz-ID: {ID}";
+
+ private final static StackTraceElement[] EMPTY_STACKTRACE_ELEMENTS = new StackTraceElement[] {};
+
+ private static String javaVersion;
+ private static long lastId;
+
+ /**
+ * used to replace the failure id.
+ */
+ public static final String PLACEHOLDER_FAILURE_ID_REGEX = "\\{ID\\}";
+
+ /**
+ * the attribute name to be used inside application classes. To determinate
+ * the version of a class this attribute name will be looked for.
+ */
+ public static final String VERSION_ID_ATTR_NAME = "VERSION_ID";
+
+ static {
+ javaVersion = System.getProperty("java.version");
+ }
+
+ private ExceptionHelper() { /* utitlity class */
+ }
+
+ /**
+ * Get the caller class name. Use the current stacktrace to determine it.
+ *
+ * @param obj
+ * the object to look for.
+ * @return the name of the object class of the caller.
+ */
+ public static String getCallerByRef(Object obj) {
+ return getCallerByName(obj.getClass().getName());
+ }
+
+ /**
+ * Get the caller class name. Use the current stacktrace to determine it.
+ *
+ * @param className
+ * the classname to look for.
+ * @return the name of the object class of the caller.
+ */
+ public static String getCallerByName(String className) {
+ boolean stackFlag = false;
+ StackTraceElement[] trace = new Throwable().getStackTrace();
+
+ for (StackTraceElement ste : trace) {
+ String steClassName = ste.getClassName();
+ if (steClassName.equals(className)) {
+ stackFlag = true;
+ } else {
+ if (stackFlag && !steClassName.startsWith("sun.") && !steClassName.startsWith("java.lang.reflect")) {
+ return steClassName;
+ }
+ }
+ }
+ return CALLER_CLASS_NOT_FOUND;
+ }
+
+ /**
+ * Get the method name of the caller class. Use the current stacktrace to
+ * determine it.
+ *
+ * @param obj
+ * the object to look for.
+ * @return the method name of the calling class.
+ */
+ public static String getCallerMethod(Object obj) {
+ return getCallerMethod(getCallerByRef(obj));
+ }
+
+ /**
+ * Get the method name of the caller class. Use the current stacktrace to
+ * determine it.
+ *
+ * @param className
+ * the class name of the object to look for.
+ * @return the method name of the calling class.
+ */
+ public static String getCallerMethod(String className) {
+ StackTraceElement[] trace = new Throwable().getStackTrace();
+
+ for (StackTraceElement ste : trace) {
+ if (ste.getClassName().equals(className)) {
+ return ste.getMethodName();
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the version id of the class specified.
+ *
+ * @param c
+ * class reference.
+ * @return the version id of the requested class
+ */
+ public static String getVersionId(Class<?> c) {
+ try {
+ Field f = c.getField(VERSION_ID_ATTR_NAME);
+ return EMPTY_STR + f.get(null);
+ } catch (Throwable ex) {
+ return UNKNOWN;
+ }
+ }
+
+ /**
+ * Get the version id of the class specified.
+ *
+ * @param className
+ * class name.
+ * @return the version id of the requested class
+ */
+ public static String getVersionId(String className) {
+ try {
+ if (className == null) {
+ return UNKNOWN;
+ } else {
+ return getVersionId(Class.forName(className));
+ }
+ } catch (Throwable ex) {
+ return UNKNOWN;
+ }
+ }
+
+ /**
+ * Get the recursive resolved stacktrace (cause chain) of the Failure passed
+ * as argument as string.
+ *
+ * @param ex
+ * throwable object reference.
+ * @return stacktrace as string.
+ */
+ public static String getRecursiveStacktrace(Throwable ex) {
+
+ List<Throwable> throwables = new ArrayList<Throwable>();
+ Throwable throwable = ex;
+
+ // collect all throwables avoiding cycles in order to reverse the
+ // sequence
+ while (throwable != null && !throwables.contains(throwable)) {
+ throwables.add(throwable);
+ throwable = throwable.getCause();
+ }
+
+ StringBuilder buffer = new StringBuilder();
+ for (int i = throwables.size() - 1; i > -1; i--) {
+ throwable = throwables.get(i);
+ buffer.append("Exception: ").append(throwable.getClass().getName()).append(": ").append(throwable.getMessage());
+
+ StackTraceElement[] trace = throwable.getStackTrace();
+
+ if (trace.length < 1 || trace[0].getClassName() == null) {
+ buffer.append("No Stacktrace available.");
+ } else {
+ for (StackTraceElement ste : trace) {
+ String className = EMPTY_STR;
+ String pkgName = EMPTY_STR;
+ String steClassName = ste.getClassName();
+ if (steClassName != null) {
+ if (steClassName.lastIndexOf(DOT_STR) > 0) {
+ int locIx = steClassName.lastIndexOf(DOT_STR);
+ className = steClassName.substring(locIx + 1);
+ pkgName = ":" + steClassName.substring(0, locIx);
+ } else {
+ className = steClassName;
+ }
+ }
+ buffer.append(LINE_SEPARATOR).append(className).append(DOT_STR).append(ste.getMethodName()).append("()").append(",").append(
+ ste.getLineNumber()).append(pkgName);
+ }
+ }
+ buffer.append(LINE_SEPARATOR);
+
+ if (i != 0) {
+ buffer.append(LINE_SEPARATOR).append("caused:").append(LINE_SEPARATOR);
+ }
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * Get the resolved stacktrace of the Failure passed as argument as string.
+ *
+ * @param throwable
+ * the throwable to get the stacktrace for.
+ * @return stacktrace as string.
+ */
+ public static String getStacktraceAsString(Throwable throwable) {
+ StringBuilder buffer = new StringBuilder();
+ StackTraceElement[] trace = throwable.getStackTrace();
+ for (StackTraceElement ste : trace) {
+ buffer.append(ste.getClassName()).append(ITEM_SEPARATOR);
+ buffer.append(ste.getMethodName()).append(ITEM_SEPARATOR);
+ buffer.append(ste.getFileName()).append(ITEM_SEPARATOR);
+ buffer.append(ste.getLineNumber()).append(LINE_SEPARATOR);
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Get the stacktrace of the Throwable passed as argument as string in its
+ * original format.
+ *
+ * @param throwable
+ * the throwable to get the stacktrace for.
+ * @return stacktrace as string.
+ */
+ public static String getStacktraceAsOriginalString(Throwable throwable) {
+ StringWriter stringWriter = new StringWriter();
+ throwable.printStackTrace(new PrintWriter(stringWriter));
+ return stringWriter.toString();
+ }
+
+ /**
+ * Warning: This method is dodgy! <br>
+ * <p>
+ * It is a hack and a workaround. <br>
+ * The method deserializes StackTraceInformation to build up an exception.
+ * <br>
+ * Within JDK1.4 <code>stackTraceElement</code> does not have an public
+ * constructor <br>
+ * or set-methods. <br>
+ * However, there is a way by accessing the private fields of the
+ * StackTraceElement. <br>
+ * This does only work when no or a very untight security Manager is used.
+ * <br>
+ * <p>
+ * The structure of Fields in the StackTraceElement is (in correct order
+ * starting with 0): <br>
+ * <code> <br>
+ * private java.lang.String java.lang.StackTraceElement.declaringClass<br>
+ * private java.lang.String java.lang.StackTraceElement.methodName<br>
+ * private java.lang.String java.lang.StackTraceElement.fileName<br>
+ * private int java.lang.StackTraceElement.lineNumber<br>
+ * </code><br>
+ * <p>
+ * The stacktrace string has the following format: <br>
+ * sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
+ * <br>
+ * which is <code>declaringClass.methodName(fileName:lineNumber)</code>.<br>
+ *
+ * @param stacktrace
+ * the stacktrace as concatenated string.
+ * @return StacktraceElement[] the deserialized Stacktrace.
+ * @throws ExceptionFailure
+ * wrappes checked exceptions from java reflection.
+ */
+ public static StackTraceElement[] parseStackTrace(String stacktrace) throws ExceptionFailure {
+
+ // if we do not have a stacktrace (empty string) we don't need to do
+ // anything.
+ if (stacktrace == null || stacktrace.length() == 0) {
+ return EMPTY_STACKTRACE_ELEMENTS;
+ }
+
+ String[] stackTraceElements = stacktrace.split(LINE_SEPARATOR);
+
+ // if there are no stacktrace elements ..
+ if (stackTraceElements.length == 0) {
+ return EMPTY_STACKTRACE_ELEMENTS;
+ }
+
+ Constructor<?> constructor;
+
+ try {
+ constructor = StackTraceElement.class.getDeclaredConstructor(new Class[] { String.class, String.class, String.class, int.class });
+ } catch (NoSuchMethodException e) {
+ throw new ExceptionFailure("Could not get the constructor of StackTraceElement.", e);
+ }
+
+ try {
+
+ // initialize the return vector
+ StackTraceElement[] resultStackTrace = (StackTraceElement[]) Array.newInstance(StackTraceElement.class, stackTraceElements.length);
+
+ // fill stacktrace for each available line
+ for (int i = 0; i < stackTraceElements.length; i++) {
+
+ String[] items = stackTraceElements[i].split(ITEM_SEPARATOR);
+ assert items.length == 4;
+
+ String declaringClass = items[0];
+ String methodName = items[1];
+ String fileName;
+ if (items[2].equals("null")) {
+ fileName = null;
+ } else {
+ fileName = items[2];
+ }
+ int lineNumber = Integer.parseInt(items[3]);
+
+ // create a new instance for the array
+ resultStackTrace[i] = (StackTraceElement) constructor.newInstance(new Object[] { declaringClass, methodName, fileName, lineNumber });
+ }
+
+ return resultStackTrace;
+
+ } catch (Throwable e) {
+ throw new ExceptionFailure("Parsing of exception failed.", e);
+ }
+ }
+
+ /**
+ * @param map
+ * the to get the values from.
+ * @return array of the map values. ordered by failure msg part names.
+ * @pre map != null
+ */
+ public static Object[] createArrayFromMap(Map<String, ? extends Object> map) {
+ PreCondition.assertNotNull("map should not be null!", map);
+
+ String[] messagePartNames = Failure.getMessagePartNames();
+ Object[] args = new Object[messagePartNames.length];
+ for (int i = 0; i < messagePartNames.length; i++) {
+ args[i] = map.get(messagePartNames[i]);
+ }
+ return args;
+ }
+
+ /**
+ * Check the throwable passed and embed it into an exception failure if
+ * necessary.
+ *
+ * @param t
+ * the throwable
+ * @return failure instance
+ */
+ public static Failure toFailure(Throwable t) {
+ if (!(t instanceof Failure)) {
+ String msgText = null;
+ if (t instanceof PreConditionException) {
+ msgText = "PreCondition violated";
+ } else if (t instanceof PostConditionException) {
+ msgText = "PostCondition violated";
+ } else {
+ msgText = "Unexpected exception occurred";
+ }
+ return new ExceptionFailure(msgText + ": " + t, t);
+ }
+
+ return (Failure) t;
+ }
+
+ /**
+ * Check and rethrow the throwable passed. Imbed it into an exception
+ * failure if neccassary.
+ *
+ * @param t
+ * the throwable
+ */
+ public static void toFailureAndThrow(Throwable t) {
+ throw toFailure(t);
+ }
+
+ /**
+ * Get the java version running inside the environmenal JVM.
+ *
+ * @return java version string
+ */
+ public static String getJavaVersion() {
+ return javaVersion;
+ }
+
+ /**
+ * Generate a unique ID satifying the requirements of a Failure instance.
+ *
+ * @return a unique long value
+ */
+ public static long generateFailureID() {
+ synchronized (ExceptionHelper.class) {
+ long newId = new Date().getTime(); // return with milliseconds of
+ // current time
+ while (newId <= lastId) {
+ newId++;
+ }
+ lastId = newId;
+ return newId;
+ }
+ }
+
+ /**
+ * Get the default client message used for unexpected failure situations.
+ *
+ * @return the client message string.
+ */
+ public static String getDefaultClientMsg() {
+ return DEFAULT_CLIENT_MSG;
+ }
+
+ /**
+ * get the primary cause of an exception (nested causes).
+ *
+ * @param ex
+ * @return the primary cause exception or the exception itself if no cause
+ * has been specified
+ */
+ public static Throwable getPrimaryCause(Throwable ex) {
+ if (ex.getCause() != null) {
+ return getPrimaryCause(ex.getCause());
+ } else {
+ return ex;
+ }
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/exception/Failure.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/exception/Failure.java
new file mode 100644
index 0000000..e1f8687
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/exception/Failure.java
@@ -0,0 +1,444 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.exception;
+
+import java.text.DateFormat;
+import java.text.MessageFormat;
+import java.util.Date;
+
+import org.eclipse.equinox.log.Logger;
+import org.eclipse.riena.internal.core.Activator;
+
+/**
+ * Exception for handling of non-recoverable errors/problems (resource
+ * unavailability, runtime exceptions and other system errors). This class
+ * extends <code>java.lang.RuntimeException</code> and is therefore an
+ * unchecked exception.
+ *
+ * @see java.lang.RuntimeException
+ */
+public abstract class Failure extends RuntimeException {
+
+ private static final String UNKNOWN = "<unknown>";
+ private static final String NONE = "<none>";
+ private static final String NO_DETAILS = "No details.";
+
+ /**
+ * version ID (controlled by CVS).
+ */
+ public static final String VERSION_ID = "$Id$";
+
+ private String javaVersion = UNKNOWN;
+
+ private String callerClassName = UNKNOWN;
+ private String callerClassVersion = UNKNOWN;
+ private String callerMethodName = UNKNOWN;
+
+ private String id = "";
+ private Date timestamp;
+
+ private String clientMsg = "";
+ private String serverMsg = "";
+
+ private String nativeErrorCode = NONE;
+
+ private static final int HEX_BASE = 16;
+
+ // package protected for unit test!!
+ static final String[] MESSAGE_PART_NAMES = { "serverMsg", "cause", "id", "timestamp", "callerClassName", "callerClassVersion", "callerMethodName",
+ "nativeErrorCode", "clientMsg", "javaVersion", "stacktrace" };
+
+ /*
+ * Note: The usage of the standard logger has been completly removed,
+ * because creating the logger via hivemind caused in some situations
+ * throwing an ExceptionInInitializerError!!!
+ */
+ private static final Logger LOGGER = Activator.getDefault().getLogger(Failure.class.getName());
+
+ /**
+ * constructor.
+ *
+ * @param cause
+ * exception which has caused this Failure.
+ * @param msg
+ * message text or message code.
+ * @param args
+ * message parameters.
+ */
+ public Failure(String msg, Object[] args, Throwable cause) {
+ super(msg, cause);
+ setDetails(msg, args);
+ }
+
+ /**
+ * constructor.
+ *
+ * @param msg
+ * message text or message code.
+ */
+ public Failure(String msg) {
+ // Note: In the case that no cause is given it neccesary to call the
+ // super constructor
+ // with the same signature. Otherwise it would not be possible to call
+ // the
+ // initCause() method without getting an IllegalStateException!!!!
+ // Every setting of cause (also with null) in Throwable will lock the
+ // cause field of Throwable!
+ super(msg);
+ setDetails(msg, null);
+ }
+
+ /**
+ * constructor.
+ *
+ * @param cause
+ * exception which has caused this Failure.
+ * @param msg
+ * message text or message code.
+ */
+ public Failure(String msg, Throwable cause) {
+ this(msg, null, cause);
+ }
+
+ /**
+ * constructor.
+ *
+ * @param cause
+ * exception which has caused this Failure.
+ * @param msg
+ * message text or message code.
+ * @param arg1
+ * single message parameter.
+ */
+ public Failure(String msg, Object arg1, Throwable cause) {
+ this(msg, new Object[] { arg1 }, cause);
+ }
+
+ /**
+ * constructor.
+ *
+ * @param cause
+ * exception which has caused this Failure.
+ * @param msg
+ * message text or message code.
+ * @param arg1
+ * message parameter 1.
+ * @param arg2
+ * message parameter 2.
+ */
+ public Failure(String msg, Object arg1, Object arg2, Throwable cause) {
+ this(msg, new Object[] { arg1, arg2 }, cause);
+ }
+
+ /**
+ * determine and set the exception details.
+ */
+ private void setDetails(String msg, Object[] args) {
+ setTimestamp(new Date());
+ // setId(Long.toString(ExceptionHelper.generateFailureID(),
+ // HEX_BASE).toUpperCase(Locale.getDefault()));
+ // setJavaVersion(ExceptionHelper.getJavaVersion());
+ // setServerMsg(getFormattedMsgText(msg, args));
+ // setClientMsg(ExceptionHelper.getDefaultClientMsg().replaceAll(ExceptionHelper.PLACEHOLDER_FAILURE_ID_REGEX,
+ // getId()));
+ // setCallerClassName(ExceptionHelper.getCallerByRef(this));
+ // setCallerMethodName(ExceptionHelper.getCallerMethod(getCallerClassName()));
+ // setCallerClassVersion(ExceptionHelper.getVersionId(getCallerClassName()));
+ }
+
+ /**
+ * Format Messagetext.
+ *
+ * @param msg
+ * message text or code.
+ * @return formatted message text.
+ */
+ private String getFormattedMsgText(String msg, Object[] args) {
+ if (msg == null || args == null) {
+ return msg;
+ } else {
+ return new MessageFormat(msg).format(args);
+ }
+ }
+
+ /**
+ * Get value of attribute <code>javaVersion</code>.
+ *
+ * @return value of attribute javaVersion.
+ */
+ public String getJavaVersion() {
+ return javaVersion;
+ }
+
+ /**
+ * Set value of attribute <code>javaVersion</code>.
+ *
+ * @param javaVersion
+ * the java version.
+ */
+ private void setJavaVersion(String javaVersion) {
+ this.javaVersion = javaVersion;
+ }
+
+ /**
+ * Set value of attribute <code>callerClassName</code>.
+ *
+ * @param callerClassName
+ * the parameter value of caller class name.
+ */
+ private void setCallerClassName(String callerClassName) {
+ this.callerClassName = callerClassName;
+ }
+
+ /**
+ * Get value of attribute <code>callerClassName</code>.
+ *
+ * @return value of attribute caller class name.
+ */
+ public String getCallerClassName() {
+ return this.callerClassName;
+ }
+
+ /**
+ * Set value of attribute <code>callerClassVersion</code>.
+ *
+ * @param callerClassVersion
+ * parameter value of caller class version.
+ */
+ private void setCallerClassVersion(String callerClassVersion) {
+ this.callerClassVersion = callerClassVersion;
+ }
+
+ /**
+ * Get value of attribute <code>callerClassVersion</code>.
+ *
+ * @return value of attribute caller class version.
+ */
+ public String getCallerClassVersion() {
+ return this.callerClassVersion;
+ }
+
+ /**
+ * Set value of attribute <code>callerMethodName</code>.
+ *
+ * @param callerMethodName
+ * parameter value of caller method name.
+ */
+ private void setCallerMethodName(String callerMethodName) {
+ this.callerMethodName = callerMethodName;
+ }
+
+ /**
+ * Get value of attribute caller method name.
+ *
+ * @return value of attribute caller method name.
+ */
+ public String getCallerMethodName() {
+ return this.callerMethodName;
+ }
+
+ /**
+ * Set value of attribute <code>id</code>.
+ *
+ * @param id
+ * parameter value of id.
+ */
+ private void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Get value of attribute <code>id</code>. The <code>id</code> is an
+ * unique identifier for this Failure instance. The <code>id</code> is
+ * embedded inside the server and client message text and can be used as a
+ * reference (i.e. inside the logging file) to address the problem.
+ *
+ * @return value of attribute id.
+ */
+ public String getId() {
+ return this.id;
+ }
+
+ /**
+ * Set value of attribute <code>timestamp</code>.
+ *
+ * @param timestamp
+ * parameter value of timestamp.
+ */
+ private void setTimestamp(Date timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ /**
+ * Get value of attribute <code>timestamp</code>.
+ *
+ * @return value of attribute timestamp.
+ */
+ public Date getTimestamp() {
+ return new Date(this.timestamp.getTime());
+ }
+
+ /**
+ * Set value of attribute <code>clientMsg</code>.
+ *
+ * @param clientMsg
+ * parameter value of clientMsg.
+ */
+ public void setClientMsg(String clientMsg) {
+ this.clientMsg = clientMsg;
+ }
+
+ /**
+ * Get value of attribute <code>clientMsg</code>.
+ *
+ * @return value of attribute clientMsg.
+ */
+ public String getClientMsg() {
+ return this.clientMsg;
+ }
+
+ /**
+ * Set value of attribute <code>serverMsg</code>.
+ *
+ * @param serverMsg
+ * parameter value of serverMsg.
+ */
+ public void setServerMsg(String serverMsg) {
+ this.serverMsg = serverMsg;
+ }
+
+ /**
+ * Get value of attribute <code>serverMsg</code>.
+ *
+ * @return value of attribute serverMsg.
+ */
+ public String getServerMsg() {
+ if (this.serverMsg == null) {
+ return "";
+ } else {
+ return this.serverMsg;
+ }
+ }
+
+ /**
+ * Set value of attribute <code>nativeErrorCode</code>.
+ *
+ * @param nativeErrorCode
+ * parameter value of native error code.
+ */
+ public void setNativeErrorCode(String nativeErrorCode) {
+ this.nativeErrorCode = nativeErrorCode;
+ }
+
+ /**
+ * Get value of attribute <code>nativeErrorCode</code>.
+ *
+ * @return value of attribute native error code.
+ */
+ public String getNativeErrorCode() {
+ return this.nativeErrorCode;
+ }
+
+ /**
+ * Get the message part names. Note: This method makes a copy of an internal
+ * string array, to protect it from malicious changes!
+ *
+ * @return the message part names.
+ */
+ public static String[] getMessagePartNames() {
+ String[] copy = new String[MESSAGE_PART_NAMES.length];
+ System.arraycopy(MESSAGE_PART_NAMES, 0, copy, 0, MESSAGE_PART_NAMES.length);
+ return copy;
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+
+ StringBuilder failureText = new StringBuilder(this.getClass().getName());
+ failureText.append(":\n - serverMsg \t\t\t= ");
+ failureText.append(getServerMsg());
+ failureText.append("\n - cause \t\t\t\t= ");
+ failureText.append(getCauseClassName());
+ failureText.append("\n - id \t\t\t\t\t= ");
+ failureText.append(getId());
+ failureText.append("\n - timestamp \t\t\t= ");
+ failureText.append(DateFormat.getInstance().format(timestamp));
+ failureText.append("\n - callerClassName \t= ");
+ failureText.append(getCallerClassName());
+ failureText.append("\n - callerClassVersion \t= ");
+ failureText.append(getCallerClassVersion());
+ failureText.append("\n - callerMethodName \t= ");
+ failureText.append(getCallerMethodName());
+ failureText.append("\n - nativeErrorCode \t= ");
+ failureText.append(getNativeErrorCode());
+ failureText.append("\n - clientMsg \t\t\t= ");
+ failureText.append(getClientMsg());
+ failureText.append("\n - javaVersion \t\t= ");
+ failureText.append(getJavaVersion());
+ return failureText.toString();
+ }
+
+ private String getCauseClassName() {
+ if (getCause() != null) {
+ return getCause().getClass().getName();
+ } else {
+ return null;
+ }
+
+ }
+
+ /**
+ * Get the full stacktrace of all nested exceptions chained to this Failure
+ * instance.
+ *
+ * @return the full stacktrace in string representation.
+ */
+ // public String getRecursiveStacktrace() {
+ // return ExceptionHelper.getRecursiveStacktrace(this);
+ // }
+ /**
+ * @see de.compeople.spirit.core.base.serialization.IImmutableBean#serializeProperties()
+ */
+ // public Object[] serializeProperties() {
+ // Calendar cal = Calendar.getInstance();
+ // cal.setTime(timestamp);
+ // return new Object[] { serverMsg, getCauseClassName(), id, cal,
+ // callerClassName, callerClassVersion,
+ // callerMethodName, nativeErrorCode, clientMsg,
+ // javaVersion, ExceptionHelper.getStacktraceAsString(this) };
+ // }
+ /**
+ * This method is called to clear details that were automatically set by the
+ * constructor but are in fact unknown.
+ */
+ public void clearDetails() {
+ callerClassName = UNKNOWN;
+ callerClassVersion = UNKNOWN;
+ callerMethodName = UNKNOWN;
+ nativeErrorCode = UNKNOWN;
+ clientMsg = NO_DETAILS;
+ javaVersion = UNKNOWN;
+ }
+
+ /**
+ * @param args
+ * @return
+ */
+ private static Object nullify(Object[] args) {
+ if (args == null || args.length == 0) {
+ return null;
+ } else {
+ return args[0];
+ }
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/exception/IExceptionHandler.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/exception/IExceptionHandler.java
new file mode 100644
index 0000000..0ec7930
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/exception/IExceptionHandler.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.exception;
+
+import org.eclipse.equinox.log.Logger;
+import org.eclipse.riena.core.exception.IExceptionHandlerManager.Action;
+
+
+/**
+ * ExceptionHandler can handle exceptions
+ */
+public interface IExceptionHandler {
+ /**
+ * Service ID
+ */
+ String ID = IExceptionHandler.class.getName();
+
+ /**
+ * Indicate that this handler will be invoked before the named handler <code>before</code> If <code>before</code>
+ * is <code>null</code> or the named handler does not exists and there are more than one handlers then the time of
+ * invocation for this handler will be indeterminate.
+ *
+ * @return a handler name
+ */
+ String getBefore();
+
+ /**
+ * Anwers this handler name
+ *
+ * @pre name != null
+ *
+ * @return this handler name
+ */
+ String getName();
+
+ /**
+ * Check if the exception passed can be handled and return an {@link Action} how might to process. This method
+ * should only be called in top level catch blocks like main, ui thread etc... From other locations inside a catch
+ * block use handleCaught(..)
+ *
+ * @pre t != null
+ * @post result != null
+ *
+ * @param t
+ * exception to be handled
+ * @param msg
+ * an optional message
+ * @param logger
+ * to be used for logging
+ *
+ * @return the Action how to process
+ */
+ Action handleUncaught(Throwable t, String msg, Logger logger);
+
+ /**
+ * Check if the exception passed can be handled and return an {@link Action} how might to process. This method
+ * should be used anywhere where an exceptions is catched directly.
+ *
+ * @pre t != null
+ * @post result != null
+ *
+ * @param t
+ * exception to be handled
+ * @param msg
+ * an optional message
+ * @param logger
+ * to be used for logging
+ *
+ * @return the Action how to process
+ *
+ */
+ Action handleCaught(Throwable t, String msg, Logger logger);
+}
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/exception/IExceptionHandlerManager.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/exception/IExceptionHandlerManager.java
new file mode 100644
index 0000000..fea2801
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/exception/IExceptionHandlerManager.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.exception;
+
+import org.eclipse.equinox.log.Logger;
+
+/**
+ * The ExceptionHandlerManager handles exception.
+ */
+public interface IExceptionHandlerManager {
+
+ /**
+ * Service ID
+ */
+ String ID = IExceptionHandlerManager.class.getName();
+
+ /**
+ * Defines actions how to process after the exception was handled.
+ */
+ public enum Action {
+
+ NotHandled,
+
+ Ok,
+
+ Retry,
+
+ Cancel
+ }
+
+ /**
+ * Check if the exception passed can be handled and return an {@link Action} how might to process. This method
+ * should be used anywhere where an exceptions is catched directly.
+ *
+ * @pre t != null
+ * @post result != null
+ *
+ * @param t
+ * exception to be handled
+ * @return the Action how to process
+ */
+ Action handleCaught(Throwable t);
+
+ /**
+ * Check if the exception passed can be handled and return an {@link Action} how might to process. This method
+ * should be used anywhere where an exceptions is catched directly.
+ *
+ * @pre t != null
+ * @post result != null
+ *
+ * @param t
+ * exception to be handled
+ * @param logger
+ * to be used for logging
+ * @return the Action how to process
+ */
+ Action handleCaught(Throwable t, Logger logger);
+
+ /**
+ * Check if the exception passed can be handled and return an {@link Action} how might to process. This method
+ * should be used anywhere where an exceptions is catched directly.
+ *
+ * @pre t != null
+ * @post result != null
+ *
+ * @param t
+ * exception to be handled
+ * @param msg
+ * an optional message
+ * @return the Action how to process
+ */
+ Action handleCaught(Throwable t, String msg);
+
+ /**
+ * Check if the exception passed can be handled and return an {@link Action} how might to process. This method
+ * should be used anywhere where an exceptions is catched directly.
+ *
+ * @pre t != null
+ * @post result != null
+ *
+ * @param t
+ * exception to be handled
+ * @param msg
+ * an optional message
+ * @param logger
+ * to be used for logging
+ * @return the Action how to process
+ */
+ Action handleCaught(Throwable t, String msg, Logger logger);
+
+ /**
+ * Check if the exception passed can be handled and return an {@link Action} how might to process. This method
+ * should only be called in top level catch blocks like main, ui thread etc... From other locations inside a catch
+ * block use handleCaught(..)
+ *
+ * @pre t != null
+ * @post result != null
+ *
+ * @param t
+ * exception to be handled
+ * @param msg
+ * an optional message
+ * @param logger
+ * to be used for logging
+ * @return the Action how to process
+ */
+ Action handleUncaught(Throwable t, String msg, Logger logger);
+}
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/extension/util/ExtensionUtility.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/extension/util/ExtensionUtility.java
new file mode 100644
index 0000000..9462e93
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/extension/util/ExtensionUtility.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.extension.util;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.RegistryFactory;
+
+/**
+ * ExtensionUtility maps Extensions to Interfaces. Extension properties can then be read by access the getters in the
+ * interface definition. ExtensionUtility instantiates generic proxies to do this.
+ *
+ * The ExtensionUtility does not know the schema so it can only trust that the extension and the interface match.
+ *
+ */
+public class ExtensionUtility {
+
+ /**
+ * Static method to read extensions
+ *
+ * @param extensionPoint
+ * @param interf
+ * @return
+ */
+ public static <T> T[] readExtensions(String extensionPoint, Class<T> interf) {
+ IExtensionRegistry registry = RegistryFactory.getRegistry();
+ IExtensionPoint extPoint = registry.getExtensionPoint(extensionPoint);
+ if (extPoint == null) {
+ return null;
+ }
+ IExtension[] cfgExtensions = extPoint.getExtensions();
+ if (cfgExtensions.length == 0) {
+ return null;
+ }
+ T[] objects = (T[]) Array.newInstance(interf, cfgExtensions.length);
+ int i = 0;
+ for (IExtension cfgExt : cfgExtensions) {
+ Array.set(objects, i++, Proxy.newProxyInstance(interf.getClassLoader(), new Class[] { interf }, new InterfaceInvocationHandler(cfgExt
+ .getConfigurationElements()[0], interf)));
+ }
+ return objects;
+ }
+
+ /**
+ * InvocationHandler for managing proxies for the extension to interface proxy mapping
+ *
+ */
+ private static class InterfaceInvocationHandler implements InvocationHandler {
+
+ private IConfigurationElement config;
+ private Class<?> interf;
+
+ InterfaceInvocationHandler(IConfigurationElement config, Class<?> interf) {
+ this.config = config;
+ this.interf = interf;
+ }
+
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if (method.getName().startsWith("get")) {
+ Method[] meths = interf.getMethods();
+ for (Method meth : meths) {
+ if (meth.getName().equals(method.getName())) {
+ Class<?> retType = meth.getReturnType();
+ String name = method.getName().substring("get".length());
+ name = name.substring(0, 1).toLowerCase() + name.substring(1);
+ if (retType.equals(String.class)) {
+ return config.getAttribute(name);
+ } else if (retType.equals(Boolean.TYPE)) {
+ return new Boolean(config.getAttribute(name));
+ } else if (retType.isInterface()) {
+ IConfigurationElement cfgElement = config.getChildren(name)[0];
+ if (cfgElement == null) {
+ return null;
+ }
+ return Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] { retType }, new InterfaceInvocationHandler(cfgElement,
+ retType));
+ }
+ }
+ }
+ throw new UnsupportedOperationException("property for method " + method.getName() + " not found.");
+ }
+ if (method.getName().startsWith("create")) {
+ String name = method.getName().substring("create".length());
+ name = name.substring(0, 1).toLowerCase() + name.substring(1);
+ return config.createExecutableExtension(name);
+ }
+ throw new UnsupportedOperationException("only getXXX or createXXX is supported");
+ }
+ }
+
+}
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/logging/AlwaysFilter.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/logging/AlwaysFilter.java
new file mode 100644
index 0000000..801279e
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/logging/AlwaysFilter.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.logging;
+
+import org.eclipse.equinox.log.LogFilter;
+import org.osgi.framework.Bundle;
+
+public class AlwaysFilter implements LogFilter {
+
+ public boolean isLoggable(Bundle b, String loggerName, int logLevel) {
+ return true;
+ }
+
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/logging/Log4jLogListener.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/logging/Log4jLogListener.java
new file mode 100644
index 0000000..7f76bc5
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/logging/Log4jLogListener.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.logging;
+
+import org.apache.log4j.Logger;
+import org.eclipse.equinox.log.ExtendedLogEntry;
+import org.osgi.service.log.LogEntry;
+import org.osgi.service.log.LogListener;
+
+public class Log4jLogListener implements LogListener {
+
+ public void logged(LogEntry entry) {
+ ExtendedLogEntry eEntry = (ExtendedLogEntry) entry;
+
+ Logger logger = Logger.getLogger(eEntry.getLoggerName());
+
+ logger.info(eEntry.getMessage());
+ }
+
+}
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/logging/LogUtil.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/logging/LogUtil.java
new file mode 100644
index 0000000..d83a50a
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/logging/LogUtil.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.logging;
+
+import org.eclipse.equinox.log.ExtendedLogReaderService;
+import org.eclipse.equinox.log.ExtendedLogService;
+import org.eclipse.equinox.log.Logger;
+import org.eclipse.riena.internal.core.Activator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+
+/**
+ * Wrapper to access the existing Logger.
+ */
+public class LogUtil {
+
+ private ServiceReference logServiceReference;
+ private ExtendedLogService logService;
+ private ServiceReference logReaderServiceReference;
+ private ExtendedLogReaderService logReaderService;
+ private boolean initialized = false;
+ private BundleContext context;
+
+ public LogUtil(BundleContext context) {
+ this.context = context;
+ }
+
+ public Logger getLogger(String name) {
+ if (!initialized) {
+ init();
+ }
+ if (logService != null) {
+ return logService.getLogger(name);
+ } else {
+ return new NullLogger();
+ }
+
+ }
+
+ public void init() {
+ logServiceReference = context.getServiceReference(ExtendedLogService.class.getName());
+ if (logServiceReference != null) {
+ logService = (ExtendedLogService) Activator.getDefault().getContext().getService(logServiceReference);
+ }
+
+ ServiceListener logServiceListener = new ServiceListener() {
+
+ public void serviceChanged(ServiceEvent event) {
+ if (event.getType() == ServiceEvent.REGISTERED) {
+ logServiceReference = event.getServiceReference();
+ logService = (ExtendedLogService) Activator.getDefault().getContext().getService(logServiceReference);
+ getLogger("Campo").log(LogService.LOG_INFO, "Stefan");
+ } else if (event.getType() == ServiceEvent.UNREGISTERING) {
+ context.ungetService(logServiceReference);
+ logServiceReference = null;
+ logService = null;
+ }
+ }
+
+ };
+
+ logReaderServiceReference = context.getServiceReference(ExtendedLogReaderService.class.getName());
+ if (logReaderServiceReference != null) {
+ logReaderService = (ExtendedLogReaderService) Activator.getDefault().getContext().getService(logReaderServiceReference);
+ }
+
+ try {
+ context.addServiceListener(logServiceListener, "(objectClass=" + ExtendedLogService.class.getName() + ")");
+ } catch (InvalidSyntaxException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ ServiceListener logReaderServiceListener = new ServiceListener() {
+
+ public void serviceChanged(ServiceEvent event) {
+ if (event.getType() == ServiceEvent.REGISTERED) {
+ logReaderServiceReference = event.getServiceReference();
+ logReaderService = (ExtendedLogReaderService) Activator.getDefault().getContext().getService(logReaderServiceReference);
+ } else if (event.getType() == ServiceEvent.UNREGISTERING) {
+ context.ungetService(logReaderServiceReference);
+ logReaderServiceReference = null;
+ logReaderService = null;
+ }
+ }
+
+ };
+ if (logReaderService != null) {
+ logReaderService.addLogListener(new SysoLogListener(), new AlwaysFilter());
+ logReaderService.addLogListener(new Log4jLogListener(), new AlwaysFilter());
+ }
+
+ try {
+ context.addServiceListener(logReaderServiceListener, "(objectClass=" + ExtendedLogReaderService.class.getName() + ")");
+ } catch (InvalidSyntaxException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+}
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/logging/NullLogger.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/logging/NullLogger.java
new file mode 100644
index 0000000..d29f395
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/logging/NullLogger.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.logging;
+
+import org.eclipse.equinox.log.Logger;
+import org.osgi.framework.ServiceReference;
+
+class NullLogger implements Logger {
+
+ public String getName() {
+ return null;
+ }
+
+ public boolean isLoggable(int level) {
+ return false;
+ }
+
+ public void log(int level, String message) {
+ }
+
+ public void log(int level, String message, Throwable exception) {
+ }
+
+ public void log(ServiceReference sr, int level, String message) {
+ }
+
+ public void log(ServiceReference sr, int level, String message, Throwable exception) {
+ }
+
+ public void log(Object context, int level, String message) {
+ }
+
+ public void log(Object context, int level, String message, Throwable exception) {
+ }
+
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/logging/SysoLogListener.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/logging/SysoLogListener.java
new file mode 100644
index 0000000..47ded84
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/logging/SysoLogListener.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.logging;
+
+import java.util.Date;
+
+import org.eclipse.equinox.log.ExtendedLogEntry;
+import org.osgi.service.log.LogEntry;
+import org.osgi.service.log.LogListener;
+
+public class SysoLogListener implements LogListener {
+
+ public void logged(LogEntry entry) {
+ ExtendedLogEntry eEntry = (ExtendedLogEntry) entry;
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(new Date(eEntry.getTime()).toString()).append(' ');
+ buffer.append(eEntry.getLevel()).append(' ');
+ buffer.append(eEntry.getLoggerName()).append(' ');
+ buffer.append(eEntry.getContext()).append(' ');
+ buffer.append(entry.getMessage());
+ System.out.println(buffer.toString());
+ if (eEntry.getException() != null) {
+ eEntry.getException().printStackTrace(System.out);
+ }
+ }
+}
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/marker/AbstractMarker.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/marker/AbstractMarker.java
new file mode 100644
index 0000000..cf4a321
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/marker/AbstractMarker.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.marker;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.riena.core.contract.PreCondition;
+
+/**
+ * An abstract implementation of the {@link IMarker IMarker}interface which
+ * implements managing the attributes.
+ *
+ */
+public abstract class AbstractMarker implements IMarker {
+
+ private Map<String, Object> attributeMap = new HashMap<String, Object>(0, 1.0f);
+ private Set<IMarkerAttributeChangeListener> attributeChangeListeners = new HashSet<IMarkerAttributeChangeListener>(1, 1.0f);
+
+ /**
+ * @see IMarker#getAttribute(String)
+ */
+ public Object getAttribute(String name) {
+ PreCondition.assertNotNullAndNotZeroLength("name", name);
+ return attributeMap.get(name);
+ }
+
+ /**
+ * @see IMarker#getAttribute(String, Object)
+ */
+ public Object getAttribute(String name, Object defaultValue) {
+ Object value = getAttribute(name);
+ if (value == null) {
+ return defaultValue;
+ }
+ return value;
+ }
+
+ /**
+ * @see IMarker#getAttributes()
+ */
+ public Map<String, Object> getAttributes() {
+ return new HashMap<String, Object>(attributeMap);
+ }
+
+ /**
+ * @see IMarker#setAttribute(String, Object)
+ */
+ public void setAttribute(String name, Object value) {
+ PreCondition.assertNotNullAndNotZeroLength("name", name);
+ Object oldValue = attributeMap.get(name);
+ if ((value != null && !value.equals(oldValue)) || (value == null && oldValue != null)) {
+ attributeMap.put(name, value);
+ fireAttributesChanged();
+ }
+ }
+
+ private void fireAttributesChanged() {
+ Iterator<IMarkerAttributeChangeListener> listenerIterator = attributeChangeListeners.iterator();
+ while (listenerIterator.hasNext()) {
+ IMarkerAttributeChangeListener listener = (IMarkerAttributeChangeListener) listenerIterator.next();
+ listener.attributesChanged();
+ }
+ }
+
+ /**
+ * @see de.compeople.spirit.core.client.uibinding.IMarker#addAttributeChangeListener(de.compeople.spirit.core.client.uibinding.IMarkerAttributeChangeListener)
+ */
+ public void addAttributeChangeListener(IMarkerAttributeChangeListener listener) {
+ attributeChangeListeners.add(listener);
+ }
+
+ /**
+ * @see de.compeople.spirit.core.client.uibinding.IMarker#removeAttributeChangeListener(de.compeople.spirit.core.client.uibinding.IMarkerAttributeChangeListener)
+ */
+ public void removeAttributeChangeListener(IMarkerAttributeChangeListener listener) {
+ attributeChangeListeners.remove(listener);
+ }
+
+ /**
+ * @see Object#equals(Object)
+ */
+ public boolean equals(Object other) {
+ if (!(other instanceof AbstractMarker)) {
+ return false;
+ }
+ if (!getClass().equals(other.getClass())) {
+ return false;
+ }
+ AbstractMarker otherMarker = (AbstractMarker) other;
+ return getAttributes().equals(otherMarker.getAttributes());
+ }
+
+ /**
+ * @see Object#hashCode()
+ */
+ public int hashCode() {
+ return getClass().hashCode();
+ }
+
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/marker/IMarkable.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/marker/IMarkable.java
new file mode 100644
index 0000000..67b747d
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/marker/IMarkable.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.marker;
+
+import java.util.Collection;
+
+/**
+ * An interface to combine all markable objects. e.g. Adapter and Controller
+ * This interfaces describes the minimal capabilities of markable objects
+ *
+ * @author Sebastian Stanossek
+ */
+
+public interface IMarkable {
+
+ /**
+ * Adds a marker to the markable object.
+ *
+ * @param marker
+ * the marker to add.
+ */
+ void addMarker(IMarker marker);
+
+ /**
+ * Removes a marker from the markable object.
+ *
+ * @param marker
+ * the marker to remove.
+ */
+ void removeMarker(IMarker marker);
+
+ /**
+ * Removes all marker from the markable object.
+ */
+ void removeAllMarkers();
+
+ /**
+ * Returns all markers corresponding to a certain type.
+ *
+ * @param type
+ * the type of markers.
+ * @return markers corresponding to a certain type.
+ */
+ <T extends IMarker> Collection<T> getMarkersOfType(Class<T> type);
+
+ /**
+ * Returns the markers of the markable object
+ *
+ * @return The markers of the markable object.
+ */
+ Collection<? extends IMarker> getMarkers();
+}
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/marker/IMarker.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/marker/IMarker.java
new file mode 100644
index 0000000..c67bb31
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/marker/IMarker.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.marker;
+
+import java.util.Map;
+
+/**
+ * A <code>IMarker</code> is used to mark an adapter, resp. its associated UI
+ * control. Implementations supported by Spirit are and
+ * {@link MandatoryMarker MandatoryMarker}{@link ErrorMarker ErrorMarker}.
+ *
+ */
+public interface IMarker {
+
+ /**
+ * Returns the attribute with the given <code>name</code>, or
+ * <code>null</code> if it does not exist.
+ *
+ * @param name
+ * the name of attribute.
+ *
+ * @return the attribute with the given <code>name</code>.
+ *
+ * @pre name != null
+ */
+ Object getAttribute(String name);
+
+ /**
+ * Returns the attribute with the given <code>name</code>, or the
+ * <code>defaultValue</code> if it does not exist.
+ *
+ * @param name
+ * the name of attribute.
+ * @param defaultValue
+ * the value that will be returned not attribute with the given
+ * name was found.
+ *
+ * @return the attribute with the given <code>name</code>.
+ *
+ * @pre name != null
+ */
+ Object getAttribute(String name, Object defaultValue);
+
+ /**
+ * @return a Map mapping the attributes' names to their values.
+ */
+ Map<String, ?> getAttributes();
+
+ /**
+ * Sets the <code>value</code> of the attribute with the given
+ * <code>name</code>.
+ *
+ * @param name
+ * the name of the attribute.
+ * @param value
+ * the value of the attribute.
+ *
+ * @pre name != null
+ */
+ void setAttribute(String name, Object value);
+
+ /**
+ * Adds an object listening for changes of the markers attributes.
+ *
+ * @param listener
+ * The new listener.
+ */
+ void addAttributeChangeListener(IMarkerAttributeChangeListener listener);
+
+ /**
+ * Removes an object listening for changes of the markers attributes.
+ *
+ * @param listener
+ * The listener to remove.
+ */
+ void removeAttributeChangeListener(IMarkerAttributeChangeListener listener);
+
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/marker/IMarkerAttributeChangeListener.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/marker/IMarkerAttributeChangeListener.java
new file mode 100644
index 0000000..4e29ce5
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/marker/IMarkerAttributeChangeListener.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.marker;
+
+/**
+ * Listening for changes of a markers attributes.
+ *
+ */
+public interface IMarkerAttributeChangeListener {
+
+ /**
+ * Invoked when the attributes of a marker have changed.
+ */
+ void attributesChanged();
+
+}
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/marker/Markable.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/marker/Markable.java
new file mode 100644
index 0000000..509e226
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/marker/Markable.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.marker;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Standard implementation for the Markable interface, can be used by other
+ * objects to delegate
+ */
+public class Markable implements IMarkable {
+
+ private Set<IMarker> markers;
+
+ /**
+ * Create new Instance and initialize
+ */
+ public Markable() {
+ super();
+ markers = new HashSet<IMarker>();
+ }
+
+ /**
+ * @see org.eclipse.riena.core.marker.IMarkable#addMarker(org.eclipse.riena.core.marker.IMarker)
+ */
+ public void addMarker(IMarker marker) {
+ markers.add(marker);
+ }
+
+ /**
+ * @see org.eclipse.riena.core.marker.IMarkable#getMarkers()
+ */
+ public Collection<? extends IMarker> getMarkers() {
+ return markers;
+ }
+
+ /**
+ * @see org.eclipse.riena.core.marker.IMarkable#getMarkersOfType(java.lang.Class)
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends IMarker> Collection<T> getMarkersOfType(Class<T> type) {
+ if (type == null) {
+ return Collections.emptyList();
+ }
+ List<T> typedMarkerList = new ArrayList<T>();
+
+ for (IMarker marker : getMarkers()) {
+ if (type.isAssignableFrom(marker.getClass())) {
+ typedMarkerList.add((T) marker);
+ }
+ }
+ return typedMarkerList;
+ }
+
+ /**
+ * @see org.eclipse.riena.core.marker.IMarkable#removeAllMarkers()
+ */
+ public void removeAllMarkers() {
+ markers.clear();
+ }
+
+ /**
+ * @see org.eclipse.riena.core.marker.IMarkable#removeMarker(org.eclipse.riena.core.marker.IMarker)
+ */
+ public void removeMarker(IMarker marker) {
+ markers.remove(marker);
+ }
+
+}
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/service/ServiceInjector.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/service/ServiceInjector.java
new file mode 100644
index 0000000..59929ca
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/service/ServiceInjector.java
@@ -0,0 +1,270 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.service;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.riena.core.util.PropertiesUtils;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * The ServiceInjector simplifies finding OSGi Services and injects them into a
+ * target object. An target object defines named bind and unbind methods. The
+ * ServiceInjector calls the bind method when the specified service was
+ * registered or modified. ServiceInjector calls the unbind method when the
+ * specified service becomes unregistered.
+ * <p>
+ * ServiceInjector tracks the specified OSGi Service after calls
+ * {@link #start()} and stop tracks after calls {@link #stop()}.
+ *
+ */
+public class ServiceInjector {
+ private boolean started = false;
+ private List<ServiceReference> trackedServiceRefs;
+ private BundleContext context;
+ private ServiceListener serviceListner;
+ private Object target;
+ private String bindMethod;
+ private String unbindMethod;
+ private String filter;
+ private String serviceId;
+
+ /**
+ * public constructor for ServiceInjector. only used for testing
+ */
+ public ServiceInjector() {
+ super();
+ }
+
+ /**
+ * Creates an ServiceInjector with the given parameters.
+ *
+ * @param context
+ * context <code>BundleContext</code> object against which the
+ * tracking is done.
+ * @param serviceId
+ * of the OSGi service to track
+ * @param target
+ * becomes the OSGi service injected
+ * @param bindMethod
+ * to call at target after the OSGi Service becomes registered or
+ * modified
+ * @param unbindMethod
+ * to call at target after the OSGi Service becomes unregistered
+ */
+ public ServiceInjector(BundleContext context, String serviceId, Object target, String bindMethod, String unbindMethod) {
+ this(context, serviceId, "(objectClass=" + serviceId + ")", target, bindMethod, unbindMethod);
+ }
+
+ /**
+ * Creates ServiceInjector with the given parameters and filter.
+ *
+ * @param context
+ * context <code>BundleContext</code> object against which the
+ * tracking is done.
+ * @param serviceId
+ * of the OSGi service to track
+ * @param filter
+ * object to select the services to be tracked.
+ * @param target
+ * becomes the OSGi service injected
+ * @param bindMethod
+ * to call at target after the OSGi Service becomes registered or
+ * modified
+ * @param unbindMethod
+ * to call at target after the OSGi Service becomes unregistered
+ */
+ public ServiceInjector(BundleContext context, String serviceId, String filter, Object target, String bindMethod, String unbindMethod) {
+ super();
+ this.context = context;
+ this.serviceId = serviceId;
+ this.filter = filter;
+ if (!methodExists(target, bindMethod)) {
+ System.out.println("bindMethod '" + bindMethod + "' does not exist");
+ throw new AssertionError("bindMethod does not exist");
+ }
+ if (!methodExists(target, unbindMethod)) {
+ System.out.println("unbindMethod '" + unbindMethod + "' does not exist");
+ throw new AssertionError("unbindMethod does not exist");
+ }
+ this.bindMethod = bindMethod;
+ this.unbindMethod = unbindMethod;
+ this.target = target;
+ serviceListner = new MyServiceListener();
+ trackedServiceRefs = new ArrayList<ServiceReference>(1);
+
+ }
+
+ public boolean methodExists(Object target, String methodName) {
+ Method[] methods = target.getClass().getDeclaredMethods();
+ for (Method method : methods) {
+ if (method.getName().equals(methodName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Starts to track the specified OSGi Service
+ */
+ public synchronized void start() {
+ try {
+ // try to find the service initial
+ ServiceReference[] serviceRefs = context.getServiceReferences(serviceId, filter);
+ if (serviceRefs != null) {
+ for (ServiceReference serviceRef : serviceRefs) {
+ bind(serviceRef);
+ }
+ }
+ // add an service listener for register or unregister
+ context.addServiceListener(serviceListner, filter);
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+ started = true;
+ }
+
+ /**
+ * Stops to track the specified OSGi Service
+ */
+ public synchronized void stop() {
+ started = false;
+ context.removeServiceListener(serviceListner);
+ synchronized (trackedServiceRefs) {
+
+ // copy list to array so that I iterate through array and still
+ // remove entries from List concurrently
+ ServiceReference[] serviceRefs = trackedServiceRefs.toArray(new ServiceReference[0]);
+ for (ServiceReference serviceRef : serviceRefs) {
+ unbind(serviceRef);
+ }
+ }
+ }
+
+ protected void handleEvent(ServiceEvent event) {
+ switch (event.getType()) {
+ case ServiceEvent.REGISTERED:
+ bind(event.getServiceReference());
+ break;
+ case ServiceEvent.UNREGISTERING:
+ unbind(event.getServiceReference());
+ break;
+ }
+
+ }
+
+ private void bind(ServiceReference serviceRef) {
+ if (bindMethod == null) {
+ return;
+ }
+ synchronized (trackedServiceRefs) {
+ if (trackedServiceRefs.contains(serviceRef)) {
+ return;
+ }
+ Object property = serviceRef.getProperty("objectClass");
+ String objectClass = PropertiesUtils.accessProperty(property, null);
+ Class<?> clazz = loadClass(objectClass);
+ if (clazz != null) {
+ Object service = context.getService(serviceRef);
+ invoke(bindMethod, clazz, service);
+ }
+ trackedServiceRefs.add(serviceRef);
+ }
+ }
+
+ private void unbind(ServiceReference serviceRef) {
+ if (unbindMethod == null) {
+ return;
+ }
+
+ synchronized (trackedServiceRefs) {
+ if (!trackedServiceRefs.contains(serviceRef)) {
+ return;
+ }
+ Object property = serviceRef.getProperty("objectClass");
+ String objectClass = PropertiesUtils.accessProperty(property, null);
+ Class<?> clazz = loadClass(objectClass);
+ if (clazz != null) {
+ Object service = context.getService(serviceRef);
+ invoke(unbindMethod, clazz, service);
+ }
+ trackedServiceRefs.remove(serviceRef);
+ context.ungetService(serviceRef);
+ }
+ }
+
+ private Class<?> loadClass(String clazz) {
+ try {
+ return context.getBundle().loadClass(clazz);
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private void invoke(String methodName, Class<?> serviceClass, Object service) {
+ try {
+ Method method = target.getClass().getMethod(methodName, new Class[] { serviceClass });
+ method.invoke(target, new Object[] { service });
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Disposes this ServiceInjector.
+ */
+ public void dispose() {
+ if (started) {
+ stop();
+ }
+ context = null;
+ serviceId = null;
+ filter = null;
+ target = null;
+ bindMethod = null;
+ unbindMethod = null;
+ serviceListner = null;
+ trackedServiceRefs = null;
+ }
+
+ class MyServiceListener implements ServiceListener {
+ public void serviceChanged(ServiceEvent event) {
+ if (serviceId != null) {
+ Object property = event.getServiceReference().getProperty("objectClass");
+ String objectClass = PropertiesUtils.accessProperty(property, null);
+ // if serviceId set than only handle this event if id is equal.
+ if (objectClass.equals(serviceId)) {
+ handleEvent(event);
+ }
+ } else {
+ // if no serviceId set handle any event
+ handleEvent(event);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/util/CloneHelper.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/util/CloneHelper.java
new file mode 100644
index 0000000..973b232
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/util/CloneHelper.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Method;
+
+/**
+ * This class offers methods for generic clone operations.
+ *
+ */
+public final class CloneHelper {
+
+ /**
+ * Private default constructor.
+ */
+ private CloneHelper() {
+ super();
+ }
+
+ /**
+ * try to (deep) clone the object passed.
+ *
+ * @param obj
+ * the object to clone.
+ * @return the cloned object.
+ * @throws CloneNotSupportedException
+ */
+ public static Object cloneObject(Object obj) throws CloneNotSupportedException {
+ Object clonedObject;
+
+ if (obj instanceof java.lang.String) {
+ clonedObject = obj; // Strings are immutable, so they can be shared.
+ } else if (obj instanceof Serializable) {
+ try { // serialize+deserialize the object to get a deep copy
+ byte[] array = objectToByteArray(obj);
+ clonedObject = byteArrayToObject(array);
+ } catch (Throwable ex) {
+ throw new CloneNotSupportedException();
+ }
+ } else if (obj instanceof Cloneable) {
+ try {
+ Method method = obj.getClass().getMethod("clone", new Class[0]);
+ clonedObject = method.invoke(obj, new Object[0]);
+ } catch (Throwable ex) {
+ throw new CloneNotSupportedException();
+ }
+ } else {
+ throw new CloneNotSupportedException();
+ }
+
+ return clonedObject;
+ }
+
+ /**
+ * convert any serializable object to a byte array.
+ *
+ * @param obj
+ * the object reference.
+ * @return the result byte array.
+ * @throws IOException
+ * thrown in any case of errors.
+ */
+ private static byte[] objectToByteArray(Object obj) throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(bos);
+ oos.writeObject(obj);
+ oos.flush();
+ byte[] array = bos.toByteArray();
+ bos.close();
+ return array;
+ }
+
+ /**
+ * convert a byte array which represents a serializable object to the object
+ * itself.
+ *
+ * @param array
+ * the byte array.
+ * @return the object.
+ * @throws ClassNotFoundException -
+ * Classloader problem.
+ * @throws IOException -
+ * all other problems.
+ */
+ private static Object byteArrayToObject(byte[] array) throws IOException, ClassNotFoundException {
+ ByteArrayInputStream bais = new ByteArrayInputStream(array);
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ return ois.readObject();
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/util/ContainerModel.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/util/ContainerModel.java
new file mode 100644
index 0000000..d8f0e1f
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/util/ContainerModel.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.util;
+
+public class ContainerModel {
+
+ private static final int CLIENT = 1;
+ private static final int SERVER = 2;
+
+ private static int containerModel = CLIENT;
+ static {
+ String s = System.getProperty("riena.container.model");
+ if (s != null && s.equals("server")) {
+ containerModel = SERVER;
+ }
+ }
+
+ public static boolean isClient() {
+ if (containerModel == CLIENT) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static boolean isServer() {
+ if (containerModel == SERVER) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+}
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/util/InvocationTargetFailure.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/util/InvocationTargetFailure.java
new file mode 100644
index 0000000..93cd79f
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/util/InvocationTargetFailure.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.util;
+
+/**
+ * The <code>InvocationTargetFailure</code> signals errors with the usage of
+ * reflection method calls that throw target exceptions.
+ *
+ * @author Stefan Liebig
+ */
+public class InvocationTargetFailure extends ReflectionFailure {
+
+ /**
+ * Constructor. Create a failure with a message.
+ *
+ * @param msg
+ * the message.
+ */
+ public InvocationTargetFailure(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructor. Create a failure with a message and a target exception.
+ *
+ * @param msg
+ * the message.
+ * @param targetException
+ * the cause.
+ */
+ public InvocationTargetFailure(String msg, Throwable targetException) {
+ super(msg, targetException);
+ }
+
+ /**
+ * Get the thrown target exception.
+ *
+ * @return
+ */
+ public Throwable getTargetException() {
+ return super.getCause();
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/util/Iter.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/util/Iter.java
new file mode 100644
index 0000000..11d13ac
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/util/Iter.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.util;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+/**
+ * The Iter class provides conversions from classes only implementing Iterator or Enumeration such that they can be used
+ * within the extended for()-loop (foreach).
+ *
+ * @author Stefan Liebig
+ */
+public final class Iter {
+
+ private Iter() {
+ // locked
+ }
+
+ /**
+ * Create an Iterable for the given iterator.
+ *
+ * @param <T>
+ * generic type for the Iterable
+ * @param iterator
+ * the iterator (might be null!)
+ *
+ * @return the Iterable
+ */
+ public static <T> Iterable<T> able(Iterator<T> iterator) {
+ if (iterator == null) {
+ return Collections.emptyList();
+ } else {
+ return new IteratorIterable<T>(iterator);
+ }
+ }
+
+ /**
+ * Create an Iterable for the given iterator.
+ *
+ * @param <T>
+ * generic type for the Iterable
+ * @param enumeration
+ * the enumeration (might be null!)
+ *
+ * @return the Iterable
+ */
+ public static <T> Iterable<T> able(Enumeration<T> enumeration) {
+ if (enumeration == null) {
+ return Collections.emptyList();
+ } else {
+ return new IteratorIterable<T>(new EnumerationIterator<T>(enumeration));
+ }
+ }
+
+ /**
+ * Create an Iterable for the given iterator. This method´s intended use is for ´pre generic´ apis.
+ *
+ * @param <T>
+ * generic type for the Iterable
+ * @param iterator
+ * the iterator (might be null!)
+ * @param t
+ * the type of the iterator
+ *
+ * @return the Iterable
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Iterable<T> able(Iterator iterator, Class<T> t) {
+ return able(iterator);
+ }
+
+ /**
+ * Create an Iterable for the given iterator. This method´s intended use is for ´pre generic´ apis.
+ *
+ * @param <T>
+ * generic type for the Iterable
+ * @param enumeration
+ * the enumeration (might be null!)
+ * @param t
+ * the type of the iterator
+ *
+ * @return the Iterable
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Iterable<T> able(Enumeration enumeration, Class<T> t) {
+ return able(enumeration);
+ }
+
+ private static final class IteratorIterable<T> implements Iterable<T> {
+
+ private Iterator<T> iterator;
+
+ private IteratorIterable(Iterator<T> iterator) {
+ this.iterator = iterator;
+ }
+
+ public Iterator<T> iterator() {
+ return iterator;
+ }
+
+ }
+
+ private static final class EnumerationIterator<T> implements Iterator<T> {
+
+ private Enumeration<T> enumeration;
+
+ private EnumerationIterator(Enumeration<T> enumeration) {
+ this.enumeration = enumeration;
+ }
+
+ public boolean hasNext() {
+ return enumeration.hasMoreElements();
+ }
+
+ public T next() {
+ return enumeration.nextElement();
+ }
+
+ public void remove() {
+ throw new NoSuchMethodError("No remove() on an wrapped Enumeration!");
+ }
+
+ }
+}
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/util/PropertiesUtils.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/util/PropertiesUtils.java
new file mode 100644
index 0000000..6e6f21c
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/util/PropertiesUtils.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.util;
+
+/**
+ * PropertiesUtils class
+ *
+ */
+public class PropertiesUtils {
+
+ /**
+ * Answers the String value for the given propValue object. If the propValue not compatible to String or String[]
+ * answers the given <code>returnIfNoString</code> as default. If propValue is an instance of String[] then
+ * answers the item with index=0.
+ *
+ * @param propValue
+ * @param returnIfNoString
+ * @return the String value for propValue or the default value <code>returnIfNoString</code>
+ */
+ public static String accessProperty(Object propValue, String returnIfNoString) {
+ if (propValue instanceof String) { // if api programmed we receive
+ return (String) propValue; // a String
+ } else {
+ if (propValue instanceof String[]) { // for DS we receive a
+ return ((String[]) propValue)[0]; // String array
+ }
+ }
+ return returnIfNoString;
+ }
+
+}
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/util/ReflectionFailure.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/util/ReflectionFailure.java
new file mode 100644
index 0000000..c983e89
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/util/ReflectionFailure.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.util;
+
+/**
+ * The <code>ReflectionFailure</code> signals errors with the usage of
+ * reflection.
+ *
+ * @author Stefan Liebig
+ */
+public class ReflectionFailure extends UtilFailure {
+
+ /**
+ * Constructor. Create a failure with a message.
+ *
+ * @param msg
+ * the message.
+ */
+ public ReflectionFailure(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructor. Create a failure with a message and a cause.
+ *
+ * @param msg
+ * the message.
+ * @param cause
+ * the cause.
+ */
+ public ReflectionFailure(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/util/ReflectionUtils.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/util/ReflectionUtils.java
new file mode 100644
index 0000000..3689f78
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/util/ReflectionUtils.java
@@ -0,0 +1,522 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.util;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+
+import org.eclipse.riena.core.contract.PreCondition;
+
+/**
+ * The <code>ReflectionUtils</code> class is a collection of usefull helpers
+ * when working with reflection. <br>
+ * <b>Note:</b> All methods only throw Failures (i.e. RuntimeExceptions)!
+ *
+ * @author Stefan Liebig
+ */
+public final class ReflectionUtils {
+
+ /**
+ * Private default constructor.
+ */
+ private ReflectionUtils() {
+ // Utility class
+ }
+
+ /**
+ * Create a new instance of type ´className´ by invoking the constructor
+ * with the given list of arguments.
+ *
+ * @param className
+ * the type of new instance.
+ * @param args
+ * the arguments for the constructor.
+ * @return the new instance.
+ * @pre className != null
+ */
+ public static Object newInstance(String className, Object... args) {
+ PreCondition.assertNotNull("className must be given!", className);
+
+ try {
+ return newInstance(Class.forName(className), args);
+ } catch (Exception e) {
+ throw new ReflectionFailure("Error creating instance for " + className + "with parameters " + Arrays.asList(args) + "!", e);
+ }
+ }
+
+ /**
+ * Create a new instance of type ´clazz´ by invoking the constructor with
+ * the given list of arguments.
+ *
+ * @param clazz
+ * the type of new instance.
+ * @param args
+ * the arguments for the constructor.
+ * @return the new instance.
+ * @pre clazz != null
+ */
+ public static <T> T newInstance(Class<T> clazz, Object... args) {
+ PreCondition.assertNotNull("clazz must be given!", clazz);
+
+ try {
+ Class<?>[] clazzes = classesFromObjects(args);
+ Constructor<T> constructor = findMatchingConstructor(clazz, clazzes);
+ return constructor.newInstance(args);
+ } catch (Exception e) {
+ throw new ReflectionFailure("Error creating instance for " + clazz.getName() + "with parameters " + Arrays.asList(args) + "!", e);
+ }
+ }
+
+ /**
+ * Create a new proxy instance of type ´interfaceName´.
+ *
+ * @param interfaceName
+ * the type of new instance.
+ * @param invocationHandler
+ * the invocation handler for the proxy.
+ * @return the new instance.
+ * @pre interfaceName != null
+ * @pre invocationHandler != null
+ */
+ public static Object newInstance(String interfaceName, InvocationHandler invocationHandler) {
+ PreCondition.assertNotNull("interfaceName must be given!", interfaceName);
+ PreCondition.assertNotNull("invocationHandler must be given!", invocationHandler);
+
+ try {
+ return newInstance(Class.forName(interfaceName), invocationHandler);
+ } catch (Exception e) {
+ throw new ReflectionFailure("Error creating proxy instance for " + interfaceName + " !", e);
+ }
+ }
+
+ /**
+ * Create a new proxy instance of type ´interfaze´.
+ *
+ * @param interfaze
+ * the type of new instance.
+ * @param invocationHandler
+ * the invocation handler for the proxy.
+ * @return the new instance.
+ * @pre interfaze != null
+ * @pre invocationHandler != null
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T newInstance(Class<T> interfaze, InvocationHandler invocationHandler) {
+ PreCondition.assertNotNull("interfaceName must be given!", interfaze);
+ PreCondition.assertNotNull("invocationHandler must be given!", invocationHandler);
+
+ Class proxyClass = Proxy.getProxyClass(interfaze.getClassLoader(), new Class<?>[] { interfaze });
+ try {
+ Constructor<T> constructor = proxyClass.getConstructor(new Class[] { InvocationHandler.class });
+ T object = constructor.newInstance(new Object[] { invocationHandler });
+ return object;
+ } catch (Throwable throwable) {
+ throw new ReflectionFailure("Error creating proxy instance for " + interfaze.getName() + " !", throwable);
+ }
+ }
+
+ /**
+ * Invoke an accessible method on a given object with the given parameters.
+ *
+ * @param instance
+ * the instance to invoke the method on, or the class for static
+ * methods.
+ * @param methodName
+ * the name of the method to invoke.
+ * @param args
+ * the actual arguments of the method to invoke.
+ * @return the result of the invocation.
+ * @pre instance != null
+ * @pre methodName != null
+ */
+ public static Object invoke(Object instance, String methodName, Object... args) {
+ return invoke(false, instance, methodName, args);
+ }
+
+ /**
+ * Invoke a ´hidden´ (private, protected, ...) method on a given object.
+ * <br>
+ * <b>This method should not be used for production code but only for unit
+ * tests! </b>
+ *
+ * @param instance
+ * the instance to invoke the method on, or the class for static
+ * methods.
+ * @param methodName
+ * the name of the method to invoke.
+ * @param args
+ * the actual arguments of the method to invoke.
+ * @return the result of the invocation.
+ * @pre instance != null
+ * @pre methodName != null
+ */
+ public static Object invokeHidden(Object instance, String methodName, Object... args) {
+ return invoke(true, instance, methodName, args);
+ }
+
+ /**
+ * Invoke an acccesible method on a given object allowing this method to
+ * throw the given type of exception.<br>
+ * <b>This method should not be used for production code but only for unit
+ * tests! </b>
+ *
+ * @param <T>
+ * @param instance
+ * @param methodName
+ * @param expectedException
+ * @param args
+ * @return
+ * @throws T
+ * @pre instance != null
+ * @pre methodName != null
+ * @pre expectedException != null
+ */
+ @SuppressWarnings("unchecked")
+ public static <T extends Throwable> Object invoke(Object instance, String methodName, Class<T> expectedException, Object... args) throws T {
+ PreCondition.assertNotNull("expectedException should not be null!", expectedException);
+
+ try {
+ return invoke(instance, methodName, args);
+ } catch (InvocationTargetFailure e) {
+ if (expectedException.isAssignableFrom(e.getCause().getClass())) {
+ throw (T) e.getCause();
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * Invoke a ´hidden´ (private, protected, ...) method on a given object
+ * allowing this method to throw the given type of exception.<br>
+ * <b>This method should not be used for production code but only for unit
+ * tests! </b>
+ *
+ * @param <T>
+ * @param instance
+ * @param methodName
+ * @param expectedException
+ * @param args
+ * @return
+ * @throws T
+ * @pre instance != null
+ * @pre methodName != null
+ * @pre expectedException != null
+ */
+ @SuppressWarnings("unchecked")
+ public static <T extends Throwable> Object invokeHidden(Object instance, String methodName, Class<T> expectedException, Object... args) throws T {
+ PreCondition.assertNotNull("expectedException should not be null!", expectedException);
+
+ try {
+ return invokeHidden(instance, methodName, args);
+ } catch (InvocationTargetFailure e) {
+ if (expectedException.isAssignableFrom(e.getCause().getClass())) {
+ throw (T) e.getCause();
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * Invoke a (private, protected, ...) method on a given object. If specified
+ * try to make the method accessible.
+ *
+ * @param open
+ * if true it is tried to make it accessible.
+ * @param instance
+ * the instance to invoke the method on, or the class for static
+ * methods.
+ * @param methodName
+ * the name of the method to invoke.
+ * @param args
+ * the actual arguments of the method to invoke.
+ * @return the result of the invocation.
+ * @pre instance != null
+ * @pre methodName != null
+ */
+ private static Object invoke(boolean open, Object instance, String methodName, Object... args) {
+ PreCondition.assertNotNull("instance must be given!", instance);
+ PreCondition.assertNotNull("methodName must be given!", methodName);
+
+ Class<?> clazz = getClass(instance);
+ Class<?>[] clazzes = classesFromObjects(args);
+ while (clazz != null) {
+ Method method = findMatchingMethod(clazz, methodName, clazzes);
+ if (method != null) {
+ if (open) {
+ method.setAccessible(true);
+ }
+ try {
+ return method.invoke(instance, args);
+ } catch (InvocationTargetException ite) {
+ throw new InvocationTargetFailure("Calling #" + methodName + " on " + instance + " failed.", ite.getTargetException());
+ } catch (IllegalArgumentException e) {
+ throw new ReflectionFailure("Calling #" + methodName + " on " + instance + " failed.", e);
+ } catch (IllegalAccessException e) {
+ throw new ReflectionFailure("Calling #" + methodName + " on " + instance + " failed.", e);
+ }
+ }
+ clazz = clazz.getSuperclass();
+ }
+
+ throw new ReflectionFailure("Could not invoke hidden method " + methodName + " on " + instance.getClass().getName() + "!");
+ }
+
+ /**
+ * Set a ´hidden´ (private, protected, ...) field on a given object. <br>
+ * <b>This field should not be used for production code but only for unit
+ * test. </b>
+ *
+ * @param instance
+ * the instance to set the field, or the class for static fields.
+ * @param fieldName
+ * the name of the field to set.
+ * @param value
+ * the new value for the field (use wrappers for primitive
+ * types).
+ * @pre instance != null
+ * @pre fieldName != null
+ * @pre value != null
+ */
+ public static void setHidden(Object instance, String fieldName, Object value) {
+ PreCondition.assertNotNull("instance must be given!", instance);
+ PreCondition.assertNotNull("fieldName must be given!", fieldName);
+ PreCondition.assertNotNull("value must be given!", value);
+
+ Class<?> clazz = getClass(instance);
+ try {
+ Field field = getDeepField(clazz, fieldName);
+ field.setAccessible(true);
+ field.set(instance, value);
+ } catch (Exception e) {
+ throw new ReflectionFailure("Could not set hidden field " + fieldName + " on " + clazz.getName() + "!", e);
+ }
+ }
+
+ /**
+ * Get a ´hidden´ (private, protected, ...) field from a given object. <br>
+ * <b>This method should not be used for production code but only for unit
+ * test. </b>
+ *
+ * @param instance
+ * the instance to get the field, or the class for static fields
+ * @param fieldName
+ * the name of the field to set.
+ * @return the value of the field (returns wrappers for primitive types).
+ * @pre instance != null
+ * @pre fieldName != null
+ */
+ public static Object getHidden(Object instance, String fieldName) {
+ PreCondition.assertNotNull("instance must be given!", instance);
+ PreCondition.assertNotNull("fieldName must be given!", fieldName);
+
+ Class<?> clazz = getClass(instance);
+ try {
+ Field field = getDeepField(clazz, fieldName);
+ field.setAccessible(true);
+ return field.get(instance);
+ } catch (Exception e) {
+ throw new ReflectionFailure("Could not get hidden field " + fieldName + " on " + clazz.getName() + "!", e);
+ }
+ }
+
+ /**
+ * @param <T>
+ * @param interfaze
+ * @param clazz
+ * @param args
+ * @return
+ */
+ public static <T> T newLazyInstance(Class<T> interfaze, Class clazz, Object... args) {
+ return newInstance(interfaze, new LazyInstantiationHandler(clazz, args));
+ }
+
+ /**
+ * @param <T>
+ * @param interfaze
+ * @param clazz
+ * @param args
+ * @return
+ */
+ public static <T> T newLazyInstance(Class<T> interfaze, String clazz, Object... args) {
+ return newInstance(interfaze, new LazyInstantiationHandler(clazz, args));
+ }
+
+ private static class LazyInstantiationHandler implements InvocationHandler {
+
+ private Object instance;
+
+ private Class clazz;
+
+ private String clazzName;
+
+ private Object[] params;
+
+ /**
+ * @param clazz
+ * @param args
+ */
+ public LazyInstantiationHandler(Class clazz, Object[] args) {
+ this.clazz = clazz;
+ this.params = args;
+ }
+
+ /**
+ * @param clazz
+ * @param args
+ */
+ public LazyInstantiationHandler(String clazz, Object[] args) {
+ this.clazzName = clazz;
+ this.params = args;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if (instance == null) {
+ if (clazz != null) {
+ instance = newInstance(clazz, params);
+ } else {
+ instance = newInstance(clazzName, params);
+ }
+ }
+ // try {
+ return ReflectionUtils.invoke(instance, method.getName(), args);
+ // } catch (Throwable e) {
+ // if ( isDeclaredException( method, e )) {
+ // throw e;
+ // }
+ // throw new ReflectionFailure("", e);
+ // }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> Constructor<T> findMatchingConstructor(Class<T> clazz, Class<?>[] clazzes) {
+ assert clazz != null;
+
+ try {
+ if (clazzes == null) {
+ return clazz.getConstructor();
+ } else {
+ Constructor[] constructors = clazz.getConstructors();
+
+ for (Constructor constructor : constructors) {
+ Class<?>[] expectedParameterTypes = constructor.getParameterTypes();
+ if (expectedParameterTypes.length == clazzes.length) {
+ boolean stop = false;
+ for (int j = 0; j < expectedParameterTypes.length && !stop; j++) {
+ if (!expectedParameterTypes[j].isAssignableFrom(clazzes[j])) {
+ stop = true;
+ }
+ }
+ if (!stop) {
+ return constructor;
+ }
+ }
+ }
+ }
+ throw new ReflectionFailure("Could not find a matching constructor for " + clazz.getName());
+ } catch (NoSuchMethodException nsme) {
+ throw new ReflectionFailure("Could not find a matching constructor for " + clazz.getName(), nsme);
+ }
+ }
+
+ private static Method findMatchingMethod(Class<?> clazz, String name, Class<?>[] clazzes) {
+ assert clazz != null;
+ assert name != null;
+
+ try {
+ if (clazzes == null) {
+ return clazz.getDeclaredMethod(name);
+ } else {
+ Method[] methods = clazz.getDeclaredMethods();
+
+ for (Method method : methods) {
+ if (method.getName().equals(name)) {
+ Class<?>[] expectedParameterTypes = method.getParameterTypes();
+ if (expectedParameterTypes.length == clazzes.length) {
+ boolean stop = false;
+ for (int j = 0; j < expectedParameterTypes.length && !stop; j++) {
+ if (!expectedParameterTypes[j].isAssignableFrom(clazzes[j])) {
+ stop = true;
+ }
+ }
+ if (!stop) {
+ return method;
+ }
+ }
+ }
+ }
+ }
+ return null;
+ } catch (NoSuchMethodException nsme) {
+ return null;
+ }
+ }
+
+ private static Class<? extends Object>[] classesFromObjects(Object[] objects) {
+ Class<?>[] clazzes = null;
+ if (objects != null) {
+ clazzes = new Class<?>[objects.length];
+ for (int i = 0; i < objects.length; i++) {
+ Class<?> argClass = objects[i].getClass();
+ if (argClass == Integer.class) {
+ argClass = int.class;
+ } else if (argClass == Long.class) {
+ argClass = long.class;
+ } else if (argClass == Short.class) {
+ argClass = short.class;
+ } else if (argClass == Boolean.class) {
+ argClass = boolean.class;
+ } else if (argClass == Byte.class) {
+ argClass = byte.class;
+ } else if (argClass == Float.class) {
+ argClass = float.class;
+ } else if (argClass == Double.class) {
+ argClass = double.class;
+ } else if (argClass == Character.class) {
+ argClass = char.class;
+ }
+ clazzes[i] = argClass;
+ }
+ }
+ return clazzes;
+ }
+
+ private static Class<?> getClass(Object instance) {
+ assert instance != null;
+
+ if (instance instanceof Class) {
+ return (Class<?>) instance;
+ } else {
+ return instance.getClass();
+ }
+ }
+
+ private static Field getDeepField(Class<?> clazz, String fieldName) throws NoSuchFieldException {
+ assert clazz != null;
+ assert fieldName != null;
+
+ Class<?> lookIn = clazz;
+ while (lookIn != null) {
+ try {
+ return lookIn.getDeclaredField(fieldName);
+ } catch (NoSuchFieldException nsfe) {
+ lookIn = lookIn.getSuperclass();
+ }
+ }
+ throw new NoSuchFieldException("Could not find field " + fieldName + " within class " + clazz + ".");
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/core/util/UtilFailure.java b/org.eclipse.riena.core/src/org/eclipse/riena/core/util/UtilFailure.java
new file mode 100644
index 0000000..e4c4223
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/core/util/UtilFailure.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.core.util;
+
+import org.eclipse.riena.core.exception.Failure;
+
+/**
+ * Failure class for util specific failures.
+ *
+ * @author Stefan Liebig
+ */
+public class UtilFailure extends Failure {
+
+ /**
+ * Constructor. Failure with a simple message.
+ *
+ * @param msg
+ * the message.
+ */
+ public UtilFailure(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructor. Failure with a simple message and a cause.
+ *
+ * @param msg
+ * the message.
+ * @param cause
+ * the cause.
+ */
+ public UtilFailure(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/internal/core/Activator.java b/org.eclipse.riena.core/src/org/eclipse/riena/internal/core/Activator.java
new file mode 100644
index 0000000..71989ba
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/internal/core/Activator.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.internal.core;
+
+import java.util.Hashtable;
+
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.equinox.log.Logger;
+import org.eclipse.riena.core.logging.LogUtil;
+import org.eclipse.riena.internal.core.config.ConfigFromExtensions;
+import org.eclipse.riena.internal.core.config.ConfigSymbolReplace;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ConfigurationPlugin;
+import org.osgi.service.cm.ManagedService;
+
+public class Activator extends Plugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.riena.core";
+
+ // The shared instance
+ private static Activator plugin;
+ private static BundleContext CONTEXT;
+ private LogUtil logUtil;
+ private ServiceRegistration configSymbolReplace;
+ private ServiceRegistration configurationPlugin;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ CONTEXT = context;
+
+ // register ConfigSymbolReplace that replaces symbols in config strings
+ ConfigSymbolReplace csr = new ConfigSymbolReplace();
+ Hashtable<String, String> ht = new Hashtable<String, String>();
+ ht.put(Constants.SERVICE_PID, "org.eclipse.riena.config.symbols");
+ // register as configurable osgi service
+ configSymbolReplace = context.registerService(ManagedService.class
+ .getName(), csr, ht);
+ // register as config admin configuration plugin
+ configurationPlugin = context.registerService(ConfigurationPlugin.class
+ .getName(), csr, null);
+ // execute the class that reads through the extensions and executes them
+ // as config admin packages
+ new ConfigFromExtensions(context).doConfig();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ configSymbolReplace.unregister();
+ configurationPlugin.unregister();
+ plugin = null;
+ CONTEXT = null;
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+ public static BundleContext getContext() {
+ return CONTEXT;
+ }
+
+ public Logger getLogger(String name) {
+ if (logUtil == null) {
+ logUtil = new LogUtil(CONTEXT);
+ }
+ return logUtil.getLogger(name);
+ }
+}
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/internal/core/config/ConfigAdminHandler.java b/org.eclipse.riena.core/src/org/eclipse/riena/internal/core/config/ConfigAdminHandler.java
new file mode 100644
index 0000000..944d027
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/internal/core/config/ConfigAdminHandler.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.internal.core.config;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.RegistryFactory;
+import org.eclipse.equinox.log.Logger;
+import org.eclipse.riena.internal.core.Activator;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.log.LogService;
+
+public class ConfigAdminHandler {
+ private Logger LOGGER = Activator.getDefault().getLogger(ConfigAdminHandler.class.getName());
+ private BundleContext context;
+
+ ConfigAdminHandler(BundleContext context) {
+ super();
+ this.context = context;
+ }
+
+ public void bind(ConfigurationAdmin cfgAdmin) {
+ try {
+
+ IExtensionRegistry registry = RegistryFactory.getRegistry();
+ IExtension[] cfgExtensions = registry.getExtensionPoint("org.eclipse.riena.config.managedService").getExtensions();
+ for (IExtension cfgExt : cfgExtensions) {
+ Bundle bundle = Platform.getBundle(cfgExt.getNamespaceIdentifier());
+ IConfigurationElement[] configs = cfgExt.getConfigurationElements();
+ for (IConfigurationElement config : configs) {
+ String servicepid = config.getAttribute("servicepid");
+ String pluginid = config.getAttribute("pluginid");
+ if (pluginid != null && pluginid.length() > 0) {
+ bundle = Platform.getBundle(pluginid);
+ if (bundle == null) {
+ LOGGER.log(LogService.LOG_ERROR, "trying to configure managedService with invalid pluginid=" + pluginid
+ + ". Bundle for that plugin not found.");
+ break;
+ }
+ }
+ Configuration configuration = cfgAdmin.getConfiguration(servicepid, /* bundle.getLocation() */null);
+ Dictionary dict = configuration.getProperties();
+ if (dict == null) {
+ dict = new Hashtable();
+ }
+ IConfigurationElement[] properties = config.getChildren();
+ for (IConfigurationElement prop : properties) {
+ String name = prop.getAttribute("name");
+ String value = prop.getAttribute("value");
+ if (name != null) {
+ dict.put(name, value);
+ } else {
+ throw new RuntimeException("name or value are not specified for a property (servicepid=" + servicepid + ") (pluginid=" + pluginid
+ + ")");
+ }
+ }
+ configuration.update(dict);
+
+ }
+ }
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+
+ public void unbind(ConfigurationAdmin cfgAdmin) {
+ return;
+ }
+
+}
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/internal/core/config/ConfigFromExtensions.java b/org.eclipse.riena.core/src/org/eclipse/riena/internal/core/config/ConfigFromExtensions.java
new file mode 100644
index 0000000..1e7c380
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/internal/core/config/ConfigFromExtensions.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.internal.core.config;
+
+import org.eclipse.riena.core.service.ServiceInjector;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * This class reads through the extensions of extension-point
+ * "org.eclipse.riena.config.managedService" and creates configuration objects
+ * for the properties in there and passes them to ConfigAdmin.
+ *
+ * doConfig is normally only called once during initialization.
+ *
+ */
+public class ConfigFromExtensions {
+
+ private BundleContext context;
+
+ /**
+ * Standard constructor
+ *
+ * @param context
+ */
+ public ConfigFromExtensions(BundleContext context) {
+ this.context = context;
+ }
+
+ /**
+ * This method is called once and transforms extensions in configuration as
+ * described in the classes javadoc.
+ */
+ public void doConfig() {
+ new ServiceInjector(context, ConfigurationAdmin.class.getName(),
+ new ConfigAdminHandler(context), "bind", "unbind").start();
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/internal/core/config/ConfigProxy.java b/org.eclipse.riena.core/src/org/eclipse/riena/internal/core/config/ConfigProxy.java
new file mode 100644
index 0000000..6ddf423
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/internal/core/config/ConfigProxy.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.internal.core.config;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+
+/**
+ * This class makes configuration a regular Java POJO easier. Its used by ConfigUtility and is instantiated for each
+ * Java POJO instance that should be wrapped. It translates configuration properties from ConfigAdmin into setter calls
+ * of the underlying Java POJO.
+ *
+ */
+public class ConfigProxy implements ManagedService {
+
+ private Object bObject;
+ private HashMap<String, Method> methods;
+
+ /**
+ * standard constructor that takes the object to wrap as parameter
+ *
+ * @param bObject
+ */
+ public ConfigProxy(Object bObject) {
+ this.bObject = bObject;
+ methods = new HashMap<String, Method>();
+ for (Method method : bObject.getClass().getMethods()) {
+ if (method.getName().startsWith("set")) {
+ methods.put(method.getName(), method);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.cm.ManagedService#updated(java.util.Dictionary)
+ */
+ public void updated(Dictionary properties) throws ConfigurationException {
+ if (properties == null) {
+ return;
+ }
+ Enumeration<?> eKeys = properties.keys();
+ while (eKeys.hasMoreElements()) {
+ Object oKey = eKeys.nextElement();
+ if (oKey instanceof String) {
+ String key = (String) oKey;
+ if (key.equals(Constants.SERVICE_PID)) {
+ continue;
+ }
+ if (key.contains(".")) {
+ System.out.println("skipping " + key);
+ continue;
+ }
+ Object oValue = properties.get(key);
+ String methodName = "set" + key.substring(0, 1).toUpperCase() + key.substring(1);
+ Method m = methods.get(methodName);
+ System.out.println(methodName + " :" + oValue + " ... " + System.currentTimeMillis());
+ try {
+ if (m != null) {
+ m.invoke(bObject, oValue);
+ } else {
+ System.out.println("method does not exist");
+ }
+ } catch (IllegalArgumentException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.riena.core/src/org/eclipse/riena/internal/core/config/ConfigSymbolReplace.java b/org.eclipse.riena.core/src/org/eclipse/riena/internal/core/config/ConfigSymbolReplace.java
new file mode 100644
index 0000000..afdd861
--- /dev/null
+++ b/org.eclipse.riena.core/src/org/eclipse/riena/internal/core/config/ConfigSymbolReplace.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2007 compeople AG 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
+ *
+ * Contributors:
+ * compeople AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.riena.internal.core.config;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+
+import org.eclipse.riena.internal.core.Activator;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ConfigurationPlugin;
+import org.osgi.service.cm.ManagedService;
+
+/**
+ * This class gets notified for each and every configuration that ConfigAdmin applies. ConfigSymbolReplace itself is
+ * configurable by sending configuration to SERVICE_PID = "org.eclipse.riena.config.symbols"
+ *
+ */
+public class ConfigSymbolReplace implements ConfigurationPlugin, ManagedService {
+
+ private HashMap<String, String> symbols = new HashMap<String, String>();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.cm.ConfigurationPlugin#modifyConfiguration(org.osgi.framework.ServiceReference,
+ * java.util.Dictionary)
+ */
+ public void modifyConfiguration(ServiceReference reference, Dictionary properties) {
+ // don't do symbolsource replace for configurations of myself
+ if (reference != null && Activator.getDefault().getContext().getService(reference) == this) {
+ return;
+ }
+ Enumeration<?> enumeration = properties.keys();
+ while (enumeration.hasMoreElements()) {
+ Object key = enumeration.nextElement();
+ Object value = properties.get(key);
+ if (value instanceof String) {
+ if (((String) value).contains("${")) {
+ properties.put(key, replaceSymbol((String) value));
+ }
+ }
+ }
+ }
+
+ /**
+ * looks for symbols in a specific property value
+ *
+ * @param value
+ * @return
+ */
+ private String replaceSymbol(String value) {
+ StringBuilder sb = new StringBuilder(value);
+ int i;
+ while ((i = sb.indexOf("${")) > -1) {
+ int x = sb.substring(i).indexOf('}');
+ if (x > 0) {
+ String key = value.substring(i + 2, i + x);
+ sb.replace(i, i + x + 1, lookupSymbol(key));
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * looks up a symbol in its table
+ *
+ * @param symbol
+ * @return
+ */
+ private String lookupSymbol(String symbol) {
+ String value = symbols.get(symbol);
+ if (value == null) {
+ throw new RuntimeException("symbol " + symbol + " not found.");
+ } else {
+ return value;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.cm.ManagedService#updated(java.util.Dictionary)
+ */
+ public void updated(Dictionary properties) throws ConfigurationException {
+ if (properties == null) {
+ return;
+ }
+ HashMap<String, String> tempSymbols = new HashMap<String, String>();
+ Enumeration<String> enumeration = properties.keys();
+ while (enumeration.hasMoreElements()) {
+ String key = enumeration.nextElement();
+ String value = (String) properties.get(key);
+ tempSymbols.put(key, value);
+ }
+ this.symbols = tempSymbols;
+ }
+
+}