Commits

Sebastian Sdorra  committed 4df5da2

bind decorator factories

  • Participants
  • Parent commits e94229e

Comments (0)

Files changed (7)

File scm-webapp/src/main/java/sonia/scm/BindingExtensionProcessor.java

   {
     this.moduleSet = Sets.newHashSet();
     this.extensions = Sets.newHashSet();
+    this.decoratorFactories = Sets.newHashSet();
   }
 
   //~--- methods --------------------------------------------------------------
    *
    * @param binder
    */
+  public void bindDecorators(Binder binder)
+  {
+    DecoratorBinder decoratorBinder = new DecoratorBinder(binder);
+
+    for (Class<? extends DecoratorFactory<?>> c : decoratorFactories)
+    {
+      decoratorBinder.bindFactory(c);
+    }
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @param binder
+   */
   @SuppressWarnings("unchecked")
   public void bindExtensions(Binder binder)
   {
 
       addModuleClass(extensionClass);
     }
+    else if (DecoratorFactory.class.isAssignableFrom(extensionClass))
+    {
+      decoratorFactories.add(extensionClass);
+    }
     else
     {
       extensions.add(extensionClass);
   //~--- fields ---------------------------------------------------------------
 
   /** Field description */
+  private Set<Class<? extends DecoratorFactory<?>>> decoratorFactories;
+
+  /** Field description */
   private Set<Class<?>> extensions;
 
   /** Field description */

File scm-webapp/src/main/java/sonia/scm/DecoratorBinder.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.inject.Binder;
+import com.google.inject.multibindings.Multibinder;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.group.GroupManagerDecoratorFactory;
+import sonia.scm.repository.RepositoryManagerDecoratorFactory;
+import sonia.scm.user.UserManagerDecoratorFactory;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class DecoratorBinder
+{
+
+  /**
+   * the logger for DecoratorBinder
+   */
+  private static final Logger logger =
+    LoggerFactory.getLogger(DecoratorBinder.class);
+
+  //~--- constructors ---------------------------------------------------------
+
+  /**
+   * Constructs ...
+   *
+   *
+   * @param binder
+   */
+  public DecoratorBinder(Binder binder)
+  {
+    userManagerDecoratorFactories = Multibinder.newSetBinder(binder,
+      UserManagerDecoratorFactory.class);
+    groupManagerDecoratorFactories = Multibinder.newSetBinder(binder,
+      GroupManagerDecoratorFactory.class);
+    repositoryManagerDecoratorFactories = Multibinder.newSetBinder(binder,
+      RepositoryManagerDecoratorFactory.class);
+  }
+
+  //~--- methods --------------------------------------------------------------
+
+  /**
+   * Method description
+   *
+   *
+   * @param factoryClass
+   */
+  public void bindFactory(Class factoryClass)
+  {
+    if (UserManagerDecoratorFactory.class.isAssignableFrom(factoryClass))
+    {
+      if (logger.isInfoEnabled())
+      {
+        logger.info("bind user manager decorator {}");
+      }
+
+      userManagerDecoratorFactories.addBinding().to(factoryClass);
+    }
+    else if (GroupManagerDecoratorFactory.class.isAssignableFrom(factoryClass))
+    {
+      if (logger.isInfoEnabled())
+      {
+        logger.info("bind group manager decorator {}");
+      }
+
+      groupManagerDecoratorFactories.addBinding().to(factoryClass);
+    }
+    else if (
+      RepositoryManagerDecoratorFactory.class.isAssignableFrom(factoryClass))
+    {
+      if (logger.isInfoEnabled())
+      {
+        logger.info("bind repository manager decorator {}");
+      }
+
+      repositoryManagerDecoratorFactories.addBinding().to(factoryClass);
+    }
+  }
+
+  //~--- fields ---------------------------------------------------------------
+
+  /** Field description */
+  private Multibinder<GroupManagerDecoratorFactory> groupManagerDecoratorFactories;
+
+  /** Field description */
+  private Multibinder<RepositoryManagerDecoratorFactory> repositoryManagerDecoratorFactories;
+
+  /** Field description */
+  private Multibinder<UserManagerDecoratorFactory> userManagerDecoratorFactories;
+}

File scm-webapp/src/main/java/sonia/scm/ScmServletModule.java

 
 //~--- non-JDK imports --------------------------------------------------------
 
+import com.google.inject.Provider;
 import com.google.inject.multibindings.Multibinder;
 import com.google.inject.name.Names;
 import com.google.inject.servlet.RequestScoped;
 import sonia.scm.group.DefaultGroupManager;
 import sonia.scm.group.GroupDAO;
 import sonia.scm.group.GroupManager;
+import sonia.scm.group.GroupManagerProvider;
 import sonia.scm.group.xml.XmlGroupDAO;
 import sonia.scm.io.DefaultFileSystem;
 import sonia.scm.io.FileSystem;
 import sonia.scm.repository.RepositoryBrowserUtil;
 import sonia.scm.repository.RepositoryDAO;
 import sonia.scm.repository.RepositoryManager;
+import sonia.scm.repository.RepositoryManagerProvider;
 import sonia.scm.repository.RepositoryProvider;
 import sonia.scm.repository.api.RepositoryServiceFactory;
 import sonia.scm.repository.xml.XmlRepositoryDAO;
 import sonia.scm.user.DefaultUserManager;
 import sonia.scm.user.UserDAO;
 import sonia.scm.user.UserManager;
+import sonia.scm.user.UserManagerProvider;
 import sonia.scm.user.xml.XmlUserDAO;
 import sonia.scm.util.DebugServlet;
 import sonia.scm.util.ScmConfigurationUtil;
 
     bind(SCMContextProvider.class).toInstance(context);
 
+    // bind decorators
+    bindExtProcessor.bindDecorators(binder());
+
     ScmConfiguration config = getScmConfiguration(context);
     CipherUtil cu = CipherUtil.getInstance();
 
     bind(UserDAO.class, XmlUserDAO.class);
     bind(RepositoryDAO.class, XmlRepositoryDAO.class);
 
-    // bind(RepositoryManager.class).annotatedWith(Undecorated.class).to(
-    // BasicRepositoryManager.class);
-    bind(RepositoryManager.class, DefaultRepositoryManager.class);
-    bind(UserManager.class, DefaultUserManager.class);
-    bind(GroupManager.class, DefaultGroupManager.class);
+    bindDecorated(RepositoryManager.class, DefaultRepositoryManager.class,
+      RepositoryManagerProvider.class);
+    bindDecorated(UserManager.class, DefaultUserManager.class,
+      UserManagerProvider.class);
+    bindDecorated(GroupManager.class, DefaultGroupManager.class,
+      GroupManagerProvider.class);
     bind(CGIExecutorFactory.class, DefaultCGIExecutorFactory.class);
     bind(ChangesetViewerUtil.class);
     bind(RepositoryBrowserUtil.class);
   private <T> void bind(Class<T> clazz,
     Class<? extends T> defaultImplementation)
   {
+    Class<? extends T> implementation = find(clazz, defaultImplementation);
+
+    if (logger.isDebugEnabled())
+    {
+      logger.debug("bind {} to {}", clazz, implementation);
+    }
+
+    bind(clazz).to(implementation);
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @param clazz
+   * @param defaultImplementation
+   * @param providerClass
+   * @param <T>
+   */
+  private <T> void bindDecorated(Class<T> clazz,
+    Class<? extends T> defaultImplementation,
+    Class<? extends Provider<T>> providerClass)
+  {
+    Class<? extends T> implementation = find(clazz, defaultImplementation);
+
+    if (logger.isDebugEnabled())
+    {
+      logger.debug("bind undecorated {} to {}", clazz, implementation);
+    }
+
+    bind(clazz).annotatedWith(Undecorated.class).to(implementation);
+
+    if (logger.isDebugEnabled())
+    {
+      logger.debug("bind {} to provider {}", clazz, providerClass);
+    }
+
+    bind(clazz).toProvider(providerClass);
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @param clazz
+   * @param defaultImplementation
+   * @param <T>
+   *
+   * @return
+   */
+  private <T> Class<? extends T> find(Class<T> clazz,
+    Class<? extends T> defaultImplementation)
+  {
     Class<? extends T> implementation = overrides.getOverride(clazz);
 
     if (implementation != null)
     {
-      logger.info("bind {} to override {}", clazz, implementation);
+      logger.info("found override {} for {}", implementation, clazz);
     }
     else
     {
       implementation = defaultImplementation;
 
-      if (logger.isDebugEnabled())
+      if (logger.isTraceEnabled())
       {
-        logger.debug("bind {} to default implementation {}", clazz,
-          implementation);
+        logger.trace(
+          "no override available for {}, using default implementation {}",
+          clazz, implementation);
       }
     }
 
-    bind(clazz).to(implementation);
+    return implementation;
   }
 
   //~--- get methods ----------------------------------------------------------

File scm-webapp/src/main/java/sonia/scm/group/GroupManagerProvider.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.group;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import sonia.scm.Undecorated;
+import sonia.scm.util.Decorators;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.util.Set;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class GroupManagerProvider implements Provider<GroupManager>
+{
+
+  /**
+   * Method description
+   *
+   *
+   * @return
+   */
+  @Override
+  public GroupManager get()
+  {
+    return Decorators.decorate(groupManagerProvider.get(), decoratorFactories);
+  }
+
+  //~--- set methods ----------------------------------------------------------
+
+  /**
+   * Method description
+   *
+   *
+   * @param decoratorFactories
+   */
+  public void setDecoratorFactories(
+    Set<GroupManagerDecoratorFactory> decoratorFactories)
+  {
+    this.decoratorFactories = decoratorFactories;
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @param groupManagerProvider
+   */
+  public void setGroupManagerProvider(
+    Provider<GroupManager> groupManagerProvider)
+  {
+    this.groupManagerProvider = groupManagerProvider;
+  }
+
+  //~--- fields ---------------------------------------------------------------
+
+  /** Field description */
+  @Inject(optional = true)
+  private Set<GroupManagerDecoratorFactory> decoratorFactories;
+
+  /** Field description */
+  @Inject
+  @Undecorated
+  private Provider<GroupManager> groupManagerProvider;
+}

File scm-webapp/src/main/java/sonia/scm/repository/RepositoryManagerProvider.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.repository;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import sonia.scm.Undecorated;
+import sonia.scm.util.Decorators;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.util.Set;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class RepositoryManagerProvider implements Provider<RepositoryManager>
+{
+
+  /**
+   * Method description
+   *
+   *
+   * @return
+   */
+  @Override
+  public RepositoryManager get()
+  {
+    return Decorators.decorate(repositoryManagerProvider.get(),
+      decoratorFactories);
+  }
+
+  //~--- set methods ----------------------------------------------------------
+
+  /**
+   * Method description
+   *
+   *
+   * @param decoratorFactories
+   */
+  public void setDecoratorFactories(
+    Set<RepositoryManagerDecoratorFactory> decoratorFactories)
+  {
+    this.decoratorFactories = decoratorFactories;
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @param repositoryManagerProvider
+   */
+  public void setRepositoryManagerProvider(
+    Provider<RepositoryManager> repositoryManagerProvider)
+  {
+    this.repositoryManagerProvider = repositoryManagerProvider;
+  }
+
+  //~--- fields ---------------------------------------------------------------
+
+  /** Field description */
+  @Inject(optional = true)
+  private Set<RepositoryManagerDecoratorFactory> decoratorFactories;
+
+  /** Field description */
+  @Inject
+  @Undecorated
+  private Provider<RepositoryManager> repositoryManagerProvider;
+}

File scm-webapp/src/main/java/sonia/scm/user/UserManagerProvider.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.user;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+import sonia.scm.Undecorated;
+import sonia.scm.util.Decorators;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.util.Set;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class UserManagerProvider implements Provider<UserManager>
+{
+
+  /**
+   * Method description
+   *
+   *
+   * @return
+   */
+  @Override
+  public UserManager get()
+  {
+    return Decorators.decorate(userManagerProvider.get(), decoratorFactories);
+  }
+
+  //~--- set methods ----------------------------------------------------------
+
+  /**
+   * Method description
+   *
+   *
+   * @param decoratorFactories
+   */
+  public void setDecoratorFactories(
+    Set<UserManagerDecoratorFactory> decoratorFactories)
+  {
+    this.decoratorFactories = decoratorFactories;
+  }
+
+  /**
+   * Method description
+   *
+   *
+   * @param userManagerProvider
+   */
+  public void setUserManagerProvider(Provider<UserManager> userManagerProvider)
+  {
+    this.userManagerProvider = userManagerProvider;
+  }
+
+  //~--- fields ---------------------------------------------------------------
+
+  /** Field description */
+  @Inject(optional = true)
+  private Set<UserManagerDecoratorFactory> decoratorFactories;
+
+  /** Field description */
+  @Inject
+  @Undecorated
+  private Provider<UserManager> userManagerProvider;
+}

File scm-webapp/src/main/java/sonia/scm/util/Decorators.java

+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.util;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sonia.scm.DecoratorFactory;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class Decorators
+{
+
+  /**
+   * the logger for Decorators
+   */
+  private static final Logger logger =
+    LoggerFactory.getLogger(Decorators.class);
+
+  //~--- methods --------------------------------------------------------------
+
+  /**
+   * Method description
+   *
+   *
+   * @param object
+   * @param decoratorFactories
+   * @param <T>
+   *
+   * @return
+   */
+  public static <T> T decorate(T object,
+    Iterable<? extends DecoratorFactory<T>> decoratorFactories)
+  {
+    if (decoratorFactories != null)
+    {
+      for (DecoratorFactory<T> decoratorFactory : decoratorFactories)
+      {
+        if (logger.isDebugEnabled())
+        {
+          logger.debug("decorate {} with {}", object.getClass(),
+            decoratorFactory.getClass());
+        }
+
+        object = decoratorFactory.createDecorator(object);
+      }
+    }
+    else if (logger.isDebugEnabled())
+    {
+      logger.debug("no decorators found for {}", object.getClass());
+    }
+
+    return object;
+  }
+}