mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-10-08 14:51:49 +00:00
Merged HEAD (5.1) to 5.1.N (5.1.1)
119697 bhorje: ACE-4744 javadoc and cleanup git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.1.N/root@120076 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2015 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class AJDanglingExtensionError implements AJExtensibleCompilingError
|
||||
{
|
||||
private Method danglingMethod;
|
||||
private Extend extendDeclaration;
|
||||
|
||||
public AJDanglingExtensionError(Method danglingMethod,Extend extendDeclaration)
|
||||
{
|
||||
super();
|
||||
this.danglingMethod = danglingMethod;
|
||||
this.extendDeclaration=extendDeclaration;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getShortMessage()
|
||||
{
|
||||
return "Dangling extension method "+danglingMethod+" "+extendDeclaration;
|
||||
}
|
||||
|
||||
}
|
@@ -42,6 +42,32 @@ import org.aspectj.lang.reflect.MethodSignature;
|
||||
|
||||
import com.hazelcast.util.ConcurrentHashSet;
|
||||
|
||||
/**
|
||||
* Static utility used for aspectJ extension consistency , routing and for
|
||||
* maintaining thread-local extension-bypass context stack.<br>
|
||||
* AspectJ extension routing distinguishes between the following contexts in
|
||||
* which an extended method (i.e. a method with an {@link Extend} annotation)
|
||||
* can be called:
|
||||
* <ol>
|
||||
* <li>Extend context<br>
|
||||
* when an extended method is called and the extension overrides the method call
|
||||
* </li>
|
||||
* <li>Local proceed context<br>
|
||||
* when an extension method needs to execute the original method that it has
|
||||
* overridden.</li>
|
||||
* <li>Extension bypass context<br>
|
||||
* when a call to an extended method needs to be completed with the extensions
|
||||
* disabled for that call</li>
|
||||
* </ol>
|
||||
* <br>
|
||||
* The {@link AJExtender} can check {@link ExtensionPoint} definitions for
|
||||
* consistency by compiling extensible classes. The compilation process fails if
|
||||
* there are inconsistencies between {@link ExtensionPoint}s and {@link Extend}
|
||||
* annotated methods (egg. an annotated method can not be mapped to a method in
|
||||
* the indicated extension by signature matching).
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public class AJExtender
|
||||
{
|
||||
private static final Object[] SAFE_NULL_ARGS = new Object[0];
|
||||
@@ -50,6 +76,9 @@ public class AJExtender
|
||||
|
||||
private static ConcurrentHashSet<ExtensionRoute> oneTimeLogSet = null;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final ThreadLocal<Stack<Boolean>> ajPointsLocalEnabled = new ThreadLocal<Stack<Boolean>>()
|
||||
{
|
||||
protected Stack<Boolean> initialValue()
|
||||
@@ -60,6 +89,9 @@ public class AJExtender
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
static class ProceedingContext
|
||||
{
|
||||
final Extend extend;
|
||||
@@ -83,12 +115,119 @@ public class AJExtender
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementors are aspectJ extension ignoring closures. When executing
|
||||
* {@link ExtensionBypass}es using {@link AJExtender#run(ExtensionBypass)} or
|
||||
* {@link AJExtender#run(ExtensionBypass, Class[])} the {@link #run()}
|
||||
* method code will ignore extension overrides.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public static interface ExtensionBypass<R>
|
||||
{
|
||||
R run() throws Throwable;
|
||||
}
|
||||
|
||||
public static class CompiledExtensible
|
||||
/**
|
||||
* Thrown-exception or stored error resulted compiling inconsistencies found
|
||||
* during aspectJ extensible classes compilation.
|
||||
*
|
||||
* @see {@link AJExtender#compile(Class)}
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
interface AJExtensibleCompilingError
|
||||
{
|
||||
String getShortMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown or stored on compiling inconsistencies found during aspectJ
|
||||
* extensible classes compilation.
|
||||
*
|
||||
* @see {@link AJExtender#compile(Class)}
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
static class AJExtensibleCompilingException extends Exception implements AJExtensibleCompilingError
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
AJExtensibleCompilingException()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
AJExtensibleCompilingException(String message, Throwable cause, boolean enableSuppression,
|
||||
boolean writableStackTrace)
|
||||
{
|
||||
super(message,
|
||||
cause,
|
||||
enableSuppression,
|
||||
writableStackTrace);
|
||||
}
|
||||
|
||||
AJExtensibleCompilingException(String message, Throwable cause)
|
||||
{
|
||||
super(message,
|
||||
cause);
|
||||
}
|
||||
|
||||
AJExtensibleCompilingException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
AJExtensibleCompilingException(Throwable cause)
|
||||
{
|
||||
super(cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortMessage()
|
||||
{
|
||||
return getMessage();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals the existence of extension methods that are not matched with
|
||||
* same-signature methods through {@link Extend} annotations within
|
||||
* {@link Extensible}.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
static class AJDanglingExtensionError implements AJExtensibleCompilingError
|
||||
{
|
||||
private Method danglingMethod;
|
||||
|
||||
private Extend extendDeclaration;
|
||||
|
||||
AJDanglingExtensionError(Method danglingMethod, Extend extendDeclaration)
|
||||
{
|
||||
super();
|
||||
this.danglingMethod = danglingMethod;
|
||||
this.extendDeclaration = extendDeclaration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortMessage()
|
||||
{
|
||||
return "Dangling extension method " + danglingMethod + " " + extendDeclaration;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An {@link Extensible} sub class compilation result containing all
|
||||
* {@link Extend} mapped routes, not routed or dangling methods within the
|
||||
* give extensible class and/or possible compilation errors.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
static class CompiledExtensible
|
||||
{
|
||||
private Class<? extends Extensible> extensible;
|
||||
|
||||
@@ -98,28 +237,28 @@ public class AJExtender
|
||||
|
||||
private List<AJExtensibleCompilingError> errors = new LinkedList<>();
|
||||
|
||||
public CompiledExtensible(Class<? extends Extensible> extensible)
|
||||
CompiledExtensible(Class<? extends Extensible> extensible)
|
||||
{
|
||||
super();
|
||||
this.extensible = extensible;
|
||||
}
|
||||
|
||||
public Class<? extends Extensible> getExtensible()
|
||||
Class<? extends Extensible> getExtensible()
|
||||
{
|
||||
return this.extensible;
|
||||
}
|
||||
|
||||
public void add(AJExtensibleCompilingError error)
|
||||
void add(AJExtensibleCompilingError error)
|
||||
{
|
||||
this.errors.add(error);
|
||||
}
|
||||
|
||||
public boolean hasErrors()
|
||||
boolean hasErrors()
|
||||
{
|
||||
return !errors.isEmpty();
|
||||
}
|
||||
|
||||
public String getErrorsString()
|
||||
String getErrorsString()
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
@@ -132,12 +271,12 @@ public class AJExtender
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public List<AJExtensibleCompilingError> getErrors()
|
||||
List<AJExtensibleCompilingError> getErrors()
|
||||
{
|
||||
return this.errors;
|
||||
}
|
||||
|
||||
public void add(ExtensionRoute route)
|
||||
void add(ExtensionRoute route)
|
||||
{
|
||||
if (route.extensionMethod == null)
|
||||
{
|
||||
@@ -152,24 +291,29 @@ public class AJExtender
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<ExtensionRoute> getAllNotRouted()
|
||||
Collection<ExtensionRoute> getAllNotRouted()
|
||||
{
|
||||
return notRoutedMethods.values();
|
||||
}
|
||||
|
||||
public int getExtendedMethodCount()
|
||||
int getExtendedMethodCount()
|
||||
{
|
||||
return routedMethods.size() + notRoutedMethods.size();
|
||||
}
|
||||
|
||||
public String getInfo()
|
||||
String getInfo()
|
||||
{
|
||||
return extensible.getName() + "{ " + routedMethods.size() + " routed methods; " + notRoutedMethods.size()
|
||||
+ " not routed methods;" + errors.size() + " errors}";
|
||||
}
|
||||
}
|
||||
|
||||
public static class ExtensionRoute
|
||||
/**
|
||||
* Encapsulates extended-method to extension-method mapping information.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
static class ExtensionRoute
|
||||
{
|
||||
final Extend extendAnnotation;
|
||||
|
||||
@@ -237,27 +381,48 @@ public class AJExtender
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean areAJPointsEnabled()
|
||||
/**
|
||||
* @return <code>true</code> if aspectJ routed extensions are enabled on the
|
||||
* call stack of the current thread
|
||||
*/
|
||||
static boolean areAJPointsEnabled()
|
||||
{
|
||||
return ajPointsLocalEnabled.get().peek();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes a new enabled state of the aspectJ routed extensions on the
|
||||
* current thread execution stack.
|
||||
*/
|
||||
static void enableAJPoints()
|
||||
{
|
||||
ajPointsLocalEnabled.get().push(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops the current aspectJ routed extensions enablement state from the
|
||||
* current thread execution stack.
|
||||
*/
|
||||
static void revertAJPoints()
|
||||
{
|
||||
ajPointsLocalEnabled.get().pop();
|
||||
}
|
||||
|
||||
public static <R> R throwableRun(AJExtender.ExtensionBypass<R> section) throws Throwable
|
||||
/**
|
||||
* Exception throwing extension-bypass closure runner method. <br>
|
||||
* Sets up adequate call contexts to avoid exception calling and than
|
||||
* delegates to the given closure.
|
||||
*
|
||||
* @param closure
|
||||
* @return
|
||||
* @throws Throwable
|
||||
*/
|
||||
static <R> R throwableRun(AJExtender.ExtensionBypass<R> closure) throws Throwable
|
||||
{
|
||||
try
|
||||
{
|
||||
AJExtender.ajPointsLocalEnabled.get().push(false);
|
||||
return section.run();
|
||||
return closure.run();
|
||||
|
||||
}
|
||||
finally
|
||||
@@ -266,11 +431,24 @@ public class AJExtender
|
||||
}
|
||||
}
|
||||
|
||||
public static <R> R run(AJExtender.ExtensionBypass<R> section, Class<?>[] exTypes) throws Throwable
|
||||
/**
|
||||
* Extension-bypass closure runner method. <br>
|
||||
* Sets up adequate call contexts to avoid exception calling and than
|
||||
* delegates to the given closure.<br>
|
||||
* Only the given exTypes exceptions will be passed on to the calling
|
||||
* context, all others will be wrapped as
|
||||
* {@link UndeclaredThrowableException}s.
|
||||
*
|
||||
* @param closure
|
||||
* @param exTypes
|
||||
* @return
|
||||
* @throws Throwable
|
||||
*/
|
||||
public static <R> R run(AJExtender.ExtensionBypass<R> closure, Class<?>[] exTypes) throws Throwable
|
||||
{
|
||||
try
|
||||
{
|
||||
return throwableRun(section);
|
||||
return throwableRun(closure);
|
||||
}
|
||||
catch (Error | RuntimeException error)
|
||||
{
|
||||
@@ -283,7 +461,7 @@ public class AJExtender
|
||||
}
|
||||
}
|
||||
|
||||
public static Throwable asCheckThrowable(Throwable error, Class<?>... checkedThrowableTypes)
|
||||
static Throwable asCheckThrowable(Throwable error, Class<?>... checkedThrowableTypes)
|
||||
{
|
||||
Class<? extends Throwable> errorClass = error.getClass();
|
||||
for (int i = 0; i < checkedThrowableTypes.length; i++)
|
||||
@@ -296,11 +474,19 @@ public class AJExtender
|
||||
return new UndeclaredThrowableException(error);
|
||||
}
|
||||
|
||||
public static <R> R run(AJExtender.ExtensionBypass<R> section)
|
||||
/**
|
||||
* Extension-bypass closure runner method. <br>
|
||||
* Sets up adequate call contexts to avoid exception calling and than
|
||||
* delegates to the given closure.
|
||||
*
|
||||
* @param closure
|
||||
* @return
|
||||
*/
|
||||
public static <R> R run(AJExtender.ExtensionBypass<R> closure)
|
||||
{
|
||||
try
|
||||
{
|
||||
return throwableRun(section);
|
||||
return throwableRun(closure);
|
||||
}
|
||||
catch (Error | RuntimeException error)
|
||||
{
|
||||
@@ -312,7 +498,13 @@ public class AJExtender
|
||||
}
|
||||
}
|
||||
|
||||
public static void oneTimeLiveLog(Log logger, ExtensionRoute route)
|
||||
/**
|
||||
* Logs each method routing path once per session.
|
||||
*
|
||||
* @param logger
|
||||
* @param route
|
||||
*/
|
||||
static void oneTimeLiveLog(Log logger, ExtensionRoute route)
|
||||
{
|
||||
synchronized (AJExtender.class)
|
||||
{
|
||||
@@ -336,8 +528,13 @@ public class AJExtender
|
||||
}
|
||||
}
|
||||
|
||||
public static CompiledExtensible compile(Class<? extends Extensible> extensible)
|
||||
throws AJExtensibleCompilingException
|
||||
/**
|
||||
* @param extensible
|
||||
* @return a compilation result containing all {@link Extend} mapped routes,
|
||||
* not routed or dangling methods within the give extensible class.
|
||||
* @throws AJExtensibleCompilingException
|
||||
*/
|
||||
static CompiledExtensible compile(Class<? extends Extensible> extensible) throws AJExtensibleCompilingException
|
||||
{
|
||||
logger.info("Compiling extensible " + extensible);
|
||||
|
||||
@@ -416,7 +613,18 @@ public class AJExtender
|
||||
return compiledExtensible;
|
||||
}
|
||||
|
||||
public static Object extendAroundAdvice(JoinPoint thisJoinPoint, Extensible extensible, Extend extendAnnotation,
|
||||
/**
|
||||
* Around advice helper that matches the advised method with its
|
||||
* corresponding extension method, sets up aspectJ call contexts (egg. the
|
||||
* local-proceed context) and delegates to the extension method.
|
||||
*
|
||||
* @param thisJoinPoint
|
||||
* @param extensible
|
||||
* @param extendAnnotation
|
||||
* @param extension
|
||||
* @return the result of the extended method
|
||||
*/
|
||||
static Object extendAroundAdvice(JoinPoint thisJoinPoint, Extensible extensible, Extend extendAnnotation,
|
||||
Object extension)
|
||||
{
|
||||
|
||||
@@ -479,7 +687,12 @@ public class AJExtender
|
||||
|
||||
}
|
||||
|
||||
public static boolean isLocalProceeder(Method method)
|
||||
/**
|
||||
* @param method
|
||||
* @return <code>true</code> if the given method has the same signature as
|
||||
* the currently aspectJ extension-overridden method
|
||||
*/
|
||||
static boolean isLocalProceeder(Method method)
|
||||
{
|
||||
if (!ajLocalProceedingJoinPoints.get().isEmpty())
|
||||
{
|
||||
@@ -495,7 +708,14 @@ public class AJExtender
|
||||
}
|
||||
}
|
||||
|
||||
public static Object localProceed(Object[] args) throws Throwable
|
||||
/**
|
||||
* Calls the currently overridden method in local-proceed context - proceeds
|
||||
* with the aspectJ join point saved on the current call stack.<br>
|
||||
*
|
||||
* @param args
|
||||
* @throws Throwable
|
||||
*/
|
||||
static Object localProceed(Object[] args) throws Throwable
|
||||
{
|
||||
ProceedingContext proceedingCotext = ajLocalProceedingJoinPoints.get().peek();
|
||||
Object[] safeArgs = args == null ? SAFE_NULL_ARGS : args;
|
||||
|
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2015 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
public interface AJExtensibleCompilingError
|
||||
{
|
||||
String getShortMessage();
|
||||
}
|
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2015 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
public class AJExtensibleCompilingException extends Exception implements AJExtensibleCompilingError
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public AJExtensibleCompilingException()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public AJExtensibleCompilingException(String message, Throwable cause, boolean enableSuppression,
|
||||
boolean writableStackTrace)
|
||||
{
|
||||
super(message,
|
||||
cause,
|
||||
enableSuppression,
|
||||
writableStackTrace);
|
||||
}
|
||||
|
||||
public AJExtensibleCompilingException(String message, Throwable cause)
|
||||
{
|
||||
super(message,
|
||||
cause);
|
||||
}
|
||||
|
||||
public AJExtensibleCompilingException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public AJExtensibleCompilingException(Throwable cause)
|
||||
{
|
||||
super(cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortMessage()
|
||||
{
|
||||
return getMessage();
|
||||
}
|
||||
|
||||
}
|
@@ -16,14 +16,28 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* A runtime retained annotation that marks AJ-trait-extended methods of
|
||||
* {@link Extensible} objects.<br>
|
||||
* It defines the actual circumstances in which the {@link ExtensionPoint}
|
||||
* defined using {@link #extensionAPI()} and {@link #traitAPI()} has its
|
||||
* extension invoked.<br>
|
||||
* Methods marked by this aspect are advised by an extension-routing around
|
||||
* advice in {@link RouteExtensions}. Consequently the call will be routed to a
|
||||
* method of an extension object having the same signature as the marked method.<br>
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Extend
|
||||
{
|
||||
Class<?> extensionAPI();
|
||||
|
||||
Class<? extends Trait> traitAPI();
|
||||
}
|
||||
|
@@ -16,10 +16,18 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Trait based extension reference holder.<br>
|
||||
* Keeps track of extension references for one extensible and allows the
|
||||
* collection of those extensions when the extensible is collected.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public class ExtendedTrait<T extends Trait>
|
||||
{
|
||||
private ConcurrentHashMap<Class<?>, Object> extensions = new ConcurrentHashMap<Class<?>, Object>();
|
||||
@@ -53,7 +61,8 @@ public class ExtendedTrait<T extends Trait>
|
||||
if (extension == null)
|
||||
{
|
||||
extension = factory.createExtension(trait);
|
||||
extensions.put(extensionAPI, extension);
|
||||
extensions.put(extensionAPI,
|
||||
extension);
|
||||
|
||||
}
|
||||
|
||||
|
@@ -16,22 +16,37 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Trait-extender central extension registry and life cycle handler.<br>
|
||||
* Implementors must handle:
|
||||
* <ol>
|
||||
* <li>
|
||||
* {@link ExtensionBundle} life cycle operations that start and stop bundles
|
||||
* of extension points implementations at runtime. <br>
|
||||
* See also: {@link Extender#start(ExtensionBundle)} ,
|
||||
* {@link Extender#stop(ExtensionBundle)} and {@link Extender#stopAll()} ).</li>
|
||||
* <li>The management of the extension point factory registry. At runtime
|
||||
* extension point factories can be registered or unregistered. The registered
|
||||
* factories will later be used for creating extensions of extensible-traits
|
||||
* (see {@link Extender#getExtension(Extensible, ExtensionPoint))}.<br>
|
||||
* See also:{@link #register(ExtensionPoint, ExtensionFactory)} and
|
||||
* {@link Extender#unregister(ExtensionPoint)}</li>
|
||||
* <li>The creation of extension for a given extensible trait. <br>
|
||||
* See: {@link Extender#getExtension(Extensible, ExtensionPoint)}</li>
|
||||
* </ol>
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public abstract class Extender
|
||||
{
|
||||
private static Extender instance;
|
||||
|
||||
public static class Configuration {
|
||||
private boolean enabled;
|
||||
private List<String> disbaledBundles;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return singleton {@link ExtenderImpl} instance
|
||||
*/
|
||||
public static synchronized Extender getInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
@@ -41,16 +56,72 @@ public abstract class Extender
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start life-cycle phase trigger method.<br>
|
||||
* Upon successful execution the bundle will have all its extension points
|
||||
* registered using {@link #register(ExtensionPoint, ExtensionFactory)} and
|
||||
* ready to be.
|
||||
*
|
||||
* @param bundle to be started
|
||||
*/
|
||||
public abstract void start(ExtensionBundle bundle);
|
||||
|
||||
/**
|
||||
* Start life-cycle phase trigger method.<br>
|
||||
* Upon successful execution the bundle will have all its extension points
|
||||
* unregistered using {@link #unregister(ExtensionPoint)}.
|
||||
*
|
||||
* @param bundle to be stopped
|
||||
*/
|
||||
public abstract void stop(ExtensionBundle bundle);
|
||||
|
||||
/**
|
||||
* Stops all previously registered {@link ExtensionBundle}s.
|
||||
*/
|
||||
public abstract void stopAll();
|
||||
|
||||
/**
|
||||
* Creates and returns a unique per {@link ExtensibleTrait} object or
|
||||
* <code>null</code> if no extension-point factory is registered for the
|
||||
* given {@link ExtensionPoint}.<br>
|
||||
* Given that {@link Extensible#getTrait(Class)} is used to obtain the
|
||||
* {@link ExtendedTrait} that the returned extension is uniquely associated
|
||||
* with, the uniqueness and garbage collection of the returned extension is
|
||||
* dependent on how the given {@link Extensible} handles its
|
||||
* {@link ExtendedTrait}s.
|
||||
*
|
||||
* @param anExtensible
|
||||
* @param point
|
||||
* @return a unique per {@link ExtensibleTrait} extension object or
|
||||
* <code>null</code> if no extension-point factory is registered for
|
||||
* the given {@link ExtensionPoint}
|
||||
*/
|
||||
public abstract <E, M extends Trait> E getExtension(Extensible anExtensible, ExtensionPoint<E, M> point);
|
||||
|
||||
/**
|
||||
* Registers an extension-point to factory association to be used in
|
||||
* extension creation. The presence of an association for a given extension
|
||||
* point guarantees that, when requested, a unique extension object per
|
||||
* {@link ExtensibleTrait} extension is returned by
|
||||
* {@link #getExtension(Extensible, ExtensionPoint)}.
|
||||
*
|
||||
* @param point the extension point to be associated with the given
|
||||
* extension factory during extension retrieval using
|
||||
* {@link Extender#getExtension(Extensible, ExtensionPoint)}
|
||||
* @param factory
|
||||
*/
|
||||
public abstract void register(ExtensionPoint<?, ?> point, ExtensionFactory<?> factory);
|
||||
|
||||
/**
|
||||
* Unregisters an extension-point to factory association of the given
|
||||
* extension point. The absence of an association for a given extension
|
||||
* point guarantees that, when requested, a null is returned by
|
||||
* {@link #getExtension(Extensible, ExtensionPoint)}.<br>
|
||||
* Unregistering extension points does not force the garbage collection of
|
||||
* the already created extensions.
|
||||
*
|
||||
* @param point
|
||||
*/
|
||||
public abstract void unregister(ExtensionPoint<?, ?> point);
|
||||
|
||||
}
|
||||
|
@@ -27,12 +27,15 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Standard-singleton {@link Extender} implementation.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public class ExtenderImpl extends Extender
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(Extender.class);
|
||||
|
||||
|
||||
|
||||
private List<ExtensionBundle> bundles = new LinkedList<ExtensionBundle>();
|
||||
|
||||
private Map<ExtensionPoint<?, ?>, ExtensionFactory<?>> pointFactories = new ConcurrentHashMap<ExtensionPoint<?, ?>, ExtensionFactory<?>>();
|
||||
|
@@ -16,9 +16,25 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
|
||||
/**
|
||||
* An {@link Extensible} object exposes a set of {@link Trait}s as
|
||||
* {@link ExtendedTrait}s objects.<br>
|
||||
* An {@link ExtendedTrait} is an association between a {@link Trait} exposing
|
||||
* object and several extension objects.<br>
|
||||
* The actual {@link Trait}s and associated extensions provided by an
|
||||
* {@link Extensible} object are given by its {@link ExtensionPoint} handling
|
||||
* strategy and by the current set of registered extensions (see
|
||||
* {@link Extender}).<br>
|
||||
* The exposed {@link Trait}s can be thought of as parts of an object's
|
||||
* interface that will be exposed to an extension. Upon the extension invocation
|
||||
* the given trait instances will be made available to their corresponding
|
||||
* extensions.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public interface Extensible
|
||||
{
|
||||
<T extends Trait> ExtendedTrait<T> getTrait(Class<? extends T> traitAPI);
|
||||
|
@@ -16,13 +16,30 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
|
||||
/**
|
||||
* Implementors are sets of extension implementations that are registered on
|
||||
* specific {@link ExtensionPoint} for given {@link Extender}s.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public interface ExtensionBundle
|
||||
{
|
||||
/**
|
||||
* Sets up an registers extension factories with the give {@link Extender}
|
||||
* for all extensions defined by this bundle.
|
||||
*
|
||||
* @param extender
|
||||
*/
|
||||
void start(Extender extender);
|
||||
|
||||
/**
|
||||
* Unregisters all defined extensions from the given {@link Extender} .
|
||||
*
|
||||
* @param extender
|
||||
*/
|
||||
void stop(Extender extender);
|
||||
|
||||
String getId();
|
||||
|
@@ -16,11 +16,27 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
/**
|
||||
* Creates extension instances for given {@link Trait}s and
|
||||
* {@link ExtensionPoint}s.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public interface ExtensionFactory<E>
|
||||
{
|
||||
<T extends Trait> E createExtension(T trait);
|
||||
|
||||
/**
|
||||
* @param point
|
||||
* @return <code>true</code> if the given extensio-point API elements are
|
||||
* compatible with the returned extension (i.e. the given extension
|
||||
* API is assignable form the type of the extension created by this
|
||||
* factory and the {@link Trait} accepted as aparameter in
|
||||
* {@link #createExtension(Trait)} is assignable from the type of
|
||||
* the given trait API).
|
||||
*/
|
||||
boolean canCreateExtensionFor(ExtensionPoint<?, ?> point);
|
||||
}
|
||||
|
@@ -16,8 +16,20 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
/**
|
||||
* Defines a two-way interfacing mechanism between a {@link Trait} exposing
|
||||
* object and an extension of that object.<br>
|
||||
* The extended object can call methods of the {@link #extensionAPI} which will
|
||||
* be able to interact with the extended object through the {@link #traitAPI}
|
||||
* interface it was paired with in the extension point. The actual circumstances
|
||||
* in which the extension methods are invoked are not defined by the extension
|
||||
* point.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public class ExtensionPoint<E, M extends Trait>
|
||||
{
|
||||
private Class<E> extensionAPI;
|
||||
@@ -53,8 +65,7 @@ public class ExtensionPoint<E, M extends Trait>
|
||||
if (obj instanceof ExtensionPoint)
|
||||
{
|
||||
ExtensionPoint<?, ?> pointObj = (ExtensionPoint<?, ?>) obj;
|
||||
return extensionAPI.equals(pointObj.extensionAPI)
|
||||
&& traitAPI.equals(pointObj.traitAPI);
|
||||
return extensionAPI.equals(pointObj.extensionAPI) && traitAPI.equals(pointObj.traitAPI);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -1,21 +0,0 @@
|
||||
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
public class ExtensionPointActivator
|
||||
{
|
||||
private ExtensionBundle bundle;
|
||||
|
||||
private ExtensionPoint<?, ?> extensionPoint;
|
||||
|
||||
private ExtensionFactory<?> extensionFactory;
|
||||
|
||||
public <E> ExtensionPointActivator(ExtensionBundle bundle, ExtensionPoint<E, ?> extensionPoint,
|
||||
ExtensionFactory<E> extensionFactory)
|
||||
{
|
||||
super();
|
||||
this.bundle = bundle;
|
||||
this.extensionPoint = extensionPoint;
|
||||
this.extensionFactory = extensionFactory;
|
||||
}
|
||||
|
||||
}
|
@@ -16,8 +16,14 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
/**
|
||||
* Trait-extension runtime target-exception wrapper.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public class ExtensionTargetException extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = -502697833178766952L;
|
||||
@@ -30,12 +36,16 @@ public class ExtensionTargetException extends RuntimeException
|
||||
public ExtensionTargetException(String message, Throwable cause, boolean enableSuppression,
|
||||
boolean writableStackTrace)
|
||||
{
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
super(message,
|
||||
cause,
|
||||
enableSuppression,
|
||||
writableStackTrace);
|
||||
}
|
||||
|
||||
public ExtensionTargetException(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
super(message,
|
||||
cause);
|
||||
}
|
||||
|
||||
public ExtensionTargetException(String message)
|
||||
|
@@ -19,6 +19,12 @@
|
||||
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
/**
|
||||
* Sub classes are extension API implementors that get instantiated once per
|
||||
* extensible-extension point definition.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public abstract class InstanceExtension<E, T extends Trait>
|
||||
{
|
||||
protected T trait;
|
||||
|
@@ -21,6 +21,12 @@ package org.alfresco.traitextender;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
/**
|
||||
* Creates extension sub classes that are extension API implementors once per
|
||||
* extensible-extension point definition.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public class InstanceExtensionFactory<I extends InstanceExtension<E, T>, T extends Trait, E> implements
|
||||
ExtensionFactory<E>
|
||||
{
|
||||
@@ -48,7 +54,8 @@ public class InstanceExtensionFactory<I extends InstanceExtension<E, T>, T exten
|
||||
{
|
||||
try
|
||||
{
|
||||
// Trait RTTI will be performed anyway at Constructor#newInstance invocation time
|
||||
// Trait RTTI will be performed anyway at Constructor#newInstance
|
||||
// invocation time
|
||||
T tTrait = (T) traitObject;
|
||||
|
||||
Constructor<? extends I> c = extensionClass.getConstructor(traitAPI);
|
||||
|
@@ -16,8 +16,14 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
/**
|
||||
* Signals an invalid extension state or extension definition.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public class InvalidExtension extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = -7146808120353555462L;
|
||||
@@ -29,12 +35,16 @@ public class InvalidExtension extends RuntimeException
|
||||
|
||||
public InvalidExtension(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace)
|
||||
{
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
super(message,
|
||||
cause,
|
||||
enableSuppression,
|
||||
writableStackTrace);
|
||||
}
|
||||
|
||||
public InvalidExtension(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
super(message,
|
||||
cause);
|
||||
}
|
||||
|
||||
public InvalidExtension(String message)
|
||||
|
@@ -16,6 +16,7 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
@@ -28,13 +29,29 @@ import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
|
||||
/**
|
||||
* An method override extension routing aspect.<br>
|
||||
* Overrides calls to methods marked by an {@link Extend} annotation with calls
|
||||
* to methods having the same signature in extensions registered for the
|
||||
* {@link ExtensionPoint} referred by the {@link Extend} method annotation.<br>
|
||||
* Overriding methods can call the overridden method using its correspondent
|
||||
* {@link Trait} representation (i.e. a method having the same signature).<br>
|
||||
* If no extension is defined the call proceeds with the original method.<br>
|
||||
* The aspect uses the {@link AJExtender} static utility to for extension
|
||||
* invocation and for maintaining thread-local extension-bypass contexts as not all
|
||||
* calls must be overridden and calls from within the extension must be aware of
|
||||
* this context (see {@link AJProxyTrait}).
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
@Aspect
|
||||
public class RouteExtensions
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(RouteExtensions.class);
|
||||
|
||||
@Around("execution(@org.alfresco.traitextender.Extend * *(..)) && (@annotation(extendAnnotation))")
|
||||
public Object intercept(ProceedingJoinPoint pjp, Extend extendAnnotation) throws Throwable {
|
||||
public Object intercept(ProceedingJoinPoint pjp, Extend extendAnnotation) throws Throwable
|
||||
{
|
||||
boolean ajPointsEnabled = AJExtender.areAJPointsEnabled();
|
||||
try
|
||||
{
|
||||
|
@@ -19,6 +19,15 @@
|
||||
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
/**
|
||||
* A singleton extension API implementor. The singleton extension continues to
|
||||
* exist after the extensible has been collected. The instance of this extension
|
||||
* is shared among {@link Extensible}s defining extension-points that this
|
||||
* extension is bound to.The {@link Trait} it requires is set at call-time on
|
||||
* the local thread.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public abstract class SingletonExtension<E, T extends Trait>
|
||||
{
|
||||
private ThreadLocal<T> localTrait = new ThreadLocal<>();
|
||||
@@ -46,6 +55,10 @@ public abstract class SingletonExtension<E, T extends Trait>
|
||||
localTrait.set(trait);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link Trait} instance of the current execution extension
|
||||
* call.
|
||||
*/
|
||||
protected T getTrait()
|
||||
{
|
||||
return localTrait.get();
|
||||
|
@@ -27,6 +27,13 @@ import java.lang.reflect.Proxy;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Creates singleton extension sub classes that are extension API implementors.
|
||||
* The singleton extensions continue to exist after the extensible has been
|
||||
* collected.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public class SingletonExtensionFactory<E, S extends SingletonExtension<E, T>, T extends Trait> implements
|
||||
ExtensionFactory<E>
|
||||
{
|
||||
|
@@ -16,8 +16,16 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
/**
|
||||
* A {@link SingletonExtension} extension-API implementor defined as a
|
||||
* spring-bean.<br>
|
||||
* Handles also spring-bundle extension registrations.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public abstract class SpringBeanExtension<E, T extends Trait> extends SingletonExtension<E, T>
|
||||
{
|
||||
private SpringExtensionPoint extensionPoint;
|
||||
@@ -34,6 +42,7 @@ public abstract class SpringBeanExtension<E,T extends Trait> extends SingletonEx
|
||||
|
||||
public void register(RegistryExtensionBundle bundle) throws InvalidExtension
|
||||
{
|
||||
extensionPoint.register(bundle,this);
|
||||
extensionPoint.register(bundle,
|
||||
this);
|
||||
}
|
||||
}
|
||||
|
@@ -26,6 +26,51 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* A {@link SpringBeanExtension}s collection that get registered on the
|
||||
* {@link Extender}'s registry on {@link #afterPropertiesSet()}.<br>
|
||||
* Works in conjunction with {@link SpringBeanExtension}s and
|
||||
* {@link SpringExtensionPoint}s to define and start spring based
|
||||
* {@link ExtensionBundle}s of {@link SingletonExtension}s.<br>
|
||||
* The spring-context XML sample bellow shows the definition of spring-bundled
|
||||
* trait-extensions:
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
*
|
||||
* <bean id="ep1" class="org.alfresco.traitextender.SpringExtensionPoint">
|
||||
* <property name="extension" value="org.alfresco.sample.Extension1" />
|
||||
* <property name="trait" value="org.alfresco.sample.Trait1" />
|
||||
* </bean>
|
||||
*
|
||||
* <bean id="ep2" class="org.alfresco.traitextender.SpringExtensionPoint">
|
||||
* <property name="extension" value="org.alfresco.sample.Extension2" />
|
||||
* <property name="trait" value="org.alfresco.sample.Trait2" />
|
||||
* </bean>
|
||||
*
|
||||
* <bean id="extension1" class="org.alfresco.sample.Extension1">
|
||||
* <property name="extensionPoint" ref="ep1" />
|
||||
* </bean>
|
||||
*
|
||||
* <bean id="extension2" class="org.alfresco.sample.Extension2">
|
||||
* <property name="extensionPoint" ref="ep2" />
|
||||
* </bean>
|
||||
*
|
||||
* <bean id="aBundle" class="org.alfresco.traitextender.SpringExtensionBundle">
|
||||
* <property name="id" value="org.alfresco.sample.aBundle" />
|
||||
* <property name="enabled" value="true" />
|
||||
* <property name="extensions">
|
||||
* <list>
|
||||
* <ref bean="extension1" />
|
||||
* <ref bean="extension2" />
|
||||
* </list >
|
||||
* </property>
|
||||
* </bean>
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public class SpringExtensionBundle implements InitializingBean
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(SpringExtensionBundle.class);
|
||||
@@ -38,6 +83,12 @@ public class SpringExtensionBundle implements InitializingBean
|
||||
|
||||
private RegistryExtensionBundle extensionBundle;
|
||||
|
||||
/**
|
||||
* @param enabled <code>true</code> if the current bundle should be
|
||||
* registered.<br>
|
||||
* <code>false</code> if the current bundle should skip extension
|
||||
* registration
|
||||
*/
|
||||
public void setEnabled(boolean enabled)
|
||||
{
|
||||
this.enabled = enabled;
|
||||
@@ -53,6 +104,17 @@ public class SpringExtensionBundle implements InitializingBean
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link RegistryExtensionBundle} and registers all contained
|
||||
* {@link SpringBeanExtension}s with it.<br>
|
||||
* When all extension have successfully registered it starts the
|
||||
* {@link RegistryExtensionBundle}.<br>
|
||||
* The previously created {@link RegistryExtensionBundle} is stored for
|
||||
* later start or {@link #stop()} operations.
|
||||
*
|
||||
* @see Extender#start(ExtensionBundle)
|
||||
* @see Extender#stop(ExtensionBundle)
|
||||
*/
|
||||
public synchronized void start()
|
||||
{
|
||||
|
||||
@@ -81,6 +143,13 @@ public class SpringExtensionBundle implements InitializingBean
|
||||
Extender.getInstance().start(extensionBundle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops a previously {@link #start()} created
|
||||
* {@link RegistryExtensionBundle}.
|
||||
*
|
||||
* @see Extender#start(ExtensionBundle)
|
||||
* @see Extender#stop(ExtensionBundle)
|
||||
*/
|
||||
public synchronized void stop()
|
||||
{
|
||||
if (extensionBundle == null)
|
||||
|
@@ -19,6 +19,15 @@
|
||||
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
/**
|
||||
* An {@link ExtensionPoint} spring bean wrapper with spring registering
|
||||
* life-cycle management.<br>
|
||||
* Works in conjunction with {@link SpringBeanExtension}s and
|
||||
* {@link SpringExtensionBundle}s to define spring based {@link ExtensionBundle}
|
||||
* s of singleton extensions.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public class SpringExtensionPoint
|
||||
{
|
||||
private String trait;
|
||||
|
@@ -1,15 +0,0 @@
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
public class SpringTraitExtenderConfigurator implements InitializingBean
|
||||
{
|
||||
|
||||
private boolean enableTraitExtender;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
}
|
@@ -16,8 +16,18 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package org.alfresco.traitextender;
|
||||
|
||||
/**
|
||||
* Markup interface.<br>
|
||||
* Subinterfaces represent distiguishing features of {@link Extensible} objects
|
||||
* that are meant to be extended and exposed to the extending code.<br>
|
||||
* Ideally they would be the only means of interaction between extensions and
|
||||
* the extended modules.
|
||||
*
|
||||
* @author Bogdan Horje
|
||||
*/
|
||||
public interface Trait
|
||||
{
|
||||
|
||||
|
@@ -32,14 +32,14 @@ import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
|
||||
public class AJExtensionsCompileTest extends TestCase
|
||||
{
|
||||
protected void compile(Class<? extends Extensible> extensible) throws AJExtensibleCompilingException
|
||||
protected void compile(Class<? extends Extensible> extensible) throws Exception
|
||||
{
|
||||
Set<Class<? extends Extensible>> extensiblesSet = new HashSet<>();
|
||||
extensiblesSet.add(extensible);
|
||||
compile(extensiblesSet);
|
||||
}
|
||||
|
||||
protected void compile(Set<Class<? extends Extensible>> extensibles) throws AJExtensibleCompilingException
|
||||
protected void compile(Set<Class<? extends Extensible>> extensibles) throws Exception
|
||||
{
|
||||
StringBuilder errorString = new StringBuilder();
|
||||
boolean errorsFound = false;
|
||||
|
Reference in New Issue
Block a user