cancel
Showing results for 
Search instead for 
Did you mean: 

Make property strings appear in wizards

swithun
Champ in-the-making
Champ in-the-making
I'm developing a custom action that will be packaged as an AMP. I imagine that most of the time, this action will be run an automated rule, and not as a one-off action via a wizard. But it can be run via the Run action wizard, and it works.

The trouble is that I can't figure out how to get property strings (title, description, summary etc.) to be used in the wizard. Having picked the action from the menu, and clicked the Set Values and Add button, the summary box is empty. If I use the Next button instead of the Finish button, then the lack of strings results in an error, although using Finish works fine, as does running the action from a rule.

This is my directory structure:


.
|– build
|   |– classes
|   |   `– uk
|   |       `– ac
|   |           `– st_andrews
|   |               `– repo
|   |                   `– action
|   |                       `– executer
|   |                           `– AntivirusActionExecuter.class
|   |– dist
|   |   `– antivirus-action.amp
|   `– lib
|       `– antivirus-action.jar
|– build.xml
|– config
|   `– alfresco
|       `– module
|           `– antivirus-action
|               |– context
|               |   |– antivirus-action.properties
|               |   `– antivirus-action.xml
|               |– module-context.xml
|               |– module.properties
|               `– template
|                   `– virus_found.ftl
`– source
    `– java
        `– uk
            `– ac
                `– st_andrews
                    `– repo
                        `– action
                            `– executer
                                `– AntivirusActionExecuter.java

This is my module.properties file:

# MyModule module properties
module.id=antivirus-action
module.version=1.0
module.title=Antivirus Action
module.description=Integrates antivirus checking as an action in Alfresco

and this is my antivirus-action.properties file:

antivirus-action.title=Check files using antivirus software
antivirus-action.description=This will check file for viruses
antivirus-action.summary=This will check file for viruses
antivirus.exe=/usr/bin/clamdscan

I would like the last property to be picked up by the antivirus-action.xml bean file.

Can anyone see what I could be doing wrong? Are any of the files in the wrong location, or is there something wrong with my naming of things?

Thanks.
4 REPLIES 4

cristian
Champ in-the-making
Champ in-the-making
Have you tried changing antivirus-action.properties in webclient.properties ??

zaizi
Champ in-the-making
Champ in-the-making
You need to implement an Action Handler to provide the UI for your action executer. See http://wiki.alfresco.com/wiki/Custom_Action_UI#Implementing_the_action_handler.

Ainga

swithun
Champ in-the-making
Champ in-the-making
Thanks for the help. I now have an AMP that is working. For those who might find it helpful, this is my new directory structure prior to compiling the AMP:


.
|– build.xml
|– config
|   `– alfresco
|       `– module
|           `– antivirus-action
|               |– alfresco-global.properties
|               |– context
|               |   `– antivirus-action.xml
|               |– module-context.xml
|               |– module.properties
|               `– template
|                   `– virus_found.ftl
`– source
    `– uk
        `– ac
            `– st_andrews
                `– repo
                    `– action
                        `– executer
                            |– AntivirusActionExecuter.java
                            `– antivirus-action-messages.properties

This is the build.xml, based on the BasicAmpSample from the SDK.

<?xml version="1.0"?>
<project name="antivirus-action" default="package-amp" basedir=".">
  <property name="project.dir" value="."/>
  <property name="build.dir" value="${project.dir}/build"/>
  <property name="config.dir" value="${project.dir}/config"/>
  <property name="jar.file" value="${build.dir}/lib/antivirus-action.jar"/>
  <property name="amp.file" value="${build.dir}/dist/antivirus-action.amp"/>
 
  <property name="properties.files.tocopy" value="**/*.properties" />

  <target name="mkdirs">
    <mkdir dir="${build.dir}/dist" />
    <mkdir dir="${build.dir}/lib" />
  </target>
 
  <path id="class.path">
    <dirset dir="${build.dir}" />
    <fileset dir="../../lib/server" includes="**/*.jar"/>
  </path>
 
  <target name="compile">
    <mkdir dir="${build.dir}/classes" />
    <javac classpathref="class.path" srcdir="${project.dir}/source" destdir="${build.dir}/classes" />
    <copy todir="${build.dir}/classes">
      <fileset dir="${project.dir}/source" includes="${properties.files.tocopy}"/>
    </copy>
  </target>
 
  <target name="package-jar" depends="compile">
    <jar destfile="${jar.file}">
      <fileset dir="${build.dir}/classes" />
    </jar>
  </target>
 
  <target name="package-amp" depends="mkdirs, package-jar" description="Package the Module" >
    <zip destfile="${amp.file}" >
      <fileset dir="${build.dir}" includes="lib/*.jar" />
      <fileset dir="${project.dir}" includes="config/**/*.*" excludes="**/module.properties" />
      <fileset dir="${project.dir}/config/alfresco/module/antivirus-action" includes="module.properties" />
    </zip>
  </target>
 
  <target name="update-war" depends="package-amp" description="Update the WAR file.  Set -Dwar.file=…" >
    <echo>Installing Fits Action AMP into WAR</echo>
    <java dir="." fork="true" classname="org.alfresco.repo.module.tool.ModuleManagementTool">
      <classpath refid="class.path" />
      <arg line="install ${amp.file} ${war.file} -force -verbose"/>
    </java>
  </target>
</project>

I put the non-I18N strings into a file called alfresco-global.properties. The bean file core-services-context.xml will pick up any alfresco-global.properties files inside modules. Mine just contains:

antivirus.exe=/usr/bin/clamdscan
antivirus.mailer=some@email.address

The file module-context.xml points to my specific module bean file, antivirus-action.xml

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
  <import resource="classpath:alfresco/module/antivirus-action/context/antivirus-action.xml"/>
</beans>

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
  <!– this bean gets the I18N strings loaded –>
  <bean id="antivirus-action-messages" class="org.alfresco.i18n.ResourceBundleBootstrapComponent">
    <property name="resourceBundles">
      <list>
        <value>uk.ac.st_andrews.repo.action.executer.antivirus-action-messages</value>
      </list>
    </property>
  </bean>
  <bean id="antivirus-action" class="uk.ac.st_andrews.repo.action.executer.AntivirusActionExecuter" parent="action-executer">
    <property name="contentService">
      <ref bean="contentService" />
    </property>
    <property name="nodeService">
      <ref bean="nodeService" />
    </property>
    <property name="templateService">
      <ref bean="templateService" />
    </property>
    <property name="actionService">
      <ref bean="actionService" />
    </property>
    <property name="personService">
      <ref bean="personService" />
    </property>
    <property name="fromEmail">
      <value>${antivirus.mailer}</value>
    </property>
    <property name="command">
      <bean class="org.alfresco.util.exec.RuntimeExec">
        <property name="commandMap">
          <map>
            <entry key=".*" value="${antivirus.exe} ${source}"/>
          </map>
        </property>
        <property name="errorCodes">
          <value>1</value>
        </property>
      </bean>
    </property>
  </bean>
</beans>

The file module.properties is copied straight from BasicAmpSample. I created a simple Freemarker template to be used for the email message sent to creators of files which contain viruses:

The file (${filename}) you ingested into Alfresco contains a virus. This is
the output from the anti-virus software:

${message}

The file will be deleted.

Regards

Alfresco

The I18N strings go in antivirus-action-messages.properties:

antivirus-action.title=Antivirus scan
antivirus-action.description=This will check file for viruses
antivirus-action.summary=This will check file for viruses

and the Java class that uses all of the above stuff is:

package uk.ac.st_andrews.repo.action.executer;

import java.util.List;
import java.io.File;
import java.util.Map;
import java.util.HashMap;

import org.alfresco.model.ContentModel;

import org.alfresco.error.AlfrescoRuntimeException;

import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.action.ActionService;

import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
import org.alfresco.repo.action.executer.MailActionExecuter;

import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.TemplateService;

import org.alfresco.service.cmr.security.PersonService;

import org.alfresco.util.TempFileProvider;
import org.alfresco.util.exec.RuntimeExec;
import org.alfresco.util.exec.RuntimeExec.ExecutionResult;

/**
* action executer
*
* @author Swithun Crowe
*/
public class AntivirusActionExecuter extends ActionExecuterAbstractBase
{
   /**
    * Action constants
    */
   public static final String NAME = "antivirus-action";
   public static final String VAR_SOURCE = "source";
  
   private ContentService contentService;
   private NodeService nodeService;
   private TemplateService templateService;
   private ActionService actionService;
   private PersonService personService;

   private RuntimeExec command;
  
   private String fromEmail;
  
   /**
    * @param contentService The contentService to set.
    */
   public void setContentService(ContentService contentService)
     {
        this.contentService = contentService;
     }

   /**
    * @param nodeService The nodeService to set.
    */
   public void setNodeService(NodeService nodeService)
     {
        this.nodeService = nodeService;
     }

   /**
    * @param templateService The templateService to set.
    */
   public void setTemplateService(TemplateService templateService)
     {
        this.templateService = templateService;
     }

   /**
    * @param actionService The actionService to set.
    */
   public void setActionService(ActionService actionService)
     {
        this.actionService = actionService;
     }

   /**
    * @param personService The personService to set.
    */
   public void setPersonService(PersonService personService)
     {
        this.personService = personService;
     }
  
   /**
    * @param fromEmail The email address that messages are sent from
    */
   public void setFromEmail(String fromEmail)
     {
        this.fromEmail = fromEmail;
     }
  
   /**
    * @param command The antivirus command
    */
   public void setCommand(RuntimeExec command)
     {
        this.command = command;
     }
  
   @Override
   public void init()
       {
          super.init();
       }
  
   @Override
   protected void addParameterDefinitions(List<ParameterDefinition> paramList)
       {
          //
       }
  
   @Override
   protected void executeImpl(final Action ruleAction,
                              final NodeRef actionedUponNodeRef)
       {
          // put content into temp file
          ContentReader reader = contentService.getReader(actionedUponNodeRef, ContentModel.PROP_CONTENT);
          String fileName = (String) nodeService.getProperty(actionedUponNodeRef, ContentModel.PROP_NAME);
          File sourceFile = TempFileProvider.createTempFile("anti_virus_check_", "_" + fileName);
          reader.getContent(sourceFile);

          // add the source property
          Map<String, String> properties = new HashMap<String, String>(5);
          properties.put(VAR_SOURCE, sourceFile.getAbsolutePath());
         
          // execute the transformation command
          ExecutionResult result = null;
          try
            {
               result = command.execute(properties);
            }
          catch (Throwable e)
            {
               throw new AlfrescoRuntimeException("Antivirus check error: \n" + command, e);
            }
         
          // check
          if (!result.getSuccess())
            {
               //throw new AlfrescoRuntimeException("Antivirus check error: \n" + result);
               // try sending email using template
               try
                 {
                    // try to get document creator's email address
                    String creatorName = (String) nodeService.getProperty(actionedUponNodeRef, ContentModel.PROP_CREATOR);
                    if (null == creatorName || 0 == creatorName.length())
                      {
                         throw new Exception("couldn't get creator's name");
                      }
                   
                    NodeRef creator = personService.getPerson(creatorName);
                    if (null == creator)
                      {
                         throw new Exception("couldn't get creator");
                      }
                   
                    String creatorEmail = (String) nodeService.getProperty(creator, ContentModel.PROP_EMAIL);
                    if (null == creatorEmail || 0 == creatorEmail.length())
                      {
                         throw new Exception("couldn't get creator's email address");
                      }
                   
                    // put together message
                    String emailTemplate = "alfresco/module/antivirus-action/template/virus_found.ftl";
                    Map<String, Object> model = new HashMap<String, Object>(8, 1.0f);
                    model.put("filename", fileName);
                    model.put("message", result);
                   
                    String emailMsg = templateService.processTemplate("freemarker", emailTemplate,  model);
                   
                    // send email message
                    Action emailAction = actionService.createAction("mail");
                    emailAction.setParameterValue(MailActionExecuter.PARAM_TO, creatorEmail);
                    emailAction.setParameterValue(MailActionExecuter.PARAM_FROM, fromEmail);
                    emailAction.setParameterValue(MailActionExecuter.PARAM_SUBJECT, "Virus found in " + fileName);
                    emailAction.setParameterValue(MailActionExecuter.PARAM_TEXT, emailMsg);
                    emailAction.setExecuteAsynchronously(true);
                    actionService.executeAction(emailAction, null);
                   
                    // delete node
                    nodeService.addAspect(actionedUponNodeRef, ContentModel.ASPECT_TEMPORARY, null);
                    nodeService.deleteNode(actionedUponNodeRef);
                 }
               catch (Exception e)
                 {
                    throw new AlfrescoRuntimeException("Failed to send email:\n" + e.getMessage());
                 }
            }
       }
}

I don't know if I've done everything the correct way, but it seems to work. All this stuff is in the wiki, but presented in such a way that you only know you've got the right bit several steps further down the line. Hopefully other people will find this useful. I know I would have done a couple of weeks ago.

swithun
Champ in-the-making
Champ in-the-making
I've added the above to the wiki, in case other people find it useful.