Catalogue des points de débranchement (hooks) disponibles dans l'API JCMS

Attention

Ce document ne tient pas compte des nouveautés des versions 8 et supérieures.
Veuillez consulter le document API de gestion des données.

1. Qui, Quoi, Quand, Où ?

Voici les principaux points de débranchements intervenant durant l'exécution de JCMS :

  • Au démarrage de JCMS
    • ChannelListener
    • PluginPolicyListener
    • StoreListener
  • Lors d'une requête HTTP
    • AuthenticationHandler
    • WebdavPolicyFilter
  • Lors de l'accès aux espaces de travail
    • CtxMenuPolicyFilter
    • QueryFilter
    • RightPolicyFilter
    • Targets
    • TemplatePolicyFilter
    • ThumbnailPolicyFilter
    • WikiPolicyFilter
    • WysiwygPolicyFilter
  • Lors de l'affichage d'une page portail
    • CtxMenuPolicyFilter
    • PortalPolicyFilter
    • RightPolicyFilter
    • Targets
    • TemplatePolicyFilter
    • ThumbnailPolicyFilter
    • WikiPolicyFilter
    • WysiwygPolicyFilter
  • Lors de la contribution
    • DataController
    • DBListener
    • StoreListener
    • Targets
    • WidgetPolicyFilter
  • Lors de la recherche (et/ou de l'indexation)
    • LuceneSearchEnginePolicyFilter
    • LuceneSearchEnginePolicy
    • MemberQueryFilter
    • QueryFilter
    • RightPolicyFilter
    • Targets
  • Lors de l'envoi d'un mail
    • MailPolicyFilter
  • Lors de l'import
    • DataController
    • ImportPolicyFilter
  • Lors de l'export
    • ExportPolicyFilter
    • QueryFilter
  • A heure régulière
    • AlarmListener
  • Lors du nettoyage du store
    • CleanFilter

2. AlarmListener

2.1 Présentation

2.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<alarmlistener schedule="30 14 * * * *" manager="PluginAlarmManager"/>
<alarmlistener frequency="5" manager="PluginAlarmManager"/>
...
</plugincomponents>

Remarques :

  • L'attribut schedule détermine une répétition à date et heure régulière (p. ex. tous les jours à 14h30).
  • L'attribut frequency détermine une répétition à fréquence régulière, en minutes (p. ex. toutes les 5 minutes).
  • L'attribut manager détermine l'instance de gestionnaire d'alarme à utiliser. S'il n'est pas précisé, l'alarme sera gérée dans le gestionnaire commun.

Classe Java

public class MyAlarmListener extends TransactionalAlarmListener {

@Override
public void handleTransactionalAlarm(AlarmEntry entry) {
// ...
}
}
public class MyAlarmListenerBeforeJCMS6 implements AlarmListener {

@Override
public void handleAlarm(AlarmEntry entry) {
// ...
}
}

Remarque :

  • A partir de JCMS 6, il faut dériver de TransactionalAlarmListener pour que le traitement soit encapsulé dans une transaction Hibernate.
  • Lorsque l'alarme se déclenche, si le traitement à réaliser est long, il est nécessaire de le traiter dans un thread séparé afin de ne pas bloquer les alarmes suivantes.

 

3. AuthenticationHandler

3.1 Présentation

  • Objectifs
    • Fournir un nouveau système d'authentification
    • Intervenir dans la chaîne d'authentification
  • Exemples d'usage
    • Authentification par SSO
    • Authentification via une base de données
    • Authentification Exchange à partir de l'authentification JCMS
  • Version de JCMS
    • JCMS 5.7 (les AuthenticationHandler ont remplacé les AuthenticationManager disponibles depuis JCMS 5.5)
  • Documentation

3.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<authenticationhandler class="com.example.MyAuthenticationHandler" />
...
</plugincomponents>

Classe Java

public class MyAuthenticationHandler extends AuthenticationHandler {

@Override
public void login(AuthenticationContext ctxt) throws IOException {
// ...
}

@Override
public void logout(AuthenticationContext ctxt) throws IOException {
// ...
}
}

4. ChannelListener

4.1 Présentation

  • Objectifs
    • Déclencher un traitement au démarrage de JCMS
    • Déclencher un traitement à l'arrêt de JCMS
  • Exemples d'usage
    • Génération de données après le démarrage de JCMS
    • Déclenchement d'analyses après un redémarrage
    • Relâchement de ressources distantes à l'arrêt de JCMS
  • Version de JCMS
    • Toute version
  • Documentation

4.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<channellistener class="com.example.MyChannelListener"/>
...
</plugincomponents>

Classe Java

public class MyChannelListener extends ChannelListener {

@Override
public void initBeforeStoreLoad() throws Exception {
// ...
}

@Override
public void initAfterStoreLoad() throws Exception {
// ...
}

@Override
public void handleFinalize() {
// ...
}
}

5. ChannelPolicyFilter

5.1 Présentation

  • Objectifs
    • Agir sur la résolution des identifiants.
    • Ajouter ou modifier les méta-templates utilisés pour la génération de ressources associées aux types de publication (classe Java, JSP d'édition, d'affichage, …)
  • Exemples d'usages
    • Résolution d'identifiants externes (p. ex. Exchange_123456789)
    • Génération de JSP d'affichage pour appareils mobiles
    • Génération de web services
    • Génération de classes et méthodes utilitaires (Comparator, DataSelector, …)
  • Version de JCMS
    • JCMS 5.7
  • Documentation

5.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<policyfilter class="com.example.MyChannelPolicyFilter" />
...
</plugincomponents>

Classe Java

public class MyChannelPolicyFilter extends BasicChannelPolicyFilter {

@Override
public Data getData(String id) {
// ...
}

@Override
public void checkJAVAMetaTemplates(Map templateMap, String className, Element typeElt, boolean isExtension) {
// ...
}

@Override
public void checkJSPMetaTemplates(Map templateMap, String className, Element typeElt, boolean isExtension) {
// ...
}
}

6. CleanFilter

6.1 Présentation

  • Objectifs
    • Intervenir dans la mécanique de nettoyage du store en proposant de nouvelles règles de filtrage.
  • Exemples d'usage
    • Ne nettoyer que les opérations sur les membres
    • Ne pas nettoyer les mises-à-jour sur les publications en cours de rédaction
    • Garder au moins les 3 dernières mises-à-jour pour chaque publication
  • Version de JCMS
    • JCMS 5.5
  • Documentation

6.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<cleanfilter class="com.example.MyCleanFilter" />
...
</plugincomponents>

Classe Java

public class MyCleanFilter extends CustomCleanFilter {

@Override
public String getLabel(String userLang) {
// ...
}

@Override
public boolean isCleanable(StorableLogEntry entry, Class clazz) {
// ...
}

@Override
public void cleanMergeMap(Map mergeMap) {
// ...
}
}

6.3 Exemples

L'exemple suivant limite le nettoyage aux opérations sur les membres :

public class MemberCleanFilter extends CustomCleanFilter {

@Override
public String getLabel(String userLang) {
return "Nettoyer les membres";
}

@Override
public boolean isCleanable(StorableLogEntry entry, Class clazz) {
if (!isEnabled()) {
return true;
}

return Member.class == clazz;
}
}

 

L'exemple suivant limite le nettoyage aux opérations portant sur des publications actuellement dans l'état planifié ou au delà :

public class KeepDraftCleanFilter extends CustomCleanFilter {

@Override
public String getLabel(String userLang) {
return "Conserver toutes les mises-à-jour sur les publications en cours de rédaction";
}

@Override
public boolean isCleanable(StorableLogEntry entry, Class clazz) {
if (!isEnabled()) {
return true;
}

if (!entry.isUpdate()) {
return true;
}

if (!Publication.class.isAssignableFrom(clazz)) {
return true;
}

Channel channel = Channel.getChannel();

Publication pub = channel.getPublication(entry.getID());
if (pub == null) {
return true;
}

return pub.getPstatus() >= WorkflowManager.SCHEDULED_PSTATUS);
}
}

 

L'exemple suivant empêche le nettoyage des 3 dernières opérations portant sur une donnée :

public class KeepLastCleanFilter extends CustomCleanFilter {

@Override
public String getLabel(String userLang) {
return "Garder au moins les 3 dernières mises-à-jour";
}

@Override
public void cleanMergeMap(Map mergeMap) {
if (!isEnabled()) {
return;
}

for (Iterator it = mergeMap.entrySet().iterator(); it.hasNext();) {
Map.Entry itEntry = (Map.Entry) it.next();
TreeSet set = (TreeSet)itEntry.getValue();
if (set == null || set.size() < 3) {
continue;
}

// Remove the 2 last updates
set.remove(set.last());
set.remove(set.last());
}
}
}

 

7. CtxMenuPolicyFilter

7.1 Présentations

  • Objectifs
    • Insérer de nouveaux items dans les menus contextuels de JCMS :
      • Menu des publications
      • Menu des membres
      • Menu des catégories
      • Menu des portlets (édition mode portail)
  • Exemples d'usage
    • Le module Favoris ajoute un item dans le menu des publications pour ajouter la publication à ses favoris.
    • Le module Wiki ajoute un item dans le menu des publications de type WikiPage pour rafraichir le cache de sur cette WikiPage.
  • Version de JCMS
    • JCMS 5.7
  • Documentation

7.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<policyfilter />
...
</plugincomponents>

Classe Java

public class MyCtxMenuPolicyFilter extends BasicCtxMenuPolicyFilter {

@Override
public char[] checkCtxMenuItems(PublicationCtxMenu ctxMenu, Publication pub, char[] letters) {
// ...
}

@Override
public int handleCtxMenuItems(StringBuffer sb, PublicationCtxMenu ctxMenu, Publication pub, char letter, int status) {
// ...
}
}

Les menus sont identifiés avec un caractère. Avant JCMS 6.1, le choix de ce caractère était à la charge du dévelopeur. Il fallait donc veiller à ne pas rentrer en conflit avec les lettres déjà utilisées. A partir de JCMS 6.1, le caractère est déterminé automatiquement.

7.3 Exemples

Exemple d'usage, à partir de JCMS 6.1 :

public class WikiPageCtxMenuPolicyFilter extends BasicCtxMenuPolicyFilter {

@Override
public boolean init(Plugin plugin) {
CtxMenuManager.getInstance().createMenuEntry(getClass(), PublicationCtxMenu.class);
return super.init(plugin);
}

@Override
public char[] checkCtxMenuItems(PublicationCtxMenu ctxMenu, Publication pub, char[] letters) {

if (!(pub instanceof AbstractWikiPage)) {
return letters;
}

return CtxMenuManager.getInstance().addEntry(letters, getClass(), PublicationCtxMenu.FLAG_EXPORT, true);
}

@Override
public int handleCtxMenuItems(StringBuffer sb, PublicationCtxMenu ctxMenu, Publication pub, char letter, int status) {

CtxMenuManager menuMgr = CtxMenuManager.getInstance();

if (!(pub instanceof AbstractWikiPage) || !menuMgr.isCurrent(getClass(), letter)) {
return PublicationCtxMenu.MENU_SKIPPED;
}

// Compute some vars
...
String redirectJSNoCaddy = ctxMenu.getUrl();

// Print the menu
CtxMenuUtil.addItemWithConfirm(sb, userLang, true, icon, label, url, confirmMsg, redirectJSNoCaddy, contextPath);

return PublicationCtxMenu.MENU_ENABLED;
}
}

 

Exemple d'usage avant JCMS 6.1 :

public class BookmarkCtxMenuPolicyFilter extends BasicCtxMenuPolicyFilter  {

private static String LABEL_PROP = "jcmsplugin.bookmarks.lbl.add-bookmark";
private static String BOOKMARK_ICON = "plugins/BookmarksPlugin/images/addBookmark.gif";
private static char FLAG_BOOKMARK = '!'; // TODO should be dynamic to avoid conflict with other CtxMenuPolicyFilter

public char[] checkCtxMenuItems(PublicationCtxMenu ctxMenu, Publication pub, char[] letters) {

if (!(pub instanceof Content)) {
return letters;
}

// Place a new menu just after the "Export XML" menu ('B')
char[] newLetters = new char[letters.length + 1];
for (int i = 0, k = 0; i < letters.length; i++, k++) {
char letter = letters[i];
newLetters[k] = letter;

if (letter == PublicationCtxMenu.FLAG_EXPORT) {
k++;
newLetters[k] = FLAG_BOOKMARK;
}
}

return newLetters;

}

public int handleCtxMenuItems(StringBuffer sb, PublicationCtxMenu ctxMenu, Publication pub, char letter, int status) {

if (letter != FLAG_BOOKMARK || !(pub instanceof Content)) {
return PublicationCtxMenu.MENU_SKIPPED;
}

// Compute some vars
String userLang = ctxMenu.getUserLang();

String icon = BOOKMARK_ICON;
String label = JcmsUtil.glp(userLang, LABEL_PROP);

BookmarkManager mgr = BookmarkManager.getInstance();

// Already bookmarked
if (mgr.isBookmarked(ctxMenu.getLoggedMember(), pub)) {
openItem(sb, true);
closeItem(sb, icon, label);

return PublicationCtxMenu.MENU_DISABLED;
}

// Not yet bookmarked
String url = "plugins/BookmarksPlugin/jsp/addBookmark.jsp?dataId=" + pub.getId();

// Print the menu (Cut And Paste from AbstractCtxMenu)
openItem(sb, true);
sb
.append("<a href='")
.append(url)
.append("' onclick='return JCMS.plugin.bookmarks.BookmarksUtils.addBookmark(this);'>");
closeItem(sb, icon, label);

return PublicationCtxMenu.MENU_ENABLED;
}

// Cut And Paste from AbstractCtxMenu. Should be public !
protected void openItem(StringBuffer sb, boolean isEnabled) {
sb.append("<li class='icon " + (isEnabled ? "" : PublicationCtxMenu.DISABLED) + "' >");
}


// Cut And Paste from AbstractCtxMenu. Should be public !
protected void closeItem(StringBuffer sb, String icon, String label) {
sb
.append("<img src='" + icon + "' class='icon icon16' alt='' /> ")
.append(label)
.append("</a>")
.append("</li>");
}
}

8. DataController

8.1 Présentation

  • Objectifs
    • Contrôler l'intégrité des objets (checkIntegrity())
    • Contrôler les écritures (checkWrite())
    • Déclencher des traitements avant et après une écriture (beforeWrite() et afterWrite())
    • Contrôler les widgets d'édition (FieldStatus)

8.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<datacontroller class="com.example.MyDataController" types="Member Article PortletSearch" />
...
</plugincomponents>

9. DBListener

9.1 Présentation

  • Objectifs
    • Dans un environnement JSync, déclencher, sur tous les réplicas, un traitement suite à une écriture dans JcmsDB
  • Exemples d'usage
    • Gestion de caches
    • Gestion d'index
    • Envoi de mail
  • Version de JCMS
    • JCMS 6.0
  • Documentation

9.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<dblistener class="com.example.MyDBListener" types="Review" />
...
</plugincomponents>

Classe Java

public class MyDBListener extends BasicDBListener {
@Override
public void onPostInsert(DBData data, PostInsertEvent event, boolean firstTime) {
// ...
}

@Override
public void onPreUpdate(DBData data, PreUpdateEvent event) {
// ...
}

@Override
public void onPostUpdate(DBData data, PostUpdateEvent event, boolean firstTime) {
// ...
}

@Override
public void onPostDelete(DBData data, PostDeleteEvent event, boolean firstTime) {
// ...
}
}

Remarque :

  • En dérivant de BasicDBListenerStoreListener il est possible d'être à la fois un StoreListener et un DBListener.
  • Les DBListener sont déclenchés sur les autres réplicas avec un retard maximum d'une minute. Ce délai est paramétrable via la propriété dbeventlog.scan-freq.
  • Lorsque l'application n'utilise pas JSync, il est préférable d'utiliser les DataController.

 

10. ExportPolicyFilter

10.1 Présentation

  • Objectifs
    • Permet d'intervenir dans le processus d'export des données, unitaire sur chaque donnée, et globalement sur l'ensemble des données
  • Exemples d'usage
    • Permet d'ajouter/supprimer des données à exporter
    • Permet d'ajouter des méta-données
  • Version de JCMS
    • Disponible à partir de JCMS 5.7 SP2 mais enrichie dans JCMS 5.7 SP5 et à partir de JCMS 6.
  • Documentation

10.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<policyfilter class="com.exampl.MyExportPolicyFilter" />
...
</plugincomponents>

Classe Java

public class MyExportPolicyFilter extends BasicExportPolicyFilter {

@Override
public void processDataExport(Data data, StringBuffer sb, Map context) {
// EMPTY
}

@Override
public void processDataSetExport(Set<? extends Data> dataSet, StringBuffer sb, Map context) {
// EMPTY
}
}

Remarque : pour des besoins simple, une QueryFilter exploitant les informations de contexte sur l'export (ExportConstants.EXPORT_QH_ATTR) peut être une alternative à l'ExportPolicyFilter.

 

11. ImportPolicyFilter

11.1 Présentation

  • Objectifs
    • Permet d'intervenir en amont et en aval du processus d'import des contenus
  • Exemples d'usage
    • Contrôler le contenu du flux d'import (p. ex. signature)
    • Enrichir ou filtrer du flux d'import à gros grain (pour les opérations plus fine, utiliser un DataController, cf. Remarques)
  • Version de JCMS
    • JCMS 5.7.2
  • Documentation

11.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<policyfilter class="com.example.MyImportPolicyFilter" />
...
</plugincomponents>

Classe Java

public class MyImportPolicyFilter extends BasicImportPolicyFilter {

@Override
public boolean beforeImportData(Document doc, ImportOptions options, ImportStatus status, Map context) {
...
}

@Override
public void afterImportData(Document doc, ImportOptions options, ImportStatus status, Map context) {
...
}
}

Remarques :

  • Peut-être combiné avec l'ExportPolicyFilter
  • Peut-être combiné avec un DataController exploitant les informations de context sur l'import:   
    • ImportConstants.IMPORT_DC_ATTR    
    • ImportConstants.IMPORT_DC_JDOM_ELEMENT 
    • ImportConstants.IMPORT_DC_STEP  
    • ImportConstants.IMPORT_OPTIONS

 

12. LuceneSearchEnginePolicyFilter

12.1 Présentation

  • Objectifs
    • La classe LuceneSearchEnginePolicyFilter permet d'intervenir sur le fonctionnement de l'indexation (et donc sur la recherche) des publications et des catégories via Lucene.
    • D'autres modifications concernant la recherche et l'indexation peuvent être réalisées via la classe custom.LuceneSearchEnginePolicy, notamment : 
      • Modification de la pertinence des résultats
      • Comportement d'ctivation de la troncature droite
  • Exemples d'usage
    • Indexation de données supplémentaires
    • Ajout de stop words supplémentaires
  • Version de JCMS
    • JCMS 5.7
  • Documentation

12.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<policyfilter class="com.example.LuceneSearchEnginePolicyFilter" />
...
</plugincomponents>

Classe Java

public class MyLuceneSearchEnginePolicyFilter extends BasicLuceneSearchEnginePolicyFilter {

@Override
  public void filterCategoryDocument(Document doc, Category cat, String lang) {
    // ...
  }
 
  @Override
  public void filterPublicationDocument(Document doc, Publication pub, String lang) {
    // ...
  }
 
  @Override
  public void filterFileDocument(Document doc, File file) {
    // ...
  }

@Override
public void filterMemberDocument(Document doc, final Member mbr) {
// ...
}
 
  @Override
  public HashSet<String> getLanguageStopWordsSet(String lang, HashSet<String> jcms) {
    // ...
  }
 
  @Override
  public Analyzer getAnalyzer(String lang, boolean isIndexing, Analyzer analyser) {
    // ...
  }

}

12.3 Exemples

12.3.1 Indexation de données supplémentaires (e.g. extradata metadata)

Méthodes concernées :

  • filterPublicationDocument(...)
  • filterCategoryDocument(...)
  • filterFileDocument(...)
  • filterMemberDocument(...)

Exemple :

  @Override
public void filterPublicationDocument(Document doc, final Publication pub, final String lang) {
String myValue = Util.getString(pub.getExtraData("jcmsplugin.someextradata"), "");

// Add to custom lucene field "foobar" in order to allow our extradata text to be search using advanced query "foobar:text"
Field customField = new Field("foobar", myValue, Field.Store.NO, Field.Index.TOKENIZED);
doc.add(customField );

// Add to ALLFIELDS_FIELD in order to allow our extradata text to be search every case
Field allField = new Field(LucenePublicationSearchEngine.ALLFIELDS_FIELD, myValue, Field.Store.NO, Field.Index.TOKENIZED);
doc.add(allField);
}

12.3.2 ajout de "stop words" supplémentaires

  • getLanguageStopWordsSet(...)

 

13. MailPolicyFilter

13.1 Présentation

  • Objectifs
    • Contrôler le mail sortant (suivi, modification, rejet).
    • Possibilité d'agir selon le contexte d'envoi (notification, alerte workflow, ...).
  • Exemples d'usage
    • Ajout d'une signature particulière à tous les mails
    • Contrôle du contenu des envois "à un ami"
    • Ajout d'un header
    • Rejet des mails
    • Log
  • Version de JCMS
    • JCMS 6.0 SP1
  • Documentation

13.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<policyfilter class="com.example.MyMailPolicyFilter"/>
...
</plugincomponents>

Classe Java

public class MyMailPolicyFilter extends BasicMailPolicyFilter {

@Override
public boolean beforeSendMail(MailMessage msg, HashMap<String, Object> ctxt) {
// ...
}

@Override
public void afterSendMail(MailMessage msg, HashMap<String, Object> ctxt) {
// ...
}

}

13.3 Exemple

public class MyPolicyFilter extends BasicMailPolicyFilter {

@Override
public boolean beforeSendMail(MailMessage msg, HashMap<String, Object> ctxt) {
// cancel notification mail sent to admin
if ("notification".equals(msg.getOrigin()) &&
msg.getToMemberSet().contains(channel.getDefaultAdmin())) {
return false;
}
return true;
}

@Override
public void afterSendMail(MailMessage msg, HashMap<String, Object> ctxt) {
logger.info(msg + " sent in " + Util.formatDuration(msg.getDuration()));
return;
}

}

 

14. MemberQueryFilter

14.1 Présentation

  • Objectifs
    • Agir sur toutes les recherches portant sur les membres qu'il s'agisse d'une recherche explicite de l'utilisateur (p. ex. dans la portlet Annuaire), dans les interfaces de sélection ou lors de l'auto-complétion.
    • Agir en aval de la recherche sur les paramètres du MemberQueryHandler (méthodes filterMemberQueryHandler()) et en amont sur les résultats (méthodes filterResultSet()).
  • Exemples d'usage
    • Ajout dynamique de paramètres d'affinement (p. ex des groupes) selon le contexte de la recherche
    • Extension de la recherche à d'autres critères (p. ex. le module ESN étend la recherche aux informations déclarées dans le profile (expertises, postes, formations, ...))
    • Restriction des membres sélectionnables pour un membre donné
  • Version de JCMS
    • JCMS 6.1
  • Documentation

14.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<policyfilter class="com.example.MyMemberQueryFilter"/>.
...
</plugincomponents>

Classe Java

public class MyMemberQueryFilter extends BasicMemberQueryFilter {

// ---------------------------------------------------------------
// MemberQueryHandler
// ---------------------------------------------------------------
@Override
public void filterMemberQueryHandler(MemberQueryHandler mqh, Map<String,Object> context) {
// ...
}

@Override
public Set<Member> filterResultSet(MemberQueryHandler mqh, Set<Member> set, Map<String,Object> context) {
// ...
}

// ---------------------------------------------------------------
// DBMemberQueryHandler
// ---------------------------------------------------------------
@Override
public void filterMemberQueryHandler(DBMemberQueryHandler dbmqh, Map<String,Object> context) {
// ...
}

@Override
public PageResult<DBMember> filterPageResult(DBMemberQueryHandler dbmqh, PageResult<DBMember> pr, Map<String,Object> context) {
// ...
}

@Override
public List<String> filterResultList(DBMemberQueryHandler dbmqh, List<String> list, Map<String,Object> context) {
...
}

// ---------------------------------------------------------------
// AllMemberQueryHandler
// ---------------------------------------------------------------
@Override
public QueryHandler filterMemberQueryHandler(AllMemberQueryHandler dbmqh, Map<String,Object> context) {
// ...
}

@Override
public PageResult<Member> filterPageResult(AllMemberQueryHandler amqh, PageResult<Member> pr, Map<String,Object> context) {
// ...
}

@Override
public List<String> filterResultList(AllMemberQueryHandler amqh, List<String> list, Map<String,Object> context) {
...
}


}

 

15. PluginPolicyFilter

15.1 Présentation

  • Objectifs
    • Intervenir dans le cycle de vie des modules : initialisation, déploiement et suppression.
  • Exemples d'usage
    • Compléter le déploiement d'un module
    • Effectuer une désinstallation plus fine d'un module
  • Version de JCMS
    • JCMS 5.7
  • Documentation

15.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<policyfilter class="MyPluginPolicyFilter" />
...
</plugincomponents>

Classe Java

public class MyPluginPolicyFilter extends BasicPluginPolicyFilter {

@Override
public void setupPlugin(Plugin plugin) {
// ...
}

@Override
public void deployPlugin(Plugin plugin, String archiveName) {
// ...
}

@Override
public void uninstallPlugin(Plugin plugin) {
// ...
}
}

 

16. PortalPolicyFilter

16.1 Présentation

  • Objectifs
    • Contrôler la mécanique du portail
    • Filtrer les redirections
    • Modifier les permaliens et les URL descriptives
    • Modifier les header JavaScript et CSS
    • Filtrer la méthode Data.getFieldValue()
  • Exemples d'usage
    • Filtrer les paramètres de la requête avant la résolution du portail
    • Changer le résultat de la résolution du portail
      • Finement dans la mécanique
      • Globalement à la fin
    • Ajouter des feuilles de style
    • Changer le texte des permaliens
    • Changer les URLs descriptives pour ne plus afficher d'identifiant (requiert l'évolution JCMS-2073 introduite dans JCMS 6.1.1)
  • Version de JCMS
    • JCMS 5.7
  • Documentation

16.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<policyfilter class="com.example.MyPortalPolicyFilter" />
...
</plugincomponents>

 

Classe Java :

 

Filtrer les paramètres de la requête avant la mécanique du portail

  public void filterDisplayContext(PortalManager.DisplayContextParameters dcp){
// ...
}

 

Filtrer le résultat calculé par la mécanique du portail.

  • Peut être null si sendForbidden()
  • Les redirections ne sont pas encore exécutées.
  public void checkDisplayContext(DisplayContext context){
// ...
}

 

Modifier l'URL de redirection dans le cas d'un Portail de Redirection

  public String checkRedirect(final String redirectUrl, final PortalRedirect redirect, final DisplayContext context, final Member loggedMember){
// ...
}

 

Modifier le permalien d'une donnée

  public String checkPermalink(final String permalink, final Data data){
// ...
}

 

Modifier le comportement des méthodes "génériques" d'accès aux champs de publication

  public Object getFieldValue(final JcmsJspContext ctxt, final String fieldName, final Data data, final Object computedValue){
// ...
}
public int getIntFieldValue(final JcmsJspContext ctxt, final String fieldName, final Data data, final int computedValue){
// ...
}
public long getLongFieldValue(final JcmsJspContext ctxt, final String fieldName, final Data data, final long computedValue){
// ...
}
public double getDoubleFieldValue(final JcmsJspContext ctxt, final String fieldName, final Data data, final double computedValue){
// ...
}
public boolean getBooleanFieldValue(final JcmsJspContext ctxt, final String fieldName, final Data data, final boolean computedValue){
// ...
}
public TreeSet<Category> getCategoryFieldValue(final JcmsJspContext ctxt, final String fieldName, final Data data, final TreeSet<Category> computedValue){
// ...
}

Modifier les entête HTML (JavaScript et CSS)

  public void initHeaders(Map header, final String key, final JcmsJspContext context){
// ...
}
public void setupHeaders(Map header, final String key, final JcmsJspContext context){
// ...
}
public void initJavaScriptSet(Set<String> jsSet, final JcmsJspContext context){
// ...
}
public void initJavaScriptCodeSet(Set<String> jsCodeSet, final JcmsJspContext context){
// ...
}

 

16.3 Exemple

Dans cet exemple, on modifie les URLs descriptives (génération et résolution) pour obtenir des URLs sans identifiant. Attention ! pour un usage en conditions réelles, le code est à modifier pour assurer un stockage en base et à compléter avec un StoreListener pour mettre à jour à la suppression d'une donnée. Cet exemple requiert JCMS 6.1 SP1. Consultez l'évolution JCMS-2073 pour plus d'information à ce sujet.

public class NoIdUrlPortalPolicyFilter extends BasicPortalPolicyFitler { 
// Internal path <=> id resolution
// MUST BE STORED IN DATABASE FOR REAL USE
private HashMap<String,String> pathToIdMap = new HashMap<String,String>(); // "/jcms/my-article" => "article_id"
private HashMap<String,String> idAndLocaleToDisplayUrlMap = new HashMap<String,String>(); // "article_id.FR-FR" => "my-article"

@Override
public String getDescriptiveURLPath(Data data, Locale locale) {
String idAndLocale = data.getId() + "." + locale; // key for cache hashmap
String customPath = idAndLocaleToDisplayUrlMap.get(idAndLocale);

// not yet any custom display URL for this Data and Locale, generate One
if (customPath == null) {
// Use suffix (with counter) to prevent collision with other Data
String suffix = "";
for (int counter = 1; true; counter++) {
String curPath = DescriptiveURLs.getDescriptiveURLText(data, locale) + suffix;
String curFullPath = "/" + DescriptiveURLs.getServletPath() + curPath;
String existingId = pathToIdMap.get(curFullPath);
if (existingId == null || existingId.equals(data.getId())) {
pathToIdMap.put(curFullPath, data.getId());
idAndLocaleToDisplayUrlMap.put(idAndLocale, curPath);
customPath = curPath;
break;
}
suffix = "-" + counter;
}
}

return customPath;
}

@Override
public String getDescriptiveURLId(String descriptiveURL, String id) {
// Comment the following condition to completely replace native descriptive url /jcms/{id}/foobar with your logic
if (id != null) {
return id;
}

String myId = pathToIdMap.get(descriptiveURL);
return myId;
}
}

17. QueryFilter

17.1 Présentation

  • Objectifs
    • Agir sur toutes les recherches portant sur les publications qu'il s'agisse d'une recherche explicite de l'utilisateur (en front-office ou back-office) ou d'une recherche d'une portlet (p. ex. Portlet Requête/Itération).
    • Agir en aval de la recherche sur les paramètres du QueryHandler (méthode filterQueryHandler()) et en amont sur les résultats (méthode filterResultSet()).
  • Exemples d'usage
    • Ouverture de la recherche sur des sources externes (e.g. Base de données, LotusNotes, Amazon, ...)
    • Ajout dynamique de paramètres d'affinement (p. ex des catégories) selon le contexte de la recherche (p. ex. PDA, adresse IP, ...)
    • Ajout de nouveaux critères de recherche (e.g. géo-localisation)
  • Version de JCMS
    • JCMS 5.0
  • Documentation

17.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<queryfilter class="com.example.MyQueryFilter" />
...
</plugincomponents>

Classe Java

public class MyQueryFilter extends QueryFilter {
  @Override
  public QueryHandler filterQueryHandler(QueryHandler qh, Map context) {
    // ...
  }
 
  @Override
  public QueryResultSet filterResultSet(QueryHandler qh, QueryResultSet set, Map context) {
    // ...
  }
}

18. RightPolicyFilter

18.1 Présentation

  • Objectifs
    • La RightPolicyFilter permet d'adapter ou de modifier une partie du système de droits de JCMS :
      • Droit de consultation des publications
      • Droit de consultation des catégories
      • Droits de contribution
      • Droits de gestion et d'utilisation des catégories
      • Droit de dépôt de fichier
      • Contrôle de contenu HTML
  • Exemples d'usage
    • Restreindre l'accès à certains contenus aux utilisateurs externes (adresse IP)
    • Restreindre l'accès à certains contenus pour les navigateurs mobiles
    • Asservir les droits de validation en fonction des droits de gestion des catégories
    • Interdire certaines balises (e.g. applet, javascript, ...) dans les champs wysiwyg
    • Contrôle anti-virus lors du dépôt d'un document
  • Version de JCMS
    • JCMS 5.7 (présent depuis JCMS 5 en tant que classe du package custom)
  • Documentation

18.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<policyfilter class="com.example.MyRightPolicyFilter" />
...
</plugincomponents>

Classe Java

public class MyRightPolicyFilter extends BasicRightPolicyFilter {

  @Override
  public boolean canBeReadBy(boolean isAuthorized, Publication pub, Member mbr, boolean searchInGroups) {
    // ...
  }

  @Override
  public boolean canBeReadBy(boolean isAuthorized, Publication pub, Group grp) {
    // ...
  }

  @Override
  public boolean canBeReadBy(boolean isAuthorized, Category cat, Member mbr, boolean searchInGroups, boolean checkAncestors) {
    // ...
    return false;
  }

  @Override
  public boolean canBeReadBy(boolean isAuthorized, Category cat, Group grp, boolean checkAncestors) {
    // ...
  }

  @Override
  public boolean canCreateWorkspace(boolean isAuthorized, Member mbr, Workspace model) {
    // ...
  }

  @Override
  public boolean canDeleteOther(boolean isAuthorized, Member mbr, Data data) {
    // ...
  }

  @Override
  public boolean canDeleteOther(boolean isAuthorized, Member mbr, Class clazz, Workspace ws) {
    // ...
  }

  @Override
 public boolean canManageCategory(boolean isAuthorized, Member mbr, Category cat, boolean searchInGroups, boolean searchInParent) {
    // ...
  }

  @Override
  public boolean canPublish(boolean isAuthorized, Member mbr, Class clazz, Set wsSet) {
    // ...
  }

  @Override
  public boolean canUpdateOther(boolean isAuthorized, Member mbr, Data data) {
    // ...
  }

  @Override
  public boolean canUpdateOther(boolean isAuthorized, Member mbr, Class clazz, Workspace ws) {
    // ...
  }

  @Override
  public boolean canUseCategory(boolean isAuthorized, Member mbr, Category cat, boolean searchInGroups, boolean searchInParent) {
    // ...
  }

  @Override
  public boolean canWorkOn(boolean isAuthorized, Publication pub, Member member) {
    // ...
  }

  @Override
  public ControllerStatus canWorkOn(ControllerStatus status, int op, Member mbr, Member member) {
    // ...
  }

  @Override
  public boolean checkAfterUpload(DocUploadInfo info) {
    // ...
  }

  @Override
  public boolean checkBeforeUpload(String fieldName, String contentType, String fileName) {
    // ...
  }

  @Override
  public ControllerStatus checkHtml(String str, String field) {
    // ...
  }

  @Override
  public boolean isWorker(boolean isWorker, Member member, Workspace ws) {
    // ...
  }

}

18.3 Exemple

Voir les exemples contenus dans l'article JCMS 5.7 : Personnalisation de la gestion des droits.

19. StatPolicyFilter

19.1 Présentation

  • Objectifs
    • Changer le comportement de l'analyse des statistiques de JCMS en agissant a différents moments.
  • Exemple d'usage
    • Encapsuler plusieurs StatListener. (cf. DualMetricsStatPolicyFilter)
    • Filtrer certaines lignes de statistiques
    • Changer le contenu de certaines lignes de statistiques
    • Générer plusieurs rapports
  • Version de JCMS
    • JCMS 5.7
  • Documentation

19.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<policyfilter class="com.example.MyStatPolicyFilter"/>
...
</plugincomponents>

Classe Java

public class MyStatPolicyFilter extends BasicStatPolicyFilter {
@override
public void initListener(AbstractStatListener listener) {
// ...
}

@override
public void checkEndOfStatEntries(AbstractStatFieldListener listener, Map workspaceMap) {
// ...
}

@override
public boolean checkBeforeValidateEntry(final AbstractStatFieldListener listener, final StatEntry entry, final boolean jcms) {
// ...
}

@override
public boolean checkAfterValidateEntry(final AbstractStatFieldListener listener, final StatEntry entry, final boolean jcms) {
// ...
}

@override
public void checkProcessEntry(Map workspaceMap, final AbstractStatFieldListener listener, final StatEntry entry, final Object workspace) {
// ...
}

@override
public void checkGeneratedReports(Map jspMap, final StatReport report, final Member member) {
// ...
}

@override
public StatListener createStatListener(final PortletStat portlet, final PortalElement report, final StatListener listener) {
// ...
}

@override
public StatListener checkCreateStatListener(final PortletStat portlet, final PortalElement report, final StatListener listener) {
// ...
}
}
  • initListener(), createStatListener() et checkCreateStatListener()
    • Permet de configurer le StatListener et d'ajouter d'autres listeners pour filtrer plus finement les lignes de statistiques.
    • La methode createStatListener() permet d'encapsuler le listener
  • checkEndOfStatEntries()
    • Une methode callback permettant de traiter la fin de l'analyse. Par exemple, pour enregistrer des calculs intermédiaires.
  • checkBeforeValidateEntry() et checkAfterValidateEntry()
    • Permet de valider l'objet StatEntry avant et après analyse de JCMS
  • checkProcessEntry()
    • Permet de traiter l'objet StatEntry après validation pour stocker des calculs intermédiaires
  • checkGeneratedReports()
    • Permet de remplir une Map avec toutes les JSP à exécuter pour chaque rapport. Par exemple pour générer un rapport en html , en csv, en texte, ... La clé de la JSP est passée en attribut de session.

20. StoreListener

20.1 Présentation

  • Objectifs
    • Déclencher un traitement :
      • après une opération d'écriture
      • lors de l'intégration d'une opération reçue par JSync
      • au démarrage de JCMS lors de la lecture du store
  • Exemples d'usage
    • Gestion d'index sur les données
    • Envoi de mail
  • Version de JCMS
    • Toute version
  • Documentation

20.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<storelistener class="com.example.MyStoreListener" types="Member Article PortletSearch" beforeStoreLoad="false" repeat="true" />
...
</plugincomponents>

Remarques :

  • L'attribut beforeStoreLoad détermine si le StoreListener doit être appelé durant le chargement du store (true), ou uniquement après celui-ci (false).
  • Dans un environnement répliqué par JSync, l'attribut repeat détermine si le StoreListener doit être déclenché sur tous les réplicas ou uniquement sur le réplica où l'opération d'écriture a eu lieu. A noter que dans ce dernier cas, il généralement préférable d'utiliser un DataController.

Classe Java

public class MyStoreListener extends BasicStoreListener {

@Override
public void handleCreate(Storable storable, boolean firstTime) {
// ...
}

@Override
public void handlePrepareUpdate(Storable storable, Map attributes, boolean firstTime) {
// ...
}

@Override
public void handleCommitUpdate(Storable storable, Storable oldStorable, boolean firstTime) {
// ...
}
@Override
public void handleDelete(Storable storable, boolean firstTime) {
// ...
}
}

Remarques :

  • En dérivant de BasicDBListenerStoreListener il est possible d'être à la fois un StoreListener et un DBListener.
  • Dans un environnement répliqué avec JSync, si le StoreListener doit être déclenché que sur un seul réplica (p. ex. envoi d'un mail) il est recommandé que ce soit sur le leader. Dans ce cas, lors de la déclaration dans plugin.xml on positionnera l'attribut repeat à true et on testera dans le StoreListener la méthode channel.isMainLeader().

 

21. TemplatePolicyFilter

21.1 Présentation

  • Objectifs
    • Gérer la liste des fichiers de CSS proposés lors de l'édition d'un portail
    • Gérer les classes et styles CSS des Portlets
    • Gérer les conditions d'affichage de portlet
    • Gérer les gabarits d'affichage d'une publication
  • Exemples d'usages
    • Choisir une feuille CSS selon le contexte de navigation
    • Masquer une portlet selon le contexte de navigation
    • Choisir un gabarit d'une publication selon le contexte d'affichage
  • Documentation

21.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<policyfilter class="com.example.MyTemplatePolicyFilter" />
...
</plugincomponents>

Classe Java

public class MyTemplatePolicyFilter extends BasicTemplatePolicyFilter {

@override
public TypeTemplateEntry getTemplateEntry(String usage, Data data, final TypeTemplateEntry tte) {
// ...
}

@override
public TypeTemplateEntry getTemplateEntry(String usage, Class<? extends Data> dataClass, final Workspace ws, final TypeTemplateEntry tte) {
// ...
}

@override
public String getTemplateUsage(final Data data, final String usage) {
// ...
}

@override
public String getTemplateUsage(final Class<?> pubClass, final String usage) {
// ...
}

@override
public String getInnerClasses(final PortalElement portlet) {
// ...
}

@override
public String getOutterClasses(final PortalElement portlet) {
// ...
}

@override
public String getInnerStyles(final PortalElement portlet) {
// ...
}

@override
public String getOutterStyles(final PortalElement portlet) {
// ...
}

@override
public void getCssFiles(List<String> jcmsChoice) {
// ...
}

@override
public String[] getConditionLabels(final String[] labels, final Class<? extends PortalElement> portlet, final String userLang) {
// ...
}

@override
public String[] getConditionValues(final String[] values, final Class<? extends PortalElement> portlet) {
// ...
}

@override
public void handleCondition(final String[] conditions) {
// ...
}
}

21.3 Exemples

21.3.1 CSS de Portail

La methode getCssFiles() permet de définir la liste des fichiers de CSS proposés à l'utilisateur lors de l'édition d'un portail. Cette liste est composée des fichiers déclarés dans css/portal/*.css et plugins/MyPlugin/css/portal/*.css.

  • Il est possible de restreindre cette liste en fonction du loggedMember
  • Ou de rajouter des fichiers déclarés par ailleurs

Par exemple, il est possible de définir des CSS de jeu de couleur, proposées à l'utilisateur (red.css, green.css, ...)

21.3.2 CSS des Portlets

Les méthodes getInnerClasses(), getOutterClasses(), getInnerStyles() et getOutterStyles() permettent de rajouter des Classes et des Styles à la mécanique des Portlets. Attention ! cela ne fonctionne que si les habillages (skin) sont correctement écrits :

<%@ page import="com.jalios.util.*, com.jalios.jcms.*, com.jalios.jcms.portlet.*, com.jalios.jcms.context.JcmsJspContext" %><%
JcmsJspContext jcmsContext = (JcmsJspContext)request.getAttribute("jcmsContext");
PortalElement portlet = (PortalElement) request.getAttribute("PortalElement");
String userLang = Util.getString(request.getAttribute("userLang"), Channel.getChannel().getLanguage()); // May include doInitPage.jsp
String idName = "id='"+ Util.getString(portlet.getCssId(), ServletUtil.generateUniqueDOMId(request,"layout")) +"'";
String styleOutter = PortalManager.getOutterStyles(portlet).trim();
String styleInner = PortalManager.getInnerStyles(portlet).trim();
String classOutter = PortalManager.getOutterClasses(portlet).trim();
String classInner = PortalManager.getInnerClasses(portlet).trim();
%>

<div style="<%= styleOutter %>" <%= idName %>>
<a href="https://community.jalios.com/jcms/jx_64101/fr/catalogue-des-points-de-debranchement-hooks-disponibles-dans-l-api-jcms#"> <%= Util.getString(((PortletSkinable)portlet).getDisplayTitle(userLang),portlet.getTitle(userLang)) %></a>
<div style="<%= styleInner %>"><%@ include file='/jcore/portal/doIncludePortletTemplate.jsp' %></div></div>

Par exemple, il est possible de définir 2 outer classes "ajax-refresh-lazy ajax-refresh-periodical-5" pour rafraichir automatiquement certaines portlet toutes les 5 secondes.

21.3.3 Conditions d'affichage

Les méthodes getConditionLabels(), getConditionValues() et handleCondition() permettent l'ajout et la validation de condition d'affichage de portlet.

Par exemple, il est possible de définir une condition "IE6 only" limitant aux utilisateur d'IE6 l'affichage d'une portlet vantant les mérites des navigateurs modernes.

21.3.4 Choix des gabarits

Les methods getTemplateUsage() permettent de changer l'usage pour un type ou une instance. Par exemple il est possible de transformer un usage query ou box en queryIPhone ou boxIPhone dans un contexte iPhone.

Les méthodes getTemplateEntry() retournent un TypeTemplateEntry en fonction d'une instance, d'un type et d'un espace de travail. Par exemple

  • pour surcharger dynamiquement une déclaration de template.
  • pour fournir un template à une donnée non persistée dans la base.

Note: La methode ResourceHelper.getDefaultTemplate() calcule le gabarit en fonction des propriétés:

  • jcms.resource.default-skin
  • jcms.resource.default-template
  • jcms.resource.default-template.query
  • jcms.resource.default-template.box

 

22. ThumbnailPolicyFilter

22.1 Présentations

  • Objectifs
    • Générer des images d'aperçus pour n'importe quel type de fichier
  • Exemples d'usage
    • Génération d'aperçus pour des formats de fichiers spécifiques (audio, 3D, ...)
    • Module de génération d'aperçu basé sur l'utilisation d'application native à l'OS
  • Version de JCMS
    • JCMS 5.5
  • Documentation

22.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<policyfilter class="com.example.MyThumbnailPolicyFilter" />
...
</plugincomponents>

Classe Java

public class MyThumbnailPolicyFilter extends BasicThumbnailPolicyFilter {
@Override
public boolean supportsThumbnail(FileDocument doc, boolean jcms) {
// ...
}

@Override
public boolean createThumbnail(FileDocument doc, File dest, ImageFormat format, int maxWidth, int maxHeight, String background, boolean done) {
// ...
}

@Override
public boolean createThumbnail(FileDocument doc, File dest, ImageFormat format, int maxWidth, int maxHeight, boolean done) {
// ...
}

}

 

23. WebdavPolicyFilter

23.1 Présentation

  • Objectifs
    • Intervenir sur le fonctionnement de WebDAV pour filtrer certaines ressources afin de ne pas les présenter au client WebDAV et de ne pas les inclure dans JCMS.
  • Exemples d'usage
    • Masquer des fichiers d'un certain type
    • Exclure de JCMS les fichiers temporaires créés par certain clients WebDAV
  • Version de JCMS
    • JCMS 5.7
  • Documentation

23.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<policyfilter class="com.example.MyWebdavPolicyFilter"/>
...
</plugincomponents>

Classe Java

public class MyWebdavPolicyFilter extends BasicWebdavPolicyFilter {

@Override
public boolean silentFilterResource(final boolean jcms, final WebdavResource res, final WebdavContext ctxt){
// ...
}

24. WidgetPolicyFilter

24.1 Présentation

  • Objectif
    • Intervenir lors de la génération des widget:
      • updateCSS() : permet de modifier les classes CSS d'un widget
      • getTreeCatNodeExtraContent() : permet de remplacer/modifier le code généré des noeuds d'un TreeCat
  • Exemple d'usage
    • Présentation personnalisé d'un widget
    • Ajout d'icône dans l'arbre des catégories
  • Version de JCMS
    • JCMS 5.7
  • Documentation

24.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<policyfilter class="com.example.MyWidgetPolicyFilter" />
...
</plugincomponents>

Classe Java

public class MyWidgetPolicyFilter extends BasicWidgetPolicyFilter {

@Override
public String updateCSS(final String css, final AbstractWidget widget){
// ...
}

@Override
public String getTreeCatNodeExtraContent(final TreeCat treecat, final String extraContent,final Category cat, final int level, final int pubcount){
// ...
}

 

25. WikiPolicyFilter

25.1 Présentation

  • Objectifs
    • Agir en amont et en aval du processus de rendu wiki
    • filtrage et/ou enrichissement du contenu wiki
    • filtrage et/ou enrichissement du contenu HTML produit
  • Exemples d'usages
    • Traitement de nouvelles balises Wiki
    • Rendu non HTML
  • Version de JCMS
    • JCMS 5.7
  • Documentation

25.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<policyfilter class="com.example.MyWikiPolicyFilter" />
...
</plugincomponents>

Classe Java

public class MyWikiPolicyFilter extends BasicWikiPolicyFilter {

@Override
public String beforeRendering(final String text, final Locale userLocale, final WikiRenderingHints hints){
// ...
}

@Override
public String afterRendering(final String text, final Locale userLocale, final WikiRenderingHints hints){
// ...
}
}

 

26. WizardPolicyFilter

26.1 Présentation

  • Objectifs
    • Modifier le comportement de la création d'Espace de travail ou de Portail via l'interface du Wizard.
  • Exemples d'usage
    • Modification du paramétrage des portlets copiées
  • Version de JCMS
    • JCMS 5.7
  • Documentation

26.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<policyfilter class="MyWizardPolicyFilter"/>
...
</plugincomponents>

Classe Java

public class MyWizardPolicyFilter extends BasicWizardPolicyFilter {

@Override
public boolean beforeWizard(WizardContext ctxt){
// ...
}

@Override
public void afterWizard(WizardContext ctxt){
// ...
}

@Override
public String handleCategoryName(final String computedName, final Category cat, final WizardContext ctxt){
// ...
}
}

26.3 Exemple

Mise à jour de liens spécifiques :

public class CustomWizardPolicyFilter extends BasicWizardPolicyFilter {

// @Override
public void afterWizard(WizardContext ctx) {

// Skip other context
if (!(ctx instanceof WorkspaceWizardContext)){ return; }

WorkspaceWizardContext ctxt = (WorkspaceWizardContext) ctx;

NDC.push("[CustomWizardPolicyFilter]");
try {

Map pubMap = new HashMap(ctxt.getPublicationMap());
for(Iterator it = pubMap.values().iterator() ; it.hasNext() ; ){
Publication itPub = (Publication) it.next();

if (!(itPub instanceof PortalRedirect ||
itPub instanceof PortletQueryForeach ||
itPub instanceof PortletCalendar)){
continue;
}

Publication itCopy = itPub.getClass().getConstructor(new Class[]{itPub.getClass()}).newInstance(new Object[]{itPub});
boolean update = false;

if (itPub instanceof PortalRedirect){
update = bindPortalRedirect((PortalRedirect)itPub, (PortalRedirect)itCopy, ctxt);
} else if (itPub instanceof PortletQueryForeach){
update = bindPortletQueryForeach((PortletQueryForeach)itPub, (PortletQueryForeach)itCopy, ctxt);
} else if (itPub instanceof PortletCalendar){
update = bindPortletCalendar((PortletCalendar)itPub, (PortletCalendar)itCopy, ctxt);
}

if (!update){
continue;
}

if (itCopy.checkUpdate(ctxt.getAuthor(), ctxt.getDataControllerContext()).isOK()){
itCopy.performUpdate(ctxt.getAuthor(), ctxt.getDataControllerContext());
}
}
} catch (Exception ex){ logger.warn(ex.getMessage(), ex); }
finally { NDC.pop(); }
}

protected boolean bindPortalRedirect(PortalRedirect portlet , PortalRedirect copy, WorkspaceWizardContext ctxt) throws Exception {
Category cat = Channel.getChannel().getCategory(portlet.getCategory());
boolean update = false;

// Fix redirect categories
Category copyCat = (Category) ctxt.getCategoryMap().get(cat);
if (copyCat != null){
copy.setCategory(copyCat.getId());
update = true;
}

// Fix redirect Portlet
PortalElement redirect = portlet.getRedirectPortlet();
PortalElement copyRedirect = (PortalElement) getDuplicate(redirect, ctxt);

if (copyRedirect == null){ return update; }

copy.setRedirectPortlet(copyRedirect);
return true;
}
}

27. WysiwygPolicyFilter

27.1 Présentation

  • Objectifs
    • Intervenir sur le contenu wysiwyg (HTML) au moment de son écriture dans la page HTML ou dans les mails HTML.
  • Exemples d'usage
    • Création automatique d'une table des matières à partir des éléments H1, H2, ...
    • Remplacement des liens vers médias (vidéos/image) par une galerie de présentation
    • Conversion de formules mathématiques en image
    • Insertion de javascript pour fonctionnalités avancées
  • Version de JCMS
    • JCMS 5.7.0
  • Documentation

27.2 Déclaration

Dans plugin.xml

<plugincomponents>
...
<policyfilter class="com.example.MyWysiwygPolicyFilter" />
...
</plugincomponents>

Classe Java

public class MyWysiwygPolicyFilter extends BasicWysiwygPolicyFilter {

@Override
public String beforeRendering(final String text, final Locale userLocale) {
// ...
}

@Override
public String afterRendering(final String text, final Locale userLocale) {
// ...
}
}

28. Classes Custom

Dans JCMS, plusieurs classes sont livrées avec leur code source. Elles se situent dans le package custom.

28.1 LuceneSearchEnginePolicy

Cette classe permet des modifications plus avancées que le hook LuceneSearchEnginePolicyFilter.

Exemple :

  • Ajout de synonymes via un custom TokenFilter dans l'analyzer par défaut (méthode CustomAnalyzer.filterTokenStream)
  • Implémentation d'une recherche par sonorité via un custom TokenFilter dans l'analyzer par défaut
  • Modification du comportement de recherche sur les nombres et séparateurs spéciaux et autres signes de ponctuations (-_)
  • Modification du fonctionnement de la troncature droite
  • Calcul de la pertinence des publications à partir des résultats issus des catégories via getPublicationNewScore(...)

28.2 LdapAuthenticationHandler

Objectifs

La classe LdapAuthenticationHandler est un AuthenticationHandler qui se charge d'effectuer l'authentification des membres auprès du serveur LDAP ainsi que leur synchronisation avec le serveur LDAP.
Cette classe est invoquée dans plusieurs circonstances :

  • Lors de la connexion d'un membre pour son authentification et sa synchronisation
  • Lors de la synchronisation d'un groupe ou d'un membre depuis le back office (opération effectuée par un administrateur)

Le fichier source de la classe custom.LdapAuthenticationHandler est volontairement fourni avec JCMS pour permettre des développements avancés lors de la synchronisation des données d'un membre ou d'un groupe avec le LDAP.

Exemples d'usage

  • Modification des catégories d'audiencement d'un membre en fonction de groupes spécifiques du LDAP
  • Ajout d'extradata pour la synchronisation de champs supplémentaires
  • ...

Pour plus de documentation sur les API LDAP utilisées dans JCMS :

28.3 SpellChecker

28.3.1 Présentation

  • Objectifs
    • Utilisation d'un correcteur orthographique différent de celui fourni en standard (XMLmind SpellChecker)
  • Exemple d'usage
    • Google Spell Checker
    • Microsoft Office
    • OpenOffice
  • Version de JCMS
    • JCMS 6
  • Documentation

28.3.3 Déclaration

Via une propriété (e.g dans plugin.prop) :

spellchecker.class: com.mycompany.jcmsplugin.spellchecker.MySpellChecker

Ou depuis du code :

  SpellChecker mySpellChecker = ...
SpellCheckerManager.setSpellChecker(mySpellChecker);

28.3.4 Exemple

Google SpellChecker API (non officielle, pourrait ne plus fonctionner)

public class GoogleSpellChecker implements SpellChecker{
public static final String REVISION = "$Revision$";

private static final Logger logger = Logger.getLogger(XMLmindSpellChecker.class);
private static final Channel channel = Channel.getChannel();

private List<String> languageList = new ArrayList<String>();

public GoogleSpellChecker() {
languageList = Util.splitToList(channel.getProperty("spellchecker.google.languages", ""), ",");
}

// ------------------------------------------------------------------------
// SpellChecker interface
// ------------------------------------------------------------------------

/**
* Returns a list of available languages for spell-checking.
* @return a List of ISO-639 language code
*/
@Override
public List<String> getLanguageList() {
return languageList;
}

/**
* Spell-check the specified text in the specified language
* and return a list of SpellCheckResult.
*
* @param text the text to check
* @param lang the language of the text (ISO-639 code), never null or empty
* @return a List of SpellCheckResult
*/
@Override
public List<SpellCheckResult> spellCheck(String text, String lang) {
InputStream in = null;
try {
// Format the XML that needs to be send to Google Spell Checker.
StringBuffer requestXML = new StringBuffer();
requestXML.append("<spellrequest textalreadyclipped=\"0\" ignoredups=\"1\" ignoredigits=\"1\" ignoreallcaps=\"0\"><text>");
requestXML.append(XmlUtil.normalize(text));
requestXML.append("</text></spellrequest>");

// The Google Spell Checker URL
URL url = new URL("https://www.google.com/tbproxy/spell?lang=" + lang + "&hl=" + lang);
URLConnection conn = url.openConnection();
conn.setDoOutput(true);

OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
out.write(requestXML.toString());
out.close();

// Get the result from Google Spell Checker
in = conn.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
return parseResponse(text, br);
}
catch (Exception ex) {
logger.warn("Could not contact google spellchecker", ex);
} finally {
IOUtils.closeQuietly(in);
}
return new ArrayList<SpellCheckResult>();
}

private List<SpellCheckResult> parseResponse(String text, BufferedReader reader) {
ArrayList<SpellCheckResult> resultList = new ArrayList<SpellCheckResult>();
Document doc = null;
try {
doc = XmlUtil.getDocument(reader);

List<Element> childrenList = doc.getRootElement().getChildren("c");
for (Element elt : childrenList) {
int startIdx = Util.toInt(elt.getAttributeValue("o"), -1);
int length = Util.toInt(elt.getAttributeValue("l"), -1);
if (startIdx == -1 || length == -1) {
continue;
}
String word = text.substring(startIdx, startIdx + length);
List<String> suggestions = Util.splitToList(elt.getText(), "\t");
SpellCheckResult scResult = new SpellCheckResult(word, suggestions);
resultList.add(scResult);
}
} catch (Exception ex) {
logger.warn("Could not parse google spellchecker result", ex);
}
return resultList;
}

}

29. Targets

29.1 Présentation

  • Objectifs
    • Les targets sont des points d'insertions dans les JSP de JCMS. Elles permettent à des modules de venir insérer des éléments d'interface graphique.
    • Un module peut aussi offrir ses propres targets pour accueillir des éléments d'interfaces d'autres modules
  • Exemples d'usage
    • Ajout de menu dans le back-office
    • Ajout de composant dans les formulaires
    • Ajout d'information dans un gabarit d'affichage

29.2 Déclaration

Dans plugin.xml

<public-files>
...
<file path="jsp/myJSP' include="TARGET_NAME" />
...
</public-files>

29.3 Affichage des targets

Pour connaitre les targets disponibles dans JCMS, il suffit d'activer la fonction "Afficher les targets" présente dans la zone Développement de l'espace d'administration. Les zone d'insertions apparaissent alors dans toutes les interfaces de JCMS (uniquement pour la session de l'utilisateur).

jcms570-targets

En résumé...

Vous êtes perdus entre les DataController, les StoreListener, les QueryFilter, les AuthenticationHandler et autres PolicyFilter ? Cet article liste et explique tous les points de débranchement (hooks) disponibles dans JCMS.

Sujet
Produits
Publié

17/06/10

Rédacteur
  • Olivier Dedieu

Table des matières

  1. 2. AlarmListener
    1. 2.1 Présentation
    2. 2.2 Déclaration
  2. 3. AuthenticationHandler
    1. 3.1 Présentation
    2. 3.2 Déclaration
  3. 4. ChannelListener
    1. 4.1 Présentation
    2. 4.2 Déclaration
  4. 5. ChannelPolicyFilter
    1. 5.1 Présentation
    2. 5.2 Déclaration
  5. 6. CleanFilter
    1. 6.1 Présentation
    2. 6.2 Déclaration
    3. 6.3 Exemples
  6. 7. CtxMenuPolicyFilter
    1. 7.1 Présentations
    2. 7.2 Déclaration
    3. 7.3 Exemples
  7. 8. DataController
    1. 8.1 Présentation
    2. 8.2 Déclaration
  8. 9. DBListener
    1. 9.1 Présentation
    2. 9.2 Déclaration
  9. 10. ExportPolicyFilter
    1. 10.1 Présentation
    2. 10.2 Déclaration
  10. 11. ImportPolicyFilter
    1. 11.1 Présentation
    2. 11.2 Déclaration
  11. 12. LuceneSearchEnginePolicyFilter
    1. 12.1 Présentation
    2. 12.2 Déclaration
    3. 12.3 Exemples
  12. 13. MailPolicyFilter
    1. 13.1 Présentation
    2. 13.2 Déclaration
    3. 13.3 Exemple
  13. 14. MemberQueryFilter
    1. 14.1 Présentation
    2. 14.2 Déclaration
  14. 15. PluginPolicyFilter
    1. 15.1 Présentation
    2. 15.2 Déclaration
  15. 16. PortalPolicyFilter
    1. 16.1 Présentation
    2. 16.2 Déclaration
    3. 16.3 Exemple
  16. 17. QueryFilter
    1. 17.1 Présentation
    2. 17.2 Déclaration
  17. 18. RightPolicyFilter
    1. 18.1 Présentation
    2. 18.2 Déclaration
    3. 18.3 Exemple
  18. 19. StatPolicyFilter
    1. 19.1 Présentation
    2. 19.2 Déclaration
  19. 20. StoreListener
    1. 20.1 Présentation
    2. 20.2 Déclaration
  20. 21. TemplatePolicyFilter
    1. 21.1 Présentation
    2. 21.2 Déclaration
    3. 21.3 Exemples
  21. 22. ThumbnailPolicyFilter
    1. 22.1 Présentations
    2. 22.2 Déclaration
  22. 23. WebdavPolicyFilter
    1. 23.1 Présentation
    2. 23.2 Déclaration
  23. 24. WidgetPolicyFilter
    1. 24.1 Présentation
    2. 24.2 Déclaration
  24. 25. WikiPolicyFilter
    1. 25.1 Présentation
    2. 25.2 Déclaration
  25. 26. WizardPolicyFilter
    1. 26.1 Présentation
    2. 26.2 Déclaration
    3. 26.3 Exemple
  26. 27. WysiwygPolicyFilter
    1. 27.1 Présentation
    2. 27.2 Déclaration
  27. 28. Classes Custom
    1. 28.1 LuceneSearchEnginePolicy
    2. 28.2 LdapAuthenticationHandler
    3. 28.3 SpellChecker
  28. 29. Targets
    1. 29.1 Présentation
    2. 29.2 Déclaration
    3. 29.3 Affichage des targets