You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@manifoldcf.apache.org by kw...@apache.org on 2014/05/07 00:43:26 UTC

svn commit: r1592916 - in /manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main: java/org/apache/manifoldcf/agents/output/amazoncloudsearch/ native2ascii/org/apache/manifoldcf/agents/output/amazoncloudsearch/ resources/org...

Author: kwright
Date: Tue May  6 22:43:25 2014
New Revision: 1592916

URL: http://svn.apache.org/r1592916
Log:
Commit latest patch

Modified:
    manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/java/org/apache/manifoldcf/agents/output/amazoncloudsearch/AmazonCloudSearchConfig.java
    manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/java/org/apache/manifoldcf/agents/output/amazoncloudsearch/AmazonCloudSearchConnector.java
    manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/native2ascii/org/apache/manifoldcf/agents/output/amazoncloudsearch/common_en_US.properties
    manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/native2ascii/org/apache/manifoldcf/agents/output/amazoncloudsearch/common_ja_JP.properties
    manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/resources/org/apache/manifoldcf/agents/output/amazoncloudsearch/editSpecification.html
    manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/resources/org/apache/manifoldcf/agents/output/amazoncloudsearch/editSpecification.js
    manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/resources/org/apache/manifoldcf/agents/output/amazoncloudsearch/viewSpecification.html

Modified: manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/java/org/apache/manifoldcf/agents/output/amazoncloudsearch/AmazonCloudSearchConfig.java
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/java/org/apache/manifoldcf/agents/output/amazoncloudsearch/AmazonCloudSearchConfig.java?rev=1592916&r1=1592915&r2=1592916&view=diff
==============================================================================
--- manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/java/org/apache/manifoldcf/agents/output/amazoncloudsearch/AmazonCloudSearchConfig.java (original)
+++ manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/java/org/apache/manifoldcf/agents/output/amazoncloudsearch/AmazonCloudSearchConfig.java Tue May  6 22:43:25 2014
@@ -34,5 +34,11 @@ public class AmazonCloudSearchConfig {
   public static final String PROXY_PROTOCOL_DEFAULT = "http";
   public static final String PROXY_HOST_DEFAULT = "";
   public static final String PROXY_PORT_DEFAULT = "";
-
+  public static final String NODE_FIELDMAP = "fieldmap";
+  public static final String NODE_KEEPMETADATA = "keepAllMetadata";
+  public static final String ATTRIBUTE_SOURCE = "source";
+  public static final String ATTRIBUTE_TARGET = "target";
+  public static final String ATTRIBUTE_VALUE = "value";
+  
+  
 }

Modified: manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/java/org/apache/manifoldcf/agents/output/amazoncloudsearch/AmazonCloudSearchConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/java/org/apache/manifoldcf/agents/output/amazoncloudsearch/AmazonCloudSearchConnector.java?rev=1592916&r1=1592915&r2=1592916&view=diff
==============================================================================
--- manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/java/org/apache/manifoldcf/agents/output/amazoncloudsearch/AmazonCloudSearchConnector.java (original)
+++ manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/java/org/apache/manifoldcf/agents/output/amazoncloudsearch/AmazonCloudSearchConnector.java Tue May  6 22:43:25 2014
@@ -23,10 +23,12 @@ import java.io.InputStream;
 import java.io.InterruptedIOException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Locale;
 
+import org.apache.commons.io.FilenameUtils;
 import org.apache.http.Consts;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpHost;
@@ -44,13 +46,15 @@ import org.apache.manifoldcf.agents.inte
 import org.apache.manifoldcf.agents.interfaces.RepositoryDocument;
 import org.apache.manifoldcf.agents.interfaces.ServiceInterruption;
 import org.apache.manifoldcf.agents.output.BaseOutputConnector;
-import org.apache.manifoldcf.agents.output.amazoncloudsearch.SDFModel.Document;
+import org.apache.manifoldcf.agents.output.amazoncloudsearch.SDFModel.Document;
 import org.apache.manifoldcf.core.interfaces.ConfigParams;
+import org.apache.manifoldcf.core.interfaces.ConfigurationNode;
 import org.apache.manifoldcf.core.interfaces.ManifoldCFException;
 import org.apache.manifoldcf.core.interfaces.IThreadContext;
 import org.apache.manifoldcf.core.interfaces.IHTTPOutput;
 import org.apache.manifoldcf.core.interfaces.IPostParameters;
 import org.apache.manifoldcf.core.interfaces.IPasswordMapperActivity;
+import org.apache.manifoldcf.core.interfaces.SpecificationNode;
 import org.apache.manifoldcf.crawler.system.Logging;
 import org.apache.tika.exception.TikaException;
 import org.apache.tika.metadata.Metadata;
@@ -66,6 +70,9 @@ import com.fasterxml.jackson.core.JsonPa
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 
 public class AmazonCloudSearchConnector  extends BaseOutputConnector {
 
@@ -79,22 +86,23 @@ public class AmazonCloudSearchConnector 
 
   /** Forward to the HTML template to edit the configuration parameters */
   private static final String EDIT_CONFIGURATION_HTML = "editConfiguration.html";
-
+  
   /** Forward to the HTML template to view the configuration parameters */
   private static final String VIEW_CONFIGURATION_HTML = "viewConfiguration.html";
 
   /** Forward to the javascript to check the specification parameters for the job */
   private static final String EDIT_SPECIFICATION_JS = "editSpecification.js";
-
-  /** Forward to the template to edit the configuration parameters for the job */
-  private static final String EDIT_SPECIFICATION_HTML = "editSpecification.html";
-
-  /** Forward to the template to view the specification parameters for the job */
-  private static final String VIEW_SPECIFICATION_HTML = "viewSpecification.html";
-
+  
+  private static final String EDIT_SPECIFICATION_CONTENT_HTML = "editSpecification.html";
+  
+  private static final String VIEW_SPEC_FORWARD = "viewSpecification.html";
+  
   /** Local connection */
   protected HttpPost poster = null;
-
+  
+  /** cloudsearch field name for file body text. */
+  private static final String FILE_BODY_TEXT_FIELDNAME = "f_bodytext";
+  
   /** Constructor.
    */
   public AmazonCloudSearchConnector(){
@@ -147,13 +155,6 @@ public class AmazonCloudSearchConnector 
   protected void getSession()
     throws ManifoldCFException
   {
-    //curl -X POST --upload-file data1.json doc.movies-123456789012.us-east-1.cloudsearch.amazonaws.com/2013-01-01/documents/batch --header "Content-Type:application/json"
-    //String documentEndpointUrl = "doc-test1-hjzolhfixtfctmuaezbzinjduu.us-east-1.cloudsearch.amazonaws.com";
-    //String urlStr = "https://" + documentEndpointUrl + "/2013-01-01/documents/batch";
-    //String proxyHost = System.getenv().get("HTTP_PROXY");
-    //String host = proxyHost.substring(proxyHost.indexOf("://")+3,proxyHost.lastIndexOf(":"));
-    //String port = proxyHost.substring(proxyHost.lastIndexOf(":")+1,proxyHost.length()-1);
-
     String serverHost = params.getParameter(AmazonCloudSearchConfig.SERVER_HOST);
     if (serverHost == null)
       throw new ManifoldCFException("Server host parameter required");
@@ -195,8 +196,16 @@ public class AmazonCloudSearchConnector 
     try {
       getSession();
       String responsbody = postData("[]");
-      String status = getStatusFromJsonResponse(responsbody);
-      
+      String status = "";
+      try
+      {
+        status = getStatusFromJsonResponse(responsbody);
+      } catch (ManifoldCFException e)
+      {
+        Logging.connectors.debug(e);
+        return "Could not get status from response body. Check Access Policy setting of your domain of Amazon CloudSearch.: " + e.getMessage();
+      }
+          
       // check status message
       String message = "";
       if ("error".equals(status)) {
@@ -264,18 +273,99 @@ public class AmazonCloudSearchConnector 
   *
   * This method presumes that the connector object has been configured, and it is thus able to communicate with the output data store should that be
   * necessary.
-  *@param spec is the current output specification for the job that is doing the crawling.
+  *@param os is the current output specification for the job that is doing the crawling.
   *@return a string, of unlimited length, which uniquely describes output configuration and specification in such a way that if two such strings are equal,
   * the document will not need to be sent again to the output data store.
   */
   @Override
-  public String getOutputDescription(OutputSpecification spec)
+  public String getOutputDescription(OutputSpecification os)
     throws ManifoldCFException, ServiceInterruption
   {
-    return "";
+    // Do the source/target pairs
+    int i = 0;
+    Map<String, List<String>> sourceTargets = new HashMap<String, List<String>>();
+    boolean keepAllMetadata = true;
+    while (i < os.getChildCount()) {
+      SpecificationNode sn = os.getChild(i++);
+      
+      if(sn.getType().equals(AmazonCloudSearchConfig.NODE_KEEPMETADATA)) {
+        String value = sn.getAttributeValue(AmazonCloudSearchConfig.ATTRIBUTE_VALUE);
+        keepAllMetadata = Boolean.parseBoolean(value);
+      } else if (sn.getType().equals(AmazonCloudSearchConfig.NODE_FIELDMAP)) {
+        String source = sn.getAttributeValue(AmazonCloudSearchConfig.ATTRIBUTE_SOURCE);
+        String target = sn.getAttributeValue(AmazonCloudSearchConfig.ATTRIBUTE_TARGET);
+        
+        if (target == null) {
+          target = "";
+        }
+        List<String> list = (List<String>)sourceTargets.get(source);
+        if (list == null) {
+          list = new ArrayList<String>();
+          sourceTargets.put(source, list);
+        }
+        list.add(target);
+      }
+    }
+    
+    String[] sortArray = new String[sourceTargets.size()];
+    Iterator iter = sourceTargets.keySet().iterator();
+    i = 0;
+    while (iter.hasNext()) {
+      sortArray[i++] = (String)iter.next();
+    }
+    java.util.Arrays.sort(sortArray);
+    
+    ArrayList<String[]> sourceTargetsList = new ArrayList<String[]>();
+    i = 0;
+    while (i < sortArray.length) {
+      String source = sortArray[i++];
+      List<String> values = (List<String>)sourceTargets.get(source);
+      java.util.Collections.sort(values);
+      int j = 0;
+      while (j < values.size()) {
+        String target = (String)values.get(j++);
+        String[] fixedList = new String[2];
+        fixedList[0] = source;
+        fixedList[1] = target;
+        sourceTargetsList.add(fixedList);
+      }
+    }
+    
+    //for Content tab
+    AmazonCloudSearchSpecs spec = new AmazonCloudSearchSpecs(getSpecNode(os));
+    
+    //build json 
+    // {"fieldMappings":{"Content-Style-Type":"content_type","dc:title":"title","description":"description"},"keepAllMetadata":true}
+    String resultBody = "";
+    try {
+      ObjectMapper mapper = new ObjectMapper();
+      
+      ObjectNode rootNode = mapper.createObjectNode();
+      ObjectNode fm = rootNode.putObject("fieldMappings");
+      for(String[] f : sourceTargetsList){
+        fm.put(f[0], f[1]);
+      }
+      
+      // Keep all metadata flag
+      if (keepAllMetadata)
+      {
+        rootNode.put("keepAllMetadata", true);
+      }
+      else
+      {
+        rootNode.put("keepAllMetadata", false);
+      }
+      
+      // Content tab..
+      rootNode.put("content", mapper.valueToTree(spec));
+      
+      resultBody = mapper.writeValueAsString(rootNode);
+    } catch (JsonProcessingException e) {
+      throw new ManifoldCFException(e);
+    }
+    return resultBody;
   }
 
-
   /** Detect if a mime type is indexable or not.  This method is used by participating repository connectors to pre-filter the number of
   * unusable documents that will be passed to this output connector.
   *@param outputDescription is the document's output version.
@@ -285,14 +375,60 @@ public class AmazonCloudSearchConnector 
   public boolean checkMimeTypeIndexable(String outputDescription, String mimeType)
     throws ManifoldCFException, ServiceInterruption
   {
-    getSession();
-    
-    if(("text/html").equalsIgnoreCase(mimeType)){
-      return super.checkMimeTypeIndexable(outputDescription,mimeType);
+    try {
+      ObjectMapper mapper = new ObjectMapper();
+      AmazonCloudSearchSpecs spec = new AmazonCloudSearchSpecs(mapper.readTree(outputDescription).get("content"));
+      if(spec.checkMimeType(mimeType))
+      {
+        return super.checkMimeTypeIndexable(mimeType);
+      }else
+      {
+        return false;
+      }
+    } catch (JsonProcessingException e) {
+      throw new ManifoldCFException(e);
+    } catch (IOException e) {
+      throw new ManifoldCFException(e);
     }
-    return false;
   }
 
+  @Override
+  public boolean checkLengthIndexable(String outputDescription, long length)
+      throws ManifoldCFException, ServiceInterruption {
+    try {
+      ObjectMapper mapper = new ObjectMapper();
+      AmazonCloudSearchSpecs spec = new AmazonCloudSearchSpecs(mapper.readTree(outputDescription).get("content"));
+      long maxFileSize = spec.getMaxFileSize();
+      if (length > maxFileSize)
+      {
+        return false;
+      }
+      return super.checkLengthIndexable(outputDescription, length);
+    } catch (JsonProcessingException e) {
+      throw new ManifoldCFException(e);
+    } catch (IOException e){
+      throw new ManifoldCFException(e);
+    }
+  }
+
+  @Override
+  public boolean checkURLIndexable(String outputDescription, String url)
+    throws ManifoldCFException, ServiceInterruption {
+    try {
+      ObjectMapper mapper = new ObjectMapper();
+      AmazonCloudSearchSpecs spec = new AmazonCloudSearchSpecs(mapper.readTree(outputDescription).get("content"));
+      if (spec.checkExtension(FilenameUtils.getExtension(url)))
+      {
+        return super.checkURLIndexable(outputDescription, url);
+      }
+      return false;
+    } catch (JsonProcessingException e) {
+      throw new ManifoldCFException(e);
+    } catch (IOException e){
+      throw new ManifoldCFException(e);
+    }
+  }
+  
   /** Add (or replace) a document in the output data store using the connector.
   * This method presumes that the connector object has been configured, and it is thus able to communicate with the output data store should that be
   * necessary.
@@ -312,65 +448,86 @@ public class AmazonCloudSearchConnector 
     throws ManifoldCFException, ServiceInterruption
   {
     // Establish a session
-    getSession();
+    getSession();
+    
+    Map<String, List<String>> sourceTargets = new HashMap<String, List<String>>();
+    boolean keepAllMetadata = true;
+    keepAllMetadata = readConfigurationDescription(outputDescription, sourceTargets);
+    
     String jsondata = "";
-    try {
-      InputStream is = document.getBinaryStream();
-      Parser parser = new HtmlParser();
-      ContentHandler handler = new BodyContentHandler();
-      Metadata metadata = new Metadata();
-      parser.parse(is, handler, metadata, new ParseContext());
-      
+    try {
       //build json..
       SDFModel model = new SDFModel();
       Document doc = model.new Document();
       doc.setType("add");
       doc.setId(documentURI);
       
-      //set body text.
-      Map<String,Object> fields = new HashMap<String,Object>();
-      String bodyStr = handler.toString();
-      if(bodyStr != null){
-        bodyStr = handler.toString().replaceAll("\\n", "").replaceAll("\\t", "");
-        fields.put("body", bodyStr);
-      }
-      
-      //mapping metadata to SDF fields.
-      String contenttype = metadata.get("Content-Style-Type");
-      String title = metadata.get("dc:title");
-      String size = String.valueOf(bodyStr.length());
-      String description = metadata.get("description");
-      String keywords = metadata.get("keywords");
-      if(contenttype != null && !"".equals(contenttype)) fields.put("content_type", contenttype);
-      if(title != null && !"".equals(title)) fields.put("title", title);
-      if(size != null && !"".equals(size)) fields.put("size", size);
-      if(description != null && !"".equals(description)) fields.put("description", description);
-      if(keywords != null && !"".equals(keywords))
-      {
-        List<String> keywordList = new ArrayList<String>();
-        for(String tmp : keywords.split(",")){
-          keywordList.add(tmp);
+      HashMap fields = new HashMap();
+      Metadata metadata = extractBinaryFile(document, fields);
+      
+      Iterator<String> itr = document.getFields();
+      while(itr.hasNext())
+      {
+        String fName = itr.next();
+        Object[] value = document.getField(fName);
+        if(sourceTargets.get(fName)!=null)
+        {
+          List<String> fnameList = sourceTargets.get(fName);
+          for(String newName : fnameList)
+          {
+            fields.put(newName, value);
+          }
+        }
+        else
+        {
+          if(keepAllMetadata)
+          {
+            fields.put(fName, value);
+          }
+        }
+      }
+      
+      //metadata of binary files.
+      String[] metaNames = metadata.names();
+      for(String mName : metaNames){
+        String value = metadata.get(mName);
+        if(sourceTargets.get(mName)!=null)
+        {
+          List<String> nameList = sourceTargets.get(mName);
+          for(String newName : nameList)
+          {
+            fields.put(newName, value);
+          }
+        }
+        else
+        {
+          if(keepAllMetadata)
+          {
+            fields.put(mName, value);
+          }
         }
-        fields.put("keywords", keywordList);
       }
       doc.setFields(fields);
       model.addDocument(doc);
       
       //generate json data.
       jsondata = model.toJSON();
-      
     } 
     catch (SAXException e) {
-      // if document data could not be converted to JSON by jackson.
+      // if document data could not be converted to JSON by jackson.
+      Logging.connectors.debug(e);
       throw new ManifoldCFException(e);
     } catch (JsonProcessingException e) {
-      // if document data could not be converted to JSON by jackson.
+      // if document data could not be converted to JSON by jackson.
+      Logging.connectors.debug(e);
       throw new ManifoldCFException(e);
     } catch (TikaException e) {
-      // if document could not be parsed by tika.
+      // if document could not be parsed by tika.
+      Logging.connectors.debug(e);
       return DOCUMENTSTATUS_REJECTED;
     } catch (IOException e) {
-      // if document data could not be read when the document parsing by tika.
+      // if document data could not be read when the document parsing by tika.
+      Logging.connectors.debug(e);
       throw new ManifoldCFException(e);
     }
     
@@ -385,8 +542,68 @@ public class AmazonCloudSearchConnector 
       return DOCUMENTSTATUS_ACCEPTED;
     }
     else {
-      throw new ManifoldCFException("recieved error status from service after feeding document.");
+      throw new ManifoldCFException("recieved error status from service after feeding document. response body : " + responsbody);
     }
+  }
+
+  private boolean readConfigurationDescription(String outputDescription,
+      Map<String, List<String>> sourceTargets)
+      throws ManifoldCFException {
+    ObjectMapper mapper = new ObjectMapper();
+    
+    boolean keepAllMetadata = true;
+    try
+    {
+      JsonNode node = mapper.readTree(outputDescription);
+      Iterator<String> ir = node.fieldNames();
+      while(ir.hasNext()){
+        String fieldName = ir.next();
+        if("fieldMappings".equals(fieldName))
+        {
+          JsonNode fm = node.path(fieldName);
+          Iterator<String> itr = fm.fieldNames();
+          while(itr.hasNext())
+          {
+            String from = itr.next();
+            String to = fm.path(from).asText();
+            
+            List<String> list = sourceTargets.get(from);
+            if (list == null) {
+              list = new ArrayList<String>();
+              sourceTargets.put(from, list);
+            }
+            list.add(to);
+          }
+        }
+        else if("keepAllMetadata".equals(fieldName)){
+          String meta = node.path(fieldName).toString();
+          keepAllMetadata = Boolean.getBoolean(meta);
+        }
+      }
+      return keepAllMetadata;
+      
+    } catch (JsonProcessingException e) {
+      throw new ManifoldCFException(e);
+    } catch (IOException e) {
+      throw new ManifoldCFException(e);
+    }
+  }
+
+  private Metadata extractBinaryFile(RepositoryDocument document, HashMap fields)
+      throws IOException, SAXException, TikaException {
+    
+    //extract body text and metadata fields from binary file.
+    InputStream is = document.getBinaryStream();
+    Parser parser = new HtmlParser(); //TODO
+    ContentHandler handler = new BodyContentHandler();
+    Metadata metadata = new Metadata();
+    parser.parse(is, handler, metadata, new ParseContext());
+    String bodyStr = handler.toString();
+    if(bodyStr != null){
+      bodyStr = handler.toString().replaceAll("\\n", "").replaceAll("\\t", "");
+      fields.put(FILE_BODY_TEXT_FIELDNAME, bodyStr);
+    }
+    return metadata;
   }
 
   /** Remove a document using the connector.
@@ -516,19 +733,18 @@ public class AmazonCloudSearchConnector 
   public void outputConfigurationBody(IThreadContext threadContext,
       IHTTPOutput out, Locale locale, ConfigParams parameters, String tabName)
       throws ManifoldCFException, IOException {
-
-
+    
     // Call the Velocity templates for each tab
     Map<String, Object> paramMap = new HashMap<String, Object>();
+    
     // Set the tab name
     paramMap.put("TABNAME", tabName);
-
+    
     // Fill in the parameters
     fillInServerConfigurationMap(paramMap, out, parameters);
-        
+    
     // Server tab
     Messages.outputResourceWithVelocity(out,locale,EDIT_CONFIGURATION_HTML,paramMap);
-
   }
 
   /**
@@ -608,5 +824,392 @@ public class AmazonCloudSearchConnector 
     throw new ServiceInterruption("IO exception: " + e.getMessage(), e,
         currentTime + 300000L, currentTime + 3 * 60 * 60000L, -1, false);
   }
+  
+  /**
+   * Output the specification header section. This method is called in the head
+   * section of a job page which has selected an output connection of the
+   * current type. Its purpose is to add the required tabs to the list, and to
+   * output any javascript methods that might be needed by the job editing HTML.
+   * 
+   * @param out is the output to which any HTML should be sent.
+   * @param os is the current output specification for this job.
+   * @param tabsArray is an array of tab names. Add to this array any tab names
+   *        that are specific to the connector.
+   */
+  @Override
+  public void outputSpecificationHeader(IHTTPOutput out, Locale locale,
+      OutputSpecification os, List<String> tabsArray)
+      throws ManifoldCFException, IOException
+  {
+    super.outputSpecificationHeader(out, locale, os, tabsArray);
+    tabsArray.add(Messages.getString(locale, "AmazonCloudSearchOutputConnector.FieldMappingTabName"));
+    tabsArray.add(Messages.getString(locale, "AmazonCloudSearchOutputConnector.ContentsTabName"));
+    outputResource(EDIT_SPECIFICATION_JS, out, locale, null, null);
+  }
+  
+  /**
+   * Read the content of a resource, replace the variable ${PARAMNAME} with the
+   * value and copy it to the out.
+   * 
+   * @param resName
+   * @param out
+   * @throws ManifoldCFException
+   */
+  private static void outputResource(String resName, IHTTPOutput out,
+    Locale locale, AmazonCloudSearchParam params, String tabName) throws ManifoldCFException {
+    Map<String,String> paramMap = null;
+    if (params != null) {
+      paramMap = params.buildMap();
+      if (tabName != null) {
+        paramMap.put("TabName", tabName);
+      }
+    }
+    
+    Messages.outputResourceWithVelocity(out,locale,resName,paramMap,false);
+  }
+
+  /** Output the specification body section.
+  * This method is called in the body section of a job page which has selected an output connection of the current type.  Its purpose is to present the required form elements for editing.
+  * The coder can presume that the HTML that is output from this configuration will be within appropriate <html>, <body>, and <form> tags.  The name of the
+  * form is "editjob".
+  *@param out is the output to which any HTML should be sent.
+  *@param os is the current output specification for this job.
+  *@param tabName is the current tab name.
+  */
+  @Override
+  public void outputSpecificationBody(IHTTPOutput out, Locale locale, OutputSpecification os, String tabName)
+    throws ManifoldCFException, IOException
+  {
+    int i = 0;
+    
+    // Field Mapping tab
+    if (tabName.equals(Messages.getString(locale,"AmazonCloudSearchOutputConnector.FieldMappingTabName")))
+    {
+      out.print(
+"<table class=\"displaytable\">\n"+
+"  <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n"+
+"  <tr>\n"+
+"    <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"AmazonCloudSearchOutputConnector.FieldMappings") + "</nobr></td>\n"+
+"    <td class=\"boxcell\">\n"+
+"      <table class=\"formtable\">\n"+
+"        <tr class=\"formheaderrow\">\n"+
+"          <td class=\"formcolumnheader\"></td>\n"+
+"          <td class=\"formcolumnheader\"><nobr>" + Messages.getBodyString(locale,"AmazonCloudSearchOutputConnector.MetadataFieldName") + "</nobr></td>\n"+
+"          <td class=\"formcolumnheader\"><nobr>" + Messages.getBodyString(locale,"AmazonCloudSearchOutputConnector.CloudSearchFieldName") + "</nobr></td>\n"+
+"        </tr>\n"
+      );
+
+      int fieldCounter = 0;
+      i = 0;
+      boolean keepMetadata = true;
+      while (i < os.getChildCount()) {
+        SpecificationNode sn = os.getChild(i++);
+        if (sn.getType().equals(AmazonCloudSearchConfig.NODE_FIELDMAP)) {
+          String source = sn.getAttributeValue(AmazonCloudSearchConfig.ATTRIBUTE_SOURCE);
+          String target = sn.getAttributeValue(AmazonCloudSearchConfig.ATTRIBUTE_TARGET);
+          if (target != null && target.length() == 0) {
+            target = null;
+          }
+          String targetDisplay = target;
+          if (target == null)
+          {
+            target = "";
+            targetDisplay = "(remove)";
+          }
+          // It's prefix will be...
+          String prefix = "cloudsearch_fieldmapping_" + Integer.toString(fieldCounter);
+          out.print(
+"        <tr class=\""+(((fieldCounter % 2)==0)?"evenformrow":"oddformrow")+"\">\n"+
+"          <td class=\"formcolumncell\">\n"+
+"            <a name=\""+prefix+"\">\n"+
+"              <input type=\"button\" value=\"Delete\" alt=\""+Messages.getAttributeString(locale,"AmazonCloudSearchOutputConnector.DeleteFieldMapping")+Integer.toString(fieldCounter+1)+"\" onclick='javascript:deleteFieldMapping("+Integer.toString(fieldCounter)+");'/>\n"+
+"              <input type=\"hidden\" name=\""+prefix+"_op\" value=\"Continue\"/>\n"+
+"              <input type=\"hidden\" name=\""+prefix+"_source\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(source)+"\"/>\n"+
+"              <input type=\"hidden\" name=\""+prefix+"_target\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(target)+"\"/>\n"+
+"            </a>\n"+
+"          </td>\n"+
+"          <td class=\"formcolumncell\">\n"+
+"            <nobr>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(source)+"</nobr>\n"+
+"          </td>\n"+
+"          <td class=\"formcolumncell\">\n"+
+"            <nobr>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(targetDisplay)+"</nobr>\n"+
+"          </td>\n"+
+"        </tr>\n"
+          );
+          fieldCounter++;
+        }
+        else if(sn.getType().equals(AmazonCloudSearchConfig.NODE_KEEPMETADATA)) {
+          keepMetadata = Boolean.parseBoolean(sn.getAttributeValue(AmazonCloudSearchConfig.ATTRIBUTE_VALUE));
+        }
+      }
+      
+      if (fieldCounter == 0)
+      {
+        out.print(
+"        <tr class=\"formrow\"><td class=\"formmessage\" colspan=\"3\">" + Messages.getBodyString(locale,"AmazonCloudSearchOutputConnector.NoFieldMappingSpecified") + "</td></tr>\n"
+        );
+      }
+      
+      String keepMetadataValue;
+      if (keepMetadata)
+        keepMetadataValue = " checked=\"true\"";
+      else
+        keepMetadataValue = "";
+
+      out.print(
+"        <tr class=\"formrow\"><td class=\"formseparator\" colspan=\"3\"><hr/></td></tr>\n"+
+"        <tr class=\"formrow\">\n"+
+"          <td class=\"formcolumncell\">\n"+
+"            <a name=\"cloudsearch_fieldmapping\">\n"+
+"              <input type=\"button\" value=\"" + Messages.getAttributeString(locale,"AmazonCloudSearchOutputConnector.Add") + "\" alt=\"" + Messages.getAttributeString(locale,"AmazonCloudSearchOutputConnector.AddFieldMapping") + "\" onclick=\"javascript:addFieldMapping();\"/>\n"+
+"            </a>\n"+
+"            <input type=\"hidden\" name=\"cloudsearch_fieldmapping_count\" value=\""+fieldCounter+"\"/>\n"+
+"            <input type=\"hidden\" name=\"cloudsearch_fieldmapping_op\" value=\"Continue\"/>\n"+
+"          </td>\n"+
+"          <td class=\"formcolumncell\">\n"+
+"            <nobr><input type=\"text\" size=\"15\" name=\"cloudsearch_fieldmapping_source\" value=\"\"/></nobr>\n"+
+"          </td>\n"+
+"          <td class=\"formcolumncell\">\n"+
+"            <nobr><input type=\"text\" size=\"15\" name=\"cloudsearch_fieldmapping_target\" value=\"\"/></nobr>\n"+
+"          </td>\n"+
+"        </tr>\n"+
+"      </table>\n"+
+"    </td>\n"+
+"  </tr>\n"+
+"  <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n"+
+"  <tr>\n"+
+"    <td class=\"description\"><nobr>"+Messages.getBodyString(locale,"AmazonCloudSearchOutputConnector.KeepAllMetadata")+"</nobr></td>\n"+
+"    <td class=\"value\">\n"+
+"       <input type=\"checkbox\""+keepMetadataValue+" name=\"cloudsearch_keepallmetadata\" value=\"true\"/>\n"+
+"    </td>\n"+
+"  </tr>\n"+
+"</table>\n"
+      );
+    }
+    else
+    {
+      // Hiddens for field mapping
+      i = 0;
+      int fieldCounter = 0;
+      String keepMetadataValue = "true";
+      while (i < os.getChildCount()) {
+        SpecificationNode sn = os.getChild(i++);
+        if (sn.getType().equals(AmazonCloudSearchConfig.NODE_FIELDMAP)) {
+          String source = sn.getAttributeValue(AmazonCloudSearchConfig.ATTRIBUTE_SOURCE);
+          String target = sn.getAttributeValue(AmazonCloudSearchConfig.ATTRIBUTE_TARGET);
+          if (target == null)
+            target = "";
+        // It's prefix will be...
+          String prefix = "cloudsearch_fieldmapping_" + Integer.toString(fieldCounter);
+          out.print(
+"<input type=\"hidden\" name=\""+prefix+"_source\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(source)+"\"/>\n"+
+"<input type=\"hidden\" name=\""+prefix+"_target\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(target)+"\"/>\n"
+          );
+          fieldCounter++;
+        }
+        else if(sn.getType().equals(AmazonCloudSearchConfig.NODE_KEEPMETADATA))
+        {
+          keepMetadataValue = sn.getAttributeValue(AmazonCloudSearchConfig.ATTRIBUTE_VALUE);
+        }
+      }
+      out.print(
+"<input type=\"hidden\" name=\"cloudsearch_keepallmetadata\" value=\""+keepMetadataValue+"\"/>\n"
+      );
+      out.print(
+"<input type=\"hidden\" name=\"cloudsearch_fieldmapping_count\" value=\""+Integer.toString(fieldCounter)+"\"/>\n"
+      );
+    }
+    
+
+    // Content tab
+    AmazonCloudSearchSpecs param = new AmazonCloudSearchSpecs(getSpecNode(os));
+    outputResource(EDIT_SPECIFICATION_CONTENT_HTML, out, locale, param, tabName);
+    
+  }
+
+  /** Process a specification post.
+  * This method is called at the start of job's edit or view page, whenever there is a possibility that form data for a connection has been
+  * posted.  Its purpose is to gather form information and modify the output specification accordingly.
+  * The name of the posted form is "editjob".
+  *@param variableContext contains the post data, including binary file-upload information.
+  *@param os is the current output specification for this job.
+  *@return null if all is well, or a string error message if there is an error that should prevent saving of the job (and cause a redirection to an error page).
+  */
+  @Override
+  public String processSpecificationPost(IPostParameters variableContext,
+      Locale locale, OutputSpecification os) throws ManifoldCFException {
+    
+    ConfigurationNode specNode = getSpecNode(os);
+    boolean bAdd = (specNode == null);
+    if (bAdd) 
+    {
+      specNode = new SpecificationNode(AmazonCloudSearchSpecs.AMAZONCLOUDSEARCH_SPECS_NODE);
+    }
+    AmazonCloudSearchSpecs.contextToSpecNode(variableContext, specNode);
+    if (bAdd)
+    {
+      os.addChild(os.getChildCount(), specNode);
+    }
+    
+    String x = variableContext.getParameter("cloudsearch_fieldmapping_count");
+    if (x != null && x.length() > 0)
+    {
+      // About to gather the fieldmapping nodes, so get rid of the old ones.
+      int i = 0;
+      while (i < os.getChildCount())
+      {
+        SpecificationNode node = os.getChild(i);
+        if (node.getType().equals(AmazonCloudSearchConfig.NODE_FIELDMAP) || node.getType().equals(AmazonCloudSearchConfig.NODE_KEEPMETADATA))
+          os.removeChild(i);
+        else
+          i++;
+      }
+      int count = Integer.parseInt(x);
+      i = 0;
+      while (i < count)
+      {
+        String prefix = "cloudsearch_fieldmapping_"+Integer.toString(i);
+        String op = variableContext.getParameter(prefix+"_op");
+        if (op == null || !op.equals("Delete"))
+        {
+          // Gather the fieldmap etc.
+          String source = variableContext.getParameter(prefix+"_source");
+          String target = variableContext.getParameter(prefix+"_target");
+          if (target == null)
+            target = "";
+          SpecificationNode node = new SpecificationNode(AmazonCloudSearchConfig.NODE_FIELDMAP);
+          node.setAttribute(AmazonCloudSearchConfig.ATTRIBUTE_SOURCE,source);
+          node.setAttribute(AmazonCloudSearchConfig.ATTRIBUTE_TARGET,target);
+          os.addChild(os.getChildCount(),node);
+        }
+        i++;
+      }
+      
+      String addop = variableContext.getParameter("cloudsearch_fieldmapping_op");
+      if (addop != null && addop.equals("Add"))
+      {
+        String source = variableContext.getParameter("cloudsearch_fieldmapping_source");
+        String target = variableContext.getParameter("cloudsearch_fieldmapping_target");
+        if (target == null)
+          target = "";
+        SpecificationNode node = new SpecificationNode(AmazonCloudSearchConfig.NODE_FIELDMAP);
+        node.setAttribute(AmazonCloudSearchConfig.ATTRIBUTE_SOURCE,source);
+        node.setAttribute(AmazonCloudSearchConfig.ATTRIBUTE_TARGET,target);
+        os.addChild(os.getChildCount(),node);
+      }
+      
+      // Gather the keep all metadata parameter to be the last one
+      SpecificationNode node = new SpecificationNode(AmazonCloudSearchConfig.NODE_KEEPMETADATA);
+      String keepAll = variableContext.getParameter("cloudsearch_keepallmetadata");
+      if (keepAll != null)
+      {
+        node.setAttribute(AmazonCloudSearchConfig.ATTRIBUTE_VALUE, keepAll);
+      }
+      else
+      {
+        node.setAttribute(AmazonCloudSearchConfig.ATTRIBUTE_VALUE, "false");
+      }
+      // Add the new keepallmetadata config parameter 
+      os.addChild(os.getChildCount(), node);
+    }
+    
+    return null;
+  }
+  
+
+  final private SpecificationNode getSpecNode(OutputSpecification os) {
+    int l = os.getChildCount();
+    for (int i = 0; i < l; i++)
+    {
+      SpecificationNode node = os.getChild(i);
+      if (AmazonCloudSearchSpecs.AMAZONCLOUDSEARCH_SPECS_NODE.equals(node.getType()))
+      {
+        return node;
+      }
+    }
+    return null;
+  }
+  
+  /** View specification.
+  * This method is called in the body section of a job's view page.  Its purpose is to present the output specification information to the user.
+  * The coder can presume that the HTML that is output from this configuration will be within appropriate <html> and <body> tags.
+  *@param out is the output to which any HTML should be sent.
+  *@param os is the current output specification for this job.
+  */
+  @Override
+  public void viewSpecification(IHTTPOutput out, Locale locale, OutputSpecification os)
+    throws ManifoldCFException, IOException
+  {
+    // Prep for field mappings
+    int i = 0;
+    
+    // Display field mappings
+    out.print(
+"\n"+
+"<table class=\"displaytable\">\n"+
+"  <tr>\n"+
+"    <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"AmazonCloudSearchOutputConnector.FieldMappings") + "</nobr></td>\n"+
+"    <td class=\"boxcell\">\n"+
+"      <table class=\"formtable\">\n"+
+"        <tr class=\"formheaderrow\">\n"+
+"          <td class=\"formcolumnheader\"><nobr>" + Messages.getBodyString(locale,"AmazonCloudSearchOutputConnector.MetadataFieldName") + "</nobr></td>\n"+
+"          <td class=\"formcolumnheader\"><nobr>" + Messages.getBodyString(locale,"AmazonCloudSearchOutputConnector.CloudSearchFieldName") + "</nobr></td>\n"+
+"        </tr>\n"
+    );
+
+    int fieldCounter = 0;
+    i = 0;
+    String keepAllMetadataValue = "true";
+    while (i < os.getChildCount()) {
+      SpecificationNode sn = os.getChild(i++);
+      if (sn.getType().equals(AmazonCloudSearchConfig.NODE_FIELDMAP)) {
+        String source = sn.getAttributeValue(AmazonCloudSearchConfig.ATTRIBUTE_SOURCE);
+        String target = sn.getAttributeValue(AmazonCloudSearchConfig.ATTRIBUTE_TARGET);
+        String targetDisplay = target;
+        if (target == null)
+        {
+          target = "";
+          targetDisplay = "(remove)";
+        }
+        out.print(
+"        <tr class=\""+(((fieldCounter % 2)==0)?"evenformrow":"oddformrow")+"\">\n"+
+"          <td class=\"formcolumncell\">\n"+
+"            <nobr>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(source)+"</nobr>\n"+
+"          </td>\n"+
+"          <td class=\"formcolumncell\">\n"+
+"            <nobr>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(targetDisplay)+"</nobr>\n"+
+"          </td>\n"+
+"        </tr>\n"
+        );
+        fieldCounter++;
+      }
+      else if (sn.getType().equals(AmazonCloudSearchConfig.NODE_KEEPMETADATA))
+      {
+        keepAllMetadataValue = sn.getAttributeValue(AmazonCloudSearchConfig.ATTRIBUTE_VALUE);
+      }
+    }
+    
+    if (fieldCounter == 0)
+    {
+      out.print(
+"        <tr class=\"formrow\"><td class=\"formmessage\" colspan=\"3\">" + Messages.getBodyString(locale,"AmazonCloudSearchOutputConnector.NoFieldMappingSpecified") + "</td></tr>\n"
+      );
+    }
+    out.print(
+"      </table>\n"+
+"    </td>\n"+
+"  </tr>\n"+
+"  <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n"+
+"  <tr>\n"+
+"    <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"AmazonCloudSearchOutputConnector.KeepAllMetadata") + "</nobr></td>\n"+
+"    <td class=\"value\"><nobr>" + keepAllMetadataValue + "</nobr></td>\n"+
+"  </tr>\n"+
+"</table>\n"
+    );
+    
+    AmazonCloudSearchSpecs spec = new AmazonCloudSearchSpecs(getSpecNode(os));
+    outputResource(VIEW_SPEC_FORWARD, out, locale, spec, null);
+    
+  }
   
-}
\ No newline at end of file
+}

Modified: manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/native2ascii/org/apache/manifoldcf/agents/output/amazoncloudsearch/common_en_US.properties
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/native2ascii/org/apache/manifoldcf/agents/output/amazoncloudsearch/common_en_US.properties?rev=1592916&r1=1592915&r2=1592916&view=diff
==============================================================================
--- manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/native2ascii/org/apache/manifoldcf/agents/output/amazoncloudsearch/common_en_US.properties (original)
+++ manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/native2ascii/org/apache/manifoldcf/agents/output/amazoncloudsearch/common_en_US.properties Tue May  6 22:43:25 2014
@@ -22,3 +22,16 @@ AmazonCloudSearchOutputConnector.ProxyPo
 AmazonCloudSearchOutputConnector.ServerHostCannotBeNull=Server host cannot be null
 AmazonCloudSearchOutputConnector.ServerPathMustStartWithSlash=Server path must start with a '/'
 AmazonCloudSearchOutputConnector.ProxyPortMustBeAnInteger=Proxy port must be an integer
+AmazonCloudSearchOutputConnector.FieldMappingTabName=CloudSearch Field Mapping
+AmazonCloudSearchOutputConnector.ContentsTabName=CloudSearch Contents
+AmazonCloudSearchOutputConnector.FieldMappings=Field Mappings
+AmazonCloudSearchOutputConnector.MetadataFieldName=Metadata Field Name
+AmazonCloudSearchOutputConnector.CloudSearchFieldName=CloudSearch Field Name
+AmazonCloudSearchOutputConnector.DeleteFieldMapping=Delete field mapping
+AmazonCloudSearchOutputConnector.AddFieldMapping=Add field mapping
+AmazonCloudSearchOutputConnector.KeepAllMetadata=Keep all metadata:
+AmazonCloudSearchOutputConnector.Add=Add
+AmazonCloudSearchOutputConnector.NoFieldMappingSpecified=No field mapping specified
+AmazonCloudSearchOutputConnector.MaxFileSizeBytesColon=Max file size (bytes):
+AmazonCloudSearchOutputConnector.AllowedMIMETypesColon=Allowed MIME types:
+AmazonCloudSearchOutputConnector.AllowedFileExtensionsColon=Allowed file extensions:

Modified: manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/native2ascii/org/apache/manifoldcf/agents/output/amazoncloudsearch/common_ja_JP.properties
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/native2ascii/org/apache/manifoldcf/agents/output/amazoncloudsearch/common_ja_JP.properties?rev=1592916&r1=1592915&r2=1592916&view=diff
==============================================================================
--- manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/native2ascii/org/apache/manifoldcf/agents/output/amazoncloudsearch/common_ja_JP.properties (original)
+++ manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/native2ascii/org/apache/manifoldcf/agents/output/amazoncloudsearch/common_ja_JP.properties Tue May  6 22:43:25 2014
@@ -22,3 +22,16 @@ AmazonCloudSearchOutputConnector.ProxyPo
 AmazonCloudSearchOutputConnector.ServerHostCannotBeNull=サーバー名は必須です。
 AmazonCloudSearchOutputConnector.ServerPathMustStartWithSlash=パスは / から入力してください。
 AmazonCloudSearchOutputConnector.ProxyPortMustBeAnInteger=プロキシ ポートは数値を入力してください。
+AmazonCloudSearchOutputConnector.FieldMappingTabName=CloudSearch フィールドマッピング
+AmazonCloudSearchOutputConnector.ContentsTabName=CloudSearch コンテンツ
+AmazonCloudSearchOutputConnector.FieldMappings=フィールドマッピング
+AmazonCloudSearchOutputConnector.MetadataFieldName=メタデータフィールド名
+AmazonCloudSearchOutputConnector.CloudSearchFieldName=CloudSearch フィールド名
+AmazonCloudSearchOutputConnector.DeleteFieldMapping=フィールドマッピングを削除
+AmazonCloudSearchOutputConnector.AddFieldMapping=フィールドマッピングを追加
+AmazonCloudSearchOutputConnector.KeepAllMetadata=全てのメタデータを保持する:
+AmazonCloudSearchOutputConnector.Add=追加
+AmazonCloudSearchOutputConnector.NoFieldMappingSpecified=フィールドマッピングを入力してください
+AmazonCloudSearchOutputConnector.MaxFileSizeBytesColon=最大ファイルサイズ (バイト):
+AmazonCloudSearchOutputConnector.AllowedMIMETypesColon=利用可能なMIMEタイプ:
+AmazonCloudSearchOutputConnector.AllowedFileExtensionsColon=利用可能なファイル拡張子:

Modified: manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/resources/org/apache/manifoldcf/agents/output/amazoncloudsearch/editSpecification.html
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/resources/org/apache/manifoldcf/agents/output/amazoncloudsearch/editSpecification.html?rev=1592916&r1=1592915&r2=1592916&view=diff
==============================================================================
--- manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/resources/org/apache/manifoldcf/agents/output/amazoncloudsearch/editSpecification.html (original)
+++ manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/resources/org/apache/manifoldcf/agents/output/amazoncloudsearch/editSpecification.html Tue May  6 22:43:25 2014
@@ -15,3 +15,36 @@
  limitations under the License.
 -->
 
+#if($TabName == $ResourceBundle.getString('AmazonCloudSearchOutputConnector.ContentsTabName'))
+
+<table class="displaytable">
+  <tr>
+    <td class="description">
+      <nobr>$Encoder.bodyEscape($ResourceBundle.getString('AmazonCloudSearchOutputConnector.MaxFileSizeBytesColon'))</nobr>
+    </td>
+    <td class="value"><input name="maxfilesize" type="text"
+      value="$Encoder.attributeEscape($MAXFILESIZE)" size="24" /></td>
+  </tr>
+  <tr>
+    <td class="description">
+      <nobr>$Encoder.bodyEscape($ResourceBundle.getString('AmazonCloudSearchOutputConnector.AllowedMIMETypesColon'))</nobr>
+    </td>
+    <td class="value">
+      <textarea rows="10" cols="64" name="mimetypes">$Encoder.bodyEscape($MIMETYPES)</textarea>
+    </td>
+  </tr>
+  <tr>
+    <td class="description"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('AmazonCloudSearchOutputConnector.AllowedFileExtensionsColon'))</nobr></td>
+    <td class="value">
+      <textarea rows="10" cols="12" name="extensions">$Encoder.bodyEscape($EXTENSIONS)</textarea>
+    </td>
+  </tr>
+</table>
+
+#else
+
+<input type="hidden" name="maxfilesize" value="$Encoder.attributeEscape($MAXFILESIZE)" />
+<input type="hidden" name="mimetypes" value="$Encoder.attributeEscape($MIMETYPES)" />
+<input type="hidden" name="extensions" value="$Encoder.attributeEscape($EXTENSIONS)" />
+
+#end

Modified: manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/resources/org/apache/manifoldcf/agents/output/amazoncloudsearch/editSpecification.js
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/resources/org/apache/manifoldcf/agents/output/amazoncloudsearch/editSpecification.js?rev=1592916&r1=1592915&r2=1592916&view=diff
==============================================================================
--- manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/resources/org/apache/manifoldcf/agents/output/amazoncloudsearch/editSpecification.js (original)
+++ manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/resources/org/apache/manifoldcf/agents/output/amazoncloudsearch/editSpecification.js Tue May  6 22:43:25 2014
@@ -15,3 +15,37 @@
  limitations under the License.
 -->
 
+<script type="text/javascript">
+<!--
+function checkOutputSpecification()
+{
+  return true;
+}
+
+function addFieldMapping()
+{
+  if (editjob.cloudsearch_fieldmapping_source.value == "")
+  {
+    alert("$Encoder.bodyEscape($ResourceBundle.getString('AmazonCloudSearchOutputConnector.NoFieldMappingSpecified'))");
+    editjob.solr_fieldmapping_source.focus();
+    return;
+  }
+  editjob.cloudsearch_fieldmapping_op.value="Add";
+  postFormSetAnchor("cloudsearch_fieldmapping");
+}
+
+function deleteFieldMapping(i)
+{
+  // Set the operation
+  eval("editjob.cloudsearch_fieldmapping_"+i+"_op.value=\"Delete\"");
+  // Submit
+  if (editjob.cloudsearch_fieldmapping_count.value==i)
+    postFormSetAnchor("cloudsearch_fieldmapping");
+  else
+    postFormSetAnchor("cloudsearch_fieldmapping_"+i)
+  // Undo, so we won't get two deletes next time
+  eval("editjob.cloudsearch_fieldmapping_"+i+"_op.value=\"Continue\"");
+}
+
+//-->
+</script>

Modified: manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/resources/org/apache/manifoldcf/agents/output/amazoncloudsearch/viewSpecification.html
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/resources/org/apache/manifoldcf/agents/output/amazoncloudsearch/viewSpecification.html?rev=1592916&r1=1592915&r2=1592916&view=diff
==============================================================================
--- manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/resources/org/apache/manifoldcf/agents/output/amazoncloudsearch/viewSpecification.html (original)
+++ manifoldcf/branches/CONNECTORS-916/connectors/amazoncloudsearch/connector/src/main/resources/org/apache/manifoldcf/agents/output/amazoncloudsearch/viewSpecification.html Tue May  6 22:43:25 2014
@@ -15,3 +15,17 @@
  limitations under the License.
 -->
 
+<table class="displaytable">
+  <tr>
+    <td class="description"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('AmazonCloudSearchOutputConnector.MaxFileSizeBytesColon'))</nobr></td>
+    <td class="value">$Encoder.bodyEscape($MAXFILESIZE)</td>
+  </tr>
+  <tr>
+    <td class="description"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('AmazonCloudSearchOutputConnector.AllowedMIMETypesColon'))</nobr></td>
+    <td class="value">$Encoder.bodyEscape($MIMETYPES)</td>
+  </tr>
+  <tr>
+    <td class="description"><nobr>$Encoder.bodyEscape($ResourceBundle.getString('AmazonCloudSearchOutputConnector.AllowedFileExtensionsColon'))</nobr></td>
+    <td class="value">$Encoder.bodyEscape($EXTENSIONS)</td>
+  </tr>
+</table>