16 May
2010
16 May
'10
2:03 p.m.
On Sun, May 16, 2010 at 15:25, Jerome Velociter <[email protected]> wrote: > > ----- "Thomas Mortagne" <[email protected]> wrote: > >> On Sat, May 15, 2010 at 17:08, jvelociter >> <[email protected]> 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) Yes probably, sounds weird to implements an incomplete component. > >> >> > - 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 >> [email protected] >> http://lists.xwiki.org/mailman/listinfo/devs > _______________________________________________ > devs mailing list > [email protected] > http://lists.xwiki.org/mailman/listinfo/devs > -- Thomas Mortagne