16 May
2010
16 May
'10
1:25 p.m.
----- "Thomas Mortagne" <thomas.mortagne@xwiki.com> wrote:
> On Sat, May 15, 2010 at 17:08, jvelociter
> <contrib-notifications@xwiki.org> wrote:
> >
> > Author: jvelociter
> > Date: 2010-05-15 17:08:25 +0200 (Sat, 15 May 2010)
> > New Revision: 28878
> >
> > Added:
> > contrib/sandbox/xwiki-wiki-components/
> > contrib/sandbox/xwiki-wiki-components/pom.xml
> > contrib/sandbox/xwiki-wiki-components/src/
> > contrib/sandbox/xwiki-wiki-components/src/main/
> > contrib/sandbox/xwiki-wiki-components/src/main/java/
> > contrib/sandbox/xwiki-wiki-components/src/main/java/com/
> > contrib/sandbox/xwiki-wiki-components/src/main/java/com/xpn/
> > contrib/sandbox/xwiki-wiki-components/src/main/java/com/xpn/xwiki/
> >
> contrib/sandbox/xwiki-wiki-components/src/main/java/com/xpn/xwiki/internal/
> >
> contrib/sandbox/xwiki-wiki-components/src/main/java/com/xpn/xwiki/internal/DefaultWikiComponentBuilder.java
> >
> contrib/sandbox/xwiki-wiki-components/src/main/java/com/xpn/xwiki/internal/WikiComponentInitializer.java
> > contrib/sandbox/xwiki-wiki-components/src/main/java/org/
> > contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/
> >
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/
> >
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/
> >
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/InvalidComponentDefinitionException.java
> >
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/MethodOutputHandler.java
> >
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponent.java
> >
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponentBuilder.java
> >
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponentException.java
> >
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponentInvocationHandler.java
> >
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponentManager.java
> >
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/internal/
> >
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/internal/DefaultMethodOutputHandler.java
> >
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/internal/DefaultWikiComponent.java
> >
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/internal/DefaultWikiComponentManager.java
> > contrib/sandbox/xwiki-wiki-components/src/main/resources/
> > contrib/sandbox/xwiki-wiki-components/src/main/resources/META-INF/
> >
> contrib/sandbox/xwiki-wiki-components/src/main/resources/META-INF/components.txt
> > contrib/sandbox/xwiki-wiki-components/src/test/
> > contrib/sandbox/xwiki-wiki-components/src/test/java/
> > contrib/sandbox/xwiki-wiki-components/src/test/java/org/
> > contrib/sandbox/xwiki-wiki-components/src/test/java/org/xwiki/
> >
> contrib/sandbox/xwiki-wiki-components/src/test/java/org/xwiki/component/
> >
> contrib/sandbox/xwiki-wiki-components/src/test/java/org/xwiki/component/wiki/
> >
> contrib/sandbox/xwiki-wiki-components/src/test/java/org/xwiki/component/wiki/WikiComponentManagerTest.java
> > Log:
> > XWIKI-5195 Make possible to implement any component from the wiki,
> using objects
> >
> > Proposal implementation, for review. Right now supports definition
> of component implementation as wiki objects, with support for multiple
> interfaces implementations and methods return value via explicit call
> or plain block rendering if no explicit call and return type is
> String.
> >
> > Missing :
> > - More tests
> > - Support for requirements bindings
> > - Support for inputs handling (method arguments bindings)
> >
> > Open questions I can think of :
> > - Should we refuse to register a component if it does not declare
> implementation of all its role methods ? (to avoid potential NPEs, for
> example)
>
> Why NPE ? The proxy is supposed to generate a proper exception when
> something is calling unimplemented method.
Right. It's actually doing so already (throwing NoSuchMethodException).
I think the question still holds, though. We could decide to enforce compliance to the interface in order to allow a component to be registered (would reduce collateral damage for components relying on that role - like the OM interacting with an EventListener not declaring onEvent)
>
> > - Better name for XWiki.ComponentInterfaceClass ? (It's the class
> representing an extra interface the component implementation
> implements)=
> >
> > Note: module right now relies on XWIKI-5194 (bridge event for XWiki
> initialized) being applied to xwiki-core/xwiki-bridge
> >
> >
>
> [...]
>
> >
> > Added:
> contrib/sandbox/xwiki-wiki-components/src/main/java/com/xpn/xwiki/internal/DefaultWikiComponentBuilder.java
> > ===================================================================
> > ---
> contrib/sandbox/xwiki-wiki-components/src/main/java/com/xpn/xwiki/internal/DefaultWikiComponentBuilder.java
> (rev 0)
> > +++
> contrib/sandbox/xwiki-wiki-components/src/main/java/com/xpn/xwiki/internal/DefaultWikiComponentBuilder.java
> 2010-05-15 15:08:25 UTC (rev 28878)
> > @@ -0,0 +1,167 @@
>
> [...]
>
> > +/**
> > + * Default implementation of a wiki component builder, that is
> using the legacy XWiki core module.
> > + *
> > + * @since 2.4-M2
> > + * @version $Id$
> > + */
> > +@Component
> > +public class DefaultWikiComponentBuilder implements
> WikiComponentBuilder
> > +{
> > +
> > + /**
> > + * The name of the document that holds the XClass definition of
> an implementation of an interface by a component.
> > + */
> > + private static final String XWIKI_COMPONENT_INTERFACE_CLASS =
> "XWiki.ComponentInterfaceClass";
> > +
> > + /**
> > + * The name of the document that holds the XClass definition of
> a method of a component.
> > + */
> > + private static final String XWIKI_COMPONENT_METHOD_CLASS =
> "XWiki.ComponentMethodClass";
> > +
> > + /**
> > + * The property name of the name of a component method.
> > + */
> > + private static final String COMPONENT_METHOD_NAME_FIELD =
> "name";
> > +
> > + /**
> > + * The property name of the name of an implemented interface.
> (Checkstyle fix).
> > + */
> > + private static final String COMPONENT_INTERFACE_NAME_FIELD =
> COMPONENT_METHOD_NAME_FIELD;
> > +
> > + /**
> > + * Execution, needed to access the XWiki context map.
> > + */
> > + @Requirement
> > + private Execution execution;
> > +
> > + /**
> > + * {@inheritDoc}
> > + */
> > + public WikiComponent build(DocumentReference reference) throws
> InvalidComponentDefinitionException,
> > + WikiComponentException
> > + {
> > + try {
> > + XWikiDocument componentDocument =
> getXWikiContext().getWiki().getDocument(reference, getXWikiContext());
> > + BaseObject componentObject =
> componentDocument.getObject("XWiki.ComponentClass");
> > +
> > + if (componentObject == null) {
> > + throw new InvalidComponentDefinitionException("No
> component object could be found");
> > + }
> > +
> > + String role = componentObject.getStringValue("role");
> > +
> > + if (StringUtils.isBlank(role)) {
> > + throw new InvalidComponentDefinitionException("No
> role were precised in the component");
> > + }
> > +
> > + Class< ? > roleAsClass;
> > + try {
> > + roleAsClass = Class.forName(role);
> > + } catch (ClassNotFoundException e) {
> > + throw new InvalidComponentDefinitionException("The
> role class could not be found", e);
> > + }
> > +
> > + String roleHint =
> StringUtils.defaultIfEmpty(componentObject.getStringValue("roleHint"),
> "default");
> > +
> > + DefaultWikiComponent component = new
> DefaultWikiComponent(reference, roleAsClass, roleHint);
> > +
> component.setHandledMethods(this.getHandledMethods(componentDocument));
> > +
> component.setImplementedInterfaces(this.getDeclaredInterfaces(componentDocument));
> > +
> > + return component;
> > +
> > + } catch (XWikiException e) {
> > + throw new WikiComponentException("Failed to build wiki
> component for document " + reference.toString());
> > + }
> > + }
> > +
> > + /**
> > + * @param componentDocument the document holding the component
> description
> > + * @return the map of component handled methods/method body
> > + */
> > + private Map<String, String> getHandledMethods(XWikiDocument
> componentDocument)
> > + {
> > + Map<String, String> handledMethods = new HashMap<String,
> String>();
> > + if
> (componentDocument.getObjectNumbers(XWIKI_COMPONENT_METHOD_CLASS) > 0)
> {
> > + for (BaseObject iface :
> componentDocument.getObjects(XWIKI_COMPONENT_METHOD_CLASS)) {
> > + if
> (!StringUtils.isBlank(iface.getStringValue(COMPONENT_METHOD_NAME_FIELD)))
> {
> > +
> handledMethods.put(iface.getStringValue(COMPONENT_METHOD_NAME_FIELD),
> iface.getStringValue("code"));
> > + }
> > + }
> > + }
> > + return handledMethods;
> > +
> > + }
> > +
> > + /**
> > + * @param componentDocument the document holding the component
> description
> > + * @return the array of interfaces declared (and actually
> existing) by the document
> > + */
> > + private Class< ? >[] getDeclaredInterfaces(XWikiDocument
> componentDocument)
> > + {
> > + List<Class< ? >> interfaces = new ArrayList<Class< ? >>();
> > + if
> (componentDocument.getObjectNumbers(XWIKI_COMPONENT_INTERFACE_CLASS) >
> 0) {
> > + for (BaseObject iface :
> componentDocument.getObjects(XWIKI_COMPONENT_INTERFACE_CLASS)) {
> > + if
> (!StringUtils.isBlank(iface.getStringValue(COMPONENT_INTERFACE_NAME_FIELD)))
> {
> > + try {
> > + Class< ? > implemented =
> Class.forName(iface.getStringValue(COMPONENT_INTERFACE_NAME_FIELD));
> > + interfaces.add(implemented);
> > + } catch (ClassNotFoundException e) {
> > + // Silent
> > + }
> > + }
> > + }
> > + }
> > + return interfaces.toArray(new Class< ? >[] {});
> > + }
> > +
> > + /**
> > + * @return a XWikiContext, retrieved from our execution
> > + */
> > + private XWikiContext getXWikiContext()
> > + {
> > + return (XWikiContext)
> execution.getContext().getProperty("xwikicontext");
> > + }
> > +
> > +}
> >
> > Added:
> contrib/sandbox/xwiki-wiki-components/src/main/java/com/xpn/xwiki/internal/WikiComponentInitializer.java
> > ===================================================================
> > ---
> contrib/sandbox/xwiki-wiki-components/src/main/java/com/xpn/xwiki/internal/WikiComponentInitializer.java
> (rev 0)
> > +++
> contrib/sandbox/xwiki-wiki-components/src/main/java/com/xpn/xwiki/internal/WikiComponentInitializer.java
> 2010-05-15 15:08:25 UTC (rev 28878)
> > @@ -0,0 +1,339 @@
>
> [...]
>
> > +/**
> > + * Initializes the Wiki Component feature. First ensure all needed
> XClasses are up-to-date, then registers existing
> > + * components.
> > + *
> > + * @since 2.4-M2
> > + * @version $Id$
> > + */
> > +@Component("wikiComponentInitializer")
> > +public class WikiComponentInitializer extends AbstractLogEnabled
> implements EventListener
> > +{
> > + /**
> > + * The XClass defining a component implementation.
> > + */
> > + private static final String WIKI_COMPONENT_CLASS =
> "XWiki.ComponentClass";
> > +
> > + /**
> > + * The XClass defining a component requirement.
> > + */
> > + private static final String WIKI_COMPONENT_REQUIREMENT_CLASS =
> "XWiki.ComponentRequirementClass";
> > +
> > + /**
> > + * The XClass defining a component method.
> > + */
> > + private static final String WIKI_COMPONENT_METHOD_CLASS =
> "XWiki.ComponentMethodClass";
> > +
> > + /**
> > + * The XClass defining a component interface implementation.
> > + */
> > + private static final String WIKI_COMPONENT_INTERFACE_CLASS =
> "XWiki.ComponentInterfaceClass";
> > +
> > + /**
> > + * The name property of the {@link
> WIKI_COMPONENT_INTERFACE_CLASS} XClass.
> > + */
> > + private static final String INTERFACE_NAME_FIELD = "name";
> > +
> > + /**
> > + * The name property of the {@link WIKI_COMPONENT_METHOD_CLASS}
> XClass. (Fix checkstyle).
> > + */
> > + private static final String METHOD_NAME_FIELD =
> INTERFACE_NAME_FIELD;
> > +
> > + /**
> > + * The role property of both {@link WIKI_COMPONENT_CLASS} and
> {@link WIKI_COMPONENT_REQUIREMENT_CLASS}.
> > + */
> > + private static final String COMPONENT_ROLE_HINT_FIELD =
> "roleHint";
> > +
> > + /**
> > + * The role hint property of both {@link WIKI_COMPONENT_CLASS}
> and {@link WIKI_COMPONENT_REQUIREMENT_CLASS}.
> > + */
> > + private static final String COMPONENT_ROLE_FIELD = "role";
> > +
> > + /**
> > + * Our execution. Needed to access the XWiki context.
> > + */
> > + @Requirement
> > + private Execution execution;
> > +
> > + /**
> > + * The wiki component manager that knows how to register
> component definition against the underlying CM.
> > + */
> > + @Requirement
> > + private WikiComponentManager wikiComponentManager;
> > +
> > + /**
> > + * Builder that creates component description from document
> references.
> > + */
> > + @Requirement
> > + private WikiComponentBuilder wikiComponentBuilder;
> > +
> > + /**
> > + * {@inheritDoc}
> > + */
> > + public List<Event> getEvents()
> > + {
> > + return Arrays.<Event> asList(new
> XWikiInitializedBridgeEvent());
> > + }
> > +
> > + /**
> > + * {@inheritDoc}
> > + */
> > + public String getName()
> > + {
> > + return "wikiComponentInitializer";
> > + }
> > +
> > + /**
> > + * {@inheritDoc}
> > + */
> > + public void onEvent(Event arg0, Object arg1, Object arg2)
> > + {
> > + // First step, verify that all XClasses exists and are
> up-to-date (act if not).
> > + this.installOrUpdateComponentXClasses();
> > + // Second step, lookup and register existing components.
> > + this.registerExistingWikiComponents();
> > + }
> > +
> > + /**
> > + * Registers existing components. Query them against the store,
> and if they are built properly (valid definition)
> > + * register them against the CM.
> > + */
> > + private void registerExistingWikiComponents()
> > + {
> > + String query =
> > + ", BaseObject as obj, StringProperty as role where
> obj.className='XWiki.ComponentClass'"
> > + + " and obj.name=doc.fullName and role.id.id=obj.id
> and role.id.name='role' and role.value <>''";
> > + try {
> > + for (DocumentReference ref :
> getXWikiContext().getWiki().getStore().searchDocumentReferences(query,
> > + getXWikiContext())) {
> > + try {
> > + WikiComponent component =
> this.wikiComponentBuilder.build(ref);
> > +
> > +
> this.wikiComponentManager.registerWikiComponent(component);
> > + } catch (InvalidComponentDefinitionException e) {
> > + // Fail quietly and only log at the debug
> level.
> > + getLogger().debug("Invalid wiki component
> definition for reference " + ref.toString(), e);
> > + } catch (WikiComponentException e) {
> > + // Fail quietly and only log at the debug
> level.
> > + getLogger().debug("Failed to register wiki
> component for reference " + ref.toString(), e);
> > + }
> > + }
> > + } catch (XWikiException e) {
> > + getLogger().error("Failed to register existing wiki
> components", e);
> > + }
> > +
> > + }
> > +
> > + /**
> > + * Verify that all XClasses exists and are up-to-date (act if
> not).
> > + */
> > + private void installOrUpdateComponentXClasses()
> > + {
> > + try {
> > + this.installOrUpdateComponentXClass();
> > + this.installOrUpdateComponentRequirementXClass();
> > + this.installOrUpdateComponentMethodXClass();
> > + this.installOrUpdateComponentInterfaceXClass();
> > + } catch (XWikiException e) {
> > + getLogger().error("Failed to install or update wiki
> component XClasses", e);
> > + }
> > + }
> > +
> > + /**
> > + * Verify that the {@link #WIKI_COMPONENT_INTERFACE_CLASS}
> exists and is up-to-date (act if not).
> > + *
> > + * @throws XWikiException on failure
> > + */
> > + private void installOrUpdateComponentInterfaceXClass() throws
> XWikiException
> > + {
> > + XWikiContext xcontext = getXWikiContext();
> > + XWikiDocument doc =
> xcontext.getWiki().getDocument(WIKI_COMPONENT_INTERFACE_CLASS,
> xcontext);
> > +
> > + BaseClass bclass = doc.getXClass();
> > + bclass.setName(WIKI_COMPONENT_INTERFACE_CLASS);
> > +
> > + boolean needsUpdate = false;
> > +
> > + needsUpdate |= this.initializeXClassDocumentMetadata(doc,
> "Wiki Component Implements Interface XWiki Class");
> > + needsUpdate |= bclass.addTextField(INTERFACE_NAME_FIELD,
> "Interface Qualified Name", 30);
> > +
> > + if (needsUpdate) {
> > + this.update(doc);
> > + }
> > + }
> > +
> > + /**
> > + * Verify that the {@link #WIKI_COMPONENT_CLASS} exists and is
> up-to-date (act if not).
> > + *
> > + * @throws XWikiException on failure
> > + */
> > + private void installOrUpdateComponentXClass() throws
> XWikiException
> > + {
> > + XWikiContext xcontext = getXWikiContext();
> > + XWikiDocument doc =
> xcontext.getWiki().getDocument(WIKI_COMPONENT_CLASS, xcontext);
> > +
> > + BaseClass bclass = doc.getXClass();
> > + bclass.setName(WIKI_COMPONENT_CLASS);
> > +
> > + boolean needsUpdate = false;
> > +
> > + needsUpdate |= this.initializeXClassDocumentMetadata(doc,
> "Wiki Component XWiki Class");
> > + needsUpdate |= bclass.addTextField(COMPONENT_ROLE_FIELD,
> "Component role", 30);
> > + needsUpdate |=
> bclass.addTextField(COMPONENT_ROLE_HINT_FIELD, "Component role hint",
> 30);
> > +
> > + if (needsUpdate) {
> > + this.update(doc);
> > + }
> > + }
> > +
> > + /**
> > + * Verify that the {@link #WIKI_COMPONENT_REQUIREMENT_CLASS}
> exists and is up-to-date (act if not).
> > + *
> > + * @throws XWikiException on failure
> > + */
> > + private void installOrUpdateComponentRequirementXClass() throws
> XWikiException
> > + {
> > + XWikiContext xcontext = getXWikiContext();
> > + XWikiDocument doc =
> xcontext.getWiki().getDocument(WIKI_COMPONENT_REQUIREMENT_CLASS,
> xcontext);
> > +
> > + BaseClass bclass = doc.getXClass();
> > + bclass.setName(WIKI_COMPONENT_REQUIREMENT_CLASS);
> > +
> > + boolean needsUpdate = false;
> > +
> > + needsUpdate |= this.initializeXClassDocumentMetadata(doc,
> "Wiki Component Requirement XWiki Class");
> > + needsUpdate |= bclass.addTextField(COMPONENT_ROLE_FIELD,
> "Requirement role", 30);
> > + needsUpdate |=
> bclass.addTextField(COMPONENT_ROLE_HINT_FIELD, "Requirement role
> hint", 30);
> > + needsUpdate |= bclass.addTextField("bindingName", "Binding
> name", 30);
> > + needsUpdate |= bclass.addStaticListField("type",
> "Requirement type", "single=Single|list=List|map=Map");
> > +
> > + if (needsUpdate) {
> > + this.update(doc);
> > + }
> > + }
> > +
> > + /**
> > + * Verify that the {@link #WIKI_COMPONENT_METHOD_CLASS} exists
> and is up-to-date (act if not).
> > + *
> > + * @throws XWikiException on failure
> > + */
> > + private void installOrUpdateComponentMethodXClass() throws
> XWikiException
> > + {
> > + XWikiContext xcontext = getXWikiContext();
> > + XWikiDocument doc =
> xcontext.getWiki().getDocument(WIKI_COMPONENT_METHOD_CLASS, xcontext);
> > +
> > + BaseClass bclass = doc.getXClass();
> > + bclass.setName(WIKI_COMPONENT_METHOD_CLASS);
> > +
> > + boolean needsUpdate = false;
> > +
> > + needsUpdate |= this.initializeXClassDocumentMetadata(doc,
> "Wiki Component Method XWiki Class");
> > + needsUpdate |= bclass.addTextField(METHOD_NAME_FIELD,
> "Method name", 30);
> > + needsUpdate |= bclass.addTextAreaField("code", "Method body
> code", 40, 20);
> > +
> > + if (needsUpdate) {
> > + this.update(doc);
> > + }
> > + }
> > +
> > + /**
> > + * Utility method for updating a wiki macro class definition
> document.
> > + *
> > + * @param doc xwiki document containing the wiki macro class.
> > + * @throws XWikiException if an error occurs while saving the
> document.
> > + */
> > + private void update(XWikiDocument doc) throws XWikiException
> > + {
> > + XWikiContext xcontext = getXWikiContext();
> > + xcontext.getWiki().saveDocument(doc, xcontext);
> > + }
> > +
> > + /**
> > + * Helper method to prepare a document that will hold an XClass
> definition, setting its initial metadata, if needed
> > + * (author, title, parent, content, etc.).
> > + *
> > + * @param doc the document to prepare
> > + * @param title the title to set
> > + * @return true if the doc has been modified and needs saving,
> false otherwise
> > + */
> > + private boolean initializeXClassDocumentMetadata(XWikiDocument
> doc, String title)
> > + {
> > + boolean needsUpdate = false;
> > +
> > + if (StringUtils.isBlank(doc.getCreator())) {
> > + needsUpdate = true;
> > + doc.setCreator(XWikiRightService.SUPERADMIN_USER);
> > + }
> > + if (StringUtils.isBlank(doc.getAuthor())) {
> > + needsUpdate = true;
> > + doc.setAuthor(doc.getCreator());
> > + }
> > + if (StringUtils.isBlank(doc.getParent())) {
> > + needsUpdate = true;
> > + doc.setParent("XWiki.XWikiClasses");
> > + }
> > + if (StringUtils.isBlank(doc.getTitle())) {
> > + needsUpdate = true;
> > + doc.setTitle(title);
> > + }
> > + if (StringUtils.isBlank(doc.getContent()) ||
> !XWikiDocument.XWIKI20_SYNTAXID.equals(doc.getSyntaxId())) {
> > + needsUpdate = true;
> > + doc.setContent("{{include document=\"XWiki.ClassSheet\"
> /}}");
> > + doc.setSyntaxId(XWikiDocument.XWIKI20_SYNTAXID);
> > + }
> > + return needsUpdate;
> > + }
> > +
> > + /**
> > + * @return the XWikiContext extracted from the execution.
> > + */
> > + private XWikiContext getXWikiContext()
> > + {
> > + return (XWikiContext)
> this.execution.getContext().getProperty("xwikicontext");
> > + }
> > +
> > +}
> >
> > Added:
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/InvalidComponentDefinitionException.java
> > ===================================================================
> > ---
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/InvalidComponentDefinitionException.java
> (rev 0)
> > +++
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/InvalidComponentDefinitionException.java
> 2010-05-15 15:08:25 UTC (rev 28878)
> > @@ -0,0 +1,59 @@
>
> [...]
>
> > +/**
> > + * Exception thrown by component builders when a document holds an
> invalid compoentn definition.
> > + * (For example if no role has been specified).
> > + *
> > + * @since 2.4-M2
> > + * @version $Id$
> > + */
> > +public class InvalidComponentDefinitionException extends Exception
> > +{
> > + /**
> > + * Constructor of this exception.
> > + */
> > + public InvalidComponentDefinitionException()
> > + {
> > + super();
> > + }
> > +
> > + /**
> > + * Constructor of this exception.
> > + *
> > + * @param message a message associated with the exception, that
> explains why the definition is invalid
> > + */
> > + public InvalidComponentDefinitionException(String message)
> > + {
> > + super(message);
> > + }
> > +
> > + /**
> > + * Constructor of this exception.
> > + *
> > + * @param message a message associated with the exception, that
> explains why the definition is invalid
> > + * @param t the root cause
> > + */
> > + public InvalidComponentDefinitionException(String message,
> Throwable t)
> > + {
> > + super(message);
> > + }
> > +}
> >
> > Added:
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/MethodOutputHandler.java
> > ===================================================================
> > ---
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/MethodOutputHandler.java
> (rev 0)
> > +++
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/MethodOutputHandler.java
> 2010-05-15 15:08:25 UTC (rev 28878)
> > @@ -0,0 +1,44 @@
>
> [...]
>
> > +/**
> > + * Utility for wiki methods to return a value. An implementation of
> this interface is binded in the context of a
> > + * wiki method execution, so that such method scripts can return a
> value using {@link #returnValue(Object)}.
> > + *
> > + * @since 2.4-M2
> > + * @version $Id$
> > + */
> > +public interface MethodOutputHandler
> > +{
> > +
> > + /**
> > + * Stores a value in the method invocation context for further
> return.
> > + * Note that if this method is called multiple times during the
> invocation, the last one wins.
> > + *
> > + * @param value the value to return
> > + */
> > + void returnValue(Object value);
> > +
> > + /**
> > + * @return the current stored return value (null if not set
> yet).
> > + */
> > + Object getReturnValue();
> > +}
> >
> > Added:
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponent.java
> > ===================================================================
> > ---
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponent.java
> (rev 0)
> > +++
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponent.java
> 2010-05-15 15:08:25 UTC (rev 28878)
> > @@ -0,0 +1,58 @@
>
> [...]
>
> > +/**
> > + * Represents the definition of a wiki component implementation.
> > + *
> > + * @since 2.4-M2
> > + * @version $Id$
> > + */
> > +public interface WikiComponent
> > +{
> > + /**
> > + * @return the reference to the document holding this wiki
> component definition.
> > + */
> > + DocumentReference getDocumentReference();
> > +
> > + /**
> > + * @return the role implemented by this component
> implementation.
> > + */
> > + Class< ? > getRole();
> > +
> > + /**
> > + * @return the hint of the role implemented by this component
> implementation.
> > + */
> > + String getRoleHint();
> > +
> > + /**
> > + * @return the extra list of interfaces this component
> implementation implements.
> > + */
> > + Class< ? >[] getImplementedInterfaces();
> > +
> > + /**
> > + * @return the map of method name/wiki code this component
> implementation handles.
> > + */
> > + Map<String, String> getHandledMethods();
> > +}
> >
> > Added:
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponentBuilder.java
> > ===================================================================
> > ---
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponentBuilder.java
> (rev 0)
> > +++
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponentBuilder.java
> 2010-05-15 15:08:25 UTC (rev 28878)
> > @@ -0,0 +1,46 @@
>
> [...]
>
> > +/**
> > + * Constructs a {@link WikiComponent} out of the data contained in
> the document pointed by a {@link DocumentReference}.
> > + *
> > + * @since 2.4-M2
> > + * @version $Id$
> > + */
> > +@ComponentRole
> > +public interface WikiComponentBuilder
> > +{
> > +
> > + /**
> > + * Builds a wiki component representation extracting the data
> stored as objects of document.
> > + *
> > + * @param reference the reference to the document that holds
> component definition objects
> > + * @return the constructed component definition
> > + * @throws InvalidComponentDefinitionException when the data in
> the document is not a valid component definition
> > + * @throws WikiComponentException the builder failed to create
> the component out of the document (for example due to
> > + * a failure by tge underlying store, etc.)
> > + */
> > + WikiComponent build(DocumentReference reference) throws
> InvalidComponentDefinitionException, WikiComponentException;
> > +
> > +}
> >
> > Added:
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponentException.java
> > ===================================================================
> > ---
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponentException.java
> (rev 0)
> > +++
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponentException.java
> 2010-05-15 15:08:25 UTC (rev 28878)
> > @@ -0,0 +1,51 @@
>
> [...]
>
> > +/**
> > + * A generic exception thrown by this module, usually a wrapper
> around lower level exceptions.
> > + *
> > + * @since 2.4-M2
> > + * @version $Id$
> > + */
> > +public class WikiComponentException extends Exception
> > +{
> > + /**
> > + * Constructor of this exception.
> > + *
> > + * @param message the message associated with the exception
> > + */
> > + public WikiComponentException(String message)
> > + {
> > + super(message);
> > + }
> > +
> > + /**
> > + * Constructor of this exception.
> > + *
> > + * @param message the message associated with the exception
> > + * @param t the root cause
> > + */
> > + public WikiComponentException(String message, Throwable t)
> > + {
> > + super(message, t);
> > + }
> > +
> > +}
> >
> > Added:
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponentInvocationHandler.java
> > ===================================================================
> > ---
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponentInvocationHandler.java
> (rev 0)
> > +++
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponentInvocationHandler.java
> 2010-05-15 15:08:25 UTC (rev 28878)
> > @@ -0,0 +1,245 @@
>
> [...]
>
> > +/**
> > + * Method invocation handler for wiki component proxy instances.
> Has a reference on a map of name/body wiki code of
> > + * supported methods.
> > + *
> > + * @since 2.4-M2
> > + * @version $Id$
> > + */
> > +public class WikiComponentInvocationHandler implements
> InvocationHandler
> > +{
> > + /**
> > + * The key under which the output is kept in the method
> invocation context.
> > + */
> > + private static final String METHOD_CONTEXT_OUTPUT_KEY =
> "output";
> > +
> > + /**
> > + * The key under which the context document is kept in the
> XWiki context.
> > + */
> > + private static final String XWIKI_CONTEXT_DOC_KEY = "doc";
> > +
> > + /**
> > + * Pre-loaded hasCode Method.
> > + *
> > + * @see {@link Object#hashCode()}
> > + */
> > + private static Method hashCodeMethod;
> > +
> > + /**
> > + * Pre-loaded equals method.
> > + *
> > + * @see {@link Object#equals(Object)}
> > + */
> > + private static Method equalsMethod;
> > +
> > + /**
> > + * Pre-loaded toString method.
> > + *
> > + * @see {@link Object#toString()}
> > + */
> > + private static Method toStringMethod;
> > +
> > + static {
> > + try {
> > + hashCodeMethod = Object.class.getMethod("hashCode",
> null);
> > + equalsMethod = Object.class.getMethod("equals", new
> Class[] {Object.class});
> > + toStringMethod = Object.class.getMethod("toString",
> null);
> > + } catch (NoSuchMethodException e) {
> > + throw new NoSuchMethodError(e.getMessage());
> > + }
> > + }
> > +
> > + /**
> > + * Map hosting handled methods. Keys are method names and
> values are wiki code to "execute".
> > + */
> > + private Map<String, String> handledMethods;
> > +
> > + /**
> > + * Our component manager.
> > + */
> > + private ComponentManager componentManager;
> > +
> > + /**
> > + * The reference to the document.
> > + */
> > + private DocumentReference componentReference;
> > +
> > + /**
> > + * Constructor of this invocation handler.
> > + *
> > + * @param componentReference reference to the document holding
> the component definition
> > + * @param methods the map of methods handled by the component
> instance
> > + * @param componentManager the component manager
> > + */
> > + public WikiComponentInvocationHandler(DocumentReference
> componentReference, Map<String, String> methods,
> > + ComponentManager componentManager)
> > + {
> > + this.componentReference = componentReference;
> > + this.handledMethods = methods;
> > + this.componentManager = componentManager;
> > + }
> > +
> > + /**
> > + * {@inheritDoc}
> > + */
> > + public Object invoke(Object proxy, Method method, Object[]
> args) throws Throwable
> > + {
> > + if (!this.handledMethods.containsKey(method.getName())) {
> > + if (method.getDeclaringClass() == Object.class) {
> > + return this.proxyObjectMethod(proxy, method, args);
> > + } else {
> > + throw new NoSuchMethodException();
> > + }
> > + } else {
> > + return this.executeWikiContent(method);
> > + }
> > +
> > + }
> > +
> > + /**
> > + * "Executes" the wiki content associated to the passed method.
> > + *
> > + * @param method the method to execute
> > + * @return the result of the execution
> > + * @throws Exception when an error occurs during execution
> > + */
> > + @SuppressWarnings("unchecked")
> > + private Object executeWikiContent(Method method) throws
> Exception
> > + {
> > + XDOM xdom;
> > + Map xwikiContext = null;
> > + Object contextDoc = null;
> > +
> > + Parser parser = componentManager.lookup(Parser.class,
> Syntax.XWIKI_2_0.toIdString());
> > + xdom = parser.parse(new
> StringReader(this.handledMethods.get(method.getName())));
> > +
> > + Execution execution =
> componentManager.lookup(Execution.class);
> > + Transformation macroTransformation =
> componentManager.lookup(Transformation.class, "macro");
> > + DocumentAccessBridge docBridge =
> componentManager.lookup(DocumentAccessBridge.class);
> > +
> > + Map<String, Object> methodContext = new HashMap<String,
> Object>();
> > + methodContext.put(METHOD_CONTEXT_OUTPUT_KEY, new
> DefaultMethodOutputHandler());
> > +
> > + // Place macro context inside xwiki context
> ($context.macro).
> > + xwikiContext = (Map)
> execution.getContext().getProperty("xwikicontext");
> > + xwikiContext.put("method", methodContext);
> > + // Save current context document.
> > + contextDoc = xwikiContext.get(XWIKI_CONTEXT_DOC_KEY);
> > + // Make sure has prog rights
> > + xwikiContext.put(XWIKI_CONTEXT_DOC_KEY,
> docBridge.getDocument(this.componentReference));
> > +
> > + // Perform internal macro transformations.
> > + macroTransformation.transform(xdom, Syntax.XWIKI_2_0);
> > +
> > + if (methodContext.get(METHOD_CONTEXT_OUTPUT_KEY) != null
> > + && ((MethodOutputHandler)
> methodContext.get(METHOD_CONTEXT_OUTPUT_KEY)).getReturnValue() !=
> null) {
> > + return
> method.getReturnType().cast(((MethodOutputHandler)
> > +
> methodContext.get(METHOD_CONTEXT_OUTPUT_KEY)).getReturnValue());
> > + } else if (method.getReturnType().equals(String.class)) {
> > + // If return type is String and no specific return
> value has been provided during the macro
> > + // expansion, then we return the content redered as
> > + WikiPrinter printer = new DefaultWikiPrinter();
> > + BlockRenderer renderer =
> componentManager.lookup(BlockRenderer.class,
> Syntax.PLAIN_1_0.toIdString());
> > + renderer.render(xdom, printer);
> > + return printer.toString();
> > + } else {
> > + // surrender
> > + return null;
> > + }
> > + }
>
> Don't do the same mistake than wik macros (see
> http://jira.xwiki.org/jira/browse/XWIKI-5030), you should store the
> XDOM instead of the source to avoid reparsing it each time you execute
> a virtual method.
OK. Will take care of that.
Jerome.
>
> > +
> > + /**
> > + * Proxies a method of the {@link Object} class.
> > + *
> > + * @param proxy the proxy instance
> > + * @param method the method to proxy
> > + * @param args possible arguments to the method invocation
> > + * @return the result of the proxied call
> > + */
> > + private Object proxyObjectMethod(Object proxy, Method method,
> Object[] args)
> > + {
> > + if (method.equals(hashCodeMethod)) {
> > + return proxyHashCode(proxy);
> > + } else if (method.equals(equalsMethod)) {
> > + return proxyEquals(proxy, args[0]);
> > + } else if (method.equals(toStringMethod)) {
> > + return proxyToString(proxy);
> > + } else {
> > + throw new InternalError("unexpected Object method
> dispatched: " + method);
> > + }
> > + }
> > +
> > + /**
> > + * Default behavior for {@link Object#hashCode()} when not
> overridden in the wiki component definition.
> > + *
> > + * @param proxy the proxy object
> > + * @return a hash code for the proxy object, as if using
> standard {Object{@link #hashCode()}.
> > + */
> > + protected Integer proxyHashCode(Object proxy)
> > + {
> > + return new Integer(System.identityHashCode(proxy));
> > + }
> > +
> > + /**
> > + * Default behavior for {@link Object#equals(Object)} when not
> overridden in the wiki component definition.
> > + *
> > + * @param proxy the proxy object
> > + * @param other the other object of the comparison
> > + * @return the result of the equality comparison between the
> passed proxy and other object
> > + */
> > + protected Boolean proxyEquals(Object proxy, Object other)
> > + {
> > + return (proxy == other ? Boolean.TRUE : Boolean.FALSE);
> > + }
> > +
> > + /**
> > + * Default behavior for {@link Object#toString()} when not
> overridden in the wiki component definition.
> > + *
> > + * @param proxy the proxy object
> > + * @return the String representation of the passed proxy object
> > + */
> > + protected String proxyToString(Object proxy)
> > + {
> > + return proxy.getClass().getName() + '@' +
> Integer.toHexString(proxy.hashCode());
> > + }
> > +
> > +}
> >
> > Added:
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponentManager.java
> > ===================================================================
> > ---
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponentManager.java
> (rev 0)
> > +++
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/WikiComponentManager.java
> 2010-05-15 15:08:25 UTC (rev 28878)
> > @@ -0,0 +1,46 @@
>
> [...]
>
> > +package org.xwiki.component.wiki;
> > +
> > +import org.xwiki.component.annotation.ComponentRole;
> > +
> > +/**
> > + * A WikiComponentManager is responsible for registering and
> unregistering components that are defined as wiki pages.
> > + * Each {@link WikiComponent} managed by such manager is associated
> to a {@link org.xwiki.model.DocumentReference}. The
> > + * referred document contains XObjects that define the role, hint
> and behavior (method bodies) of the component. This
> > + * document may also define requirements (other components to be
> binded in the method bodies execution context) and
> > + * possible extra interfaces (for example to implement {@link
> org.xwiki.component.phase.Initializable}).
> > + *
> > + * @since 2.4-M2
> > + * @version $Id$
> > + */
> > +@ComponentRole
> > +public interface WikiComponentManager
> > +{
> > +
> > + /**
> > + * Registers the passed component against the underlying
> component repository.
> > + *
> > + * @param component the component to register
> > + * @throws WikiComponentException when failed to register the
> component against the CM
> > + */
> > + void registerWikiComponent(WikiComponent component) throws
> WikiComponentException;
> > +
> > +}
> >
> > Added:
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/internal/DefaultMethodOutputHandler.java
> > ===================================================================
> > ---
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/internal/DefaultMethodOutputHandler.java
> (rev 0)
> > +++
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/internal/DefaultMethodOutputHandler.java
> 2010-05-15 15:08:25 UTC (rev 28878)
> > @@ -0,0 +1,54 @@
>
> [...]
>
> > +package org.xwiki.component.wiki.internal;
> > +
> > +import org.xwiki.component.wiki.MethodOutputHandler;
> > +
> > +/**
> > + * Default method output handler.
> > + *
> > + * @since 2.4-M2
> > + * @version $Id$
> > + */
> > +public class DefaultMethodOutputHandler implements
> MethodOutputHandler
> > +{
> > +
> > + /**
> > + * The stored return value.
> > + */
> > + private Object returnValue;
> > +
> > + /**
> > + * {@inheritDoc}
> > + */
> > + public void returnValue(Object value)
> > + {
> > + this.returnValue = value;
> > + }
> > +
> > + /**
> > + * {@inheritDoc}
> > + */
> > + public Object getReturnValue()
> > + {
> > + return this.returnValue;
> > + }
> > +
> > +}
> >
> > Added:
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/internal/DefaultWikiComponent.java
> > ===================================================================
> > ---
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/internal/DefaultWikiComponent.java
> (rev 0)
> > +++
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/internal/DefaultWikiComponent.java
> 2010-05-15 15:08:25 UTC (rev 28878)
> > @@ -0,0 +1,139 @@
>
> [...]
>
> > +package org.xwiki.component.wiki.internal;
> > +
> > +import java.util.HashMap;
> > +import java.util.Map;
> > +
> > +import org.xwiki.component.wiki.WikiComponent;
> > +import org.xwiki.model.reference.DocumentReference;
> > +
> > +/**
> > + * Default implementation of a wiki component definition.
> > + *
> > + * @since 2.4-M2
> > + * @version $Id$
> > + */
> > +public class DefaultWikiComponent implements WikiComponent
> > +{
> > + /**
> > + * @see {@link #getDocumentReference()}
> > + */
> > + private DocumentReference documentReference;
> > +
> > + /**
> > + * @see {@link #getHandledMethods()}
> > + */
> > + private Map<String, String> handledMethods = new
> HashMap<String, String>();
> > +
> > + /**
> > + * @see {@link #getRole()}
> > + */
> > + private Class< ? > role;
> > +
> > + /**
> > + * @see {@link #getRoleHint()}
> > + */
> > + private String roleHint;
> > +
> > + /**
> > + * @see {@link #getImplementedInterfaces()}
> > + */
> > + private Class< ? >[] implementedInterfaces = new Class< ?
> >[]{};
> > +
> > + /**
> > + * Constructor of this component.
> > + *
> > + * @param reference the document holding the component
> definition
> > + * @param role the role implemented
> > + * @param roleHint the role hint for this role implementation
> > + */
> > + public DefaultWikiComponent(DocumentReference reference, Class<
> ? > role, String roleHint)
> > + {
> > + this.documentReference = reference;
> > + this.role = role;
> > + this.roleHint = roleHint;
> > + }
> > +
> > + /**
> > + * {@inheritDoc}
> > + */
> > + public DocumentReference getDocumentReference()
> > + {
> > + return this.documentReference;
> > + }
> > +
> > + /**
> > + * {@inheritDoc}
> > + */
> > + public Map<String, String> getHandledMethods()
> > + {
> > + return this.handledMethods;
> > + }
> > +
> > + /**
> > + * {@inheritDoc}
> > + */
> > + public Class< ? > getRole()
> > + {
> > + return this.role;
> > + }
> > +
> > + /**
> > + * {@inheritDoc}
> > + */
> > + public String getRoleHint()
> > + {
> > + return this.roleHint;
> > + }
> > +
> > + /**
> > + * {@inheritDoc}
> > + */
> > + public Class< ? >[] getImplementedInterfaces()
> > + {
> > + return this.implementedInterfaces;
> > + }
> > +
> > + /**
> > + * Sets the handled method.
> > + *
> > + * @see {@link #getHandledMethods()}
> > + *
> > + * @param methods the methods this component will handle
> > + */
> > + public void setHandledMethods(Map<String, String> methods)
> > + {
> > + this.handledMethods = methods;
> > + }
> > +
> > + /**
> > + * Sets the implemented interfaces.
> > + *
> > + * @see {@link #getImplementedInterfaces()}
> > + *
> > + * @param interfaces the interfaces this component will
> implement.
> > + */
> > + public void setImplementedInterfaces(Class< ? >[] interfaces)
> > + {
> > + this.implementedInterfaces = interfaces;
> > + }
> > +
> > +}
> >
> > Added:
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/internal/DefaultWikiComponentManager.java
> > ===================================================================
> > ---
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/internal/DefaultWikiComponentManager.java
> (rev 0)
> > +++
> contrib/sandbox/xwiki-wiki-components/src/main/java/org/xwiki/component/wiki/internal/DefaultWikiComponentManager.java
> 2010-05-15 15:08:25 UTC (rev 28878)
> > @@ -0,0 +1,130 @@
>
> [...]
>
> > +
> > +/**
> > + * Default implementation of {@link WikiComponentManager}. Creates
> proxy objects which method invocation handler keeps a
> > + * reference on a set of declared method and associated wiki
> content to "execute".
> > + *
> > + * @since 2.4-M2
> > + * @version $Id$
> > + */
> > +@Component
> > +public class DefaultWikiComponentManager extends AbstractLogEnabled
> implements WikiComponentManager
> > +{
> > + /**
> > + * Component manager against which wiki component will be
> registered.
> > + */
> > + @Requirement
> > + private ComponentManager mainComponentManager;
> > +
> > + /**
> > + * {@inheritDoc}
> > + */
> > + @SuppressWarnings("unchecked")
> > + public void registerWikiComponent(WikiComponent component)
> throws WikiComponentException
> > + {
> > + try {
> > + // Get the component role interface
> > + Class< ? > role = component.getRole();
> > +
> > + // Create the method invocation handler of the proxy
> > + InvocationHandler handler =
> > + new
> WikiComponentInvocationHandler(component.getDocumentReference(),
> component.getHandledMethods(),
> > + mainComponentManager);
> > +
> > + // Prepare array of all interfaces the component
> implementation declares, that is the interface declared as
> > + // component role
> > + // plus possible extra other interfaces
> > + Class< ? >[] allImplementedInterfaces = new Class< ?
> >[component.getImplementedInterfaces().length + 1];
> > + System.arraycopy(component.getImplementedInterfaces(),
> 0, allImplementedInterfaces, 0, component
> > + .getImplementedInterfaces().length);
> > +
> allImplementedInterfaces[component.getImplementedInterfaces().length]
> = role;
> > +
> > + // Create the component instance and its descritor
> > + Object instance =
> Proxy.newProxyInstance(role.getClassLoader(),
> allImplementedInterfaces, handler);
> > + ComponentDescriptor componentDescriptor =
> this.createComponentDescriptor(role, component.getRoleHint());
> > +
> > + // Since we are responsible to create the component
> instance,
> > + // we also are responsible of its initialization (if
> needed)
> > + if (this.isInitializable(allImplementedInterfaces)) {
> > + try {
> > + ((Initializable) instance).initialize();
> > + } catch (InitializationException e) {
> > + getLogger().error("Failed to initialize wiki
> component", e);
> > + }
> > + }
> > +
> > + // Finally, register the component against the CM
> > +
> this.mainComponentManager.registerComponent(componentDescriptor,
> role.cast(instance));
> > + } catch (ComponentRepositoryException e) {
> > + throw new WikiComponentException("Failed to register
> wiki component against component repository", e);
> > + }
> > + }
> > +
> > + /**
> > + * Helper method to create a component descriptor from role and
> hint.
> > + *
> > + * @param role the component role of the descriptor to create
> > + * @param roleHint the hint of the implementation for the
> descriptor to create
> > + * @return the constructed {@link ComponentDescriptor}
> > + */
> > + @SuppressWarnings("unchecked")
> > + private ComponentDescriptor createComponentDescriptor(Class
> role, String roleHint)
> > + {
> > + DefaultComponentDescriptor cd = new
> DefaultComponentDescriptor();
> > + cd.setRole(role);
> > + cd.setRoleHint(roleHint);
> > + return cd;
> > + }
> > +
> > + /**
> > + * Helper method that checks if at least one of an array of
> interfaces is the {@link Initializable} class.
> > + *
> > + * @param interfaces the array of interfaces to test
> > + * @return true if at least one of the passed interfaces is the
> is the {@link Initializable} class.
> > + */
> > + private boolean isInitializable(Class< ? >[] interfaces)
> > + {
> > + for (Class< ? > iface : interfaces) {
> > + if (Initializable.class.equals(iface)) {
> > + return true;
> > + }
> > + }
> > + return false;
> > + }
> > +}
> >
>
> [...]
>
> >
> > Added:
> contrib/sandbox/xwiki-wiki-components/src/test/java/org/xwiki/component/wiki/WikiComponentManagerTest.java
> > ===================================================================
> > ---
> contrib/sandbox/xwiki-wiki-components/src/test/java/org/xwiki/component/wiki/WikiComponentManagerTest.java
> (rev 0)
> > +++
> contrib/sandbox/xwiki-wiki-components/src/test/java/org/xwiki/component/wiki/WikiComponentManagerTest.java
> 2010-05-15 15:08:25 UTC (rev 28878)
> > @@ -0,0 +1,34 @@
>
> [...]
>
> > +
> > +public class WikiComponentManagerTest extends
> AbstractComponentTestCase
> > +{
> > + private WikiComponentManager manager;
> > +
> > + @Before
> > + public void setUp() throws Exception
> > + {
> > + manager =
> getComponentManager().lookup(WikiComponentManager.class);
> > + }
> > +
> > + @Test
> > + public void testRegisterWikiComponent() throws Exception
> > + {
> > + DocumentReference pseudoReference = new
> DocumentReference("somewiki","XWiki","MyComponent");
> > +
> > + DefaultWikiComponent wc = new
> DefaultWikiComponent(pseudoReference, WikiComponentManager.class,
> "test");
> > +
> > + this.manager.registerWikiComponent(wc);
> > +
> > + WikiComponentManager registered =
> this.getComponentManager().lookup(WikiComponentManager.class, "test");
> > +
> > + Assert.assertNotNull(registered);
> > + }
> > +}
>
>
>
> --
> Thomas Mortagne
> _______________________________________________
> devs mailing list
> devs@xwiki.org
> http://lists.xwiki.org/mailman/listinfo/devs