Package com.google.feedserver.tools

Source Code of com.google.feedserver.tools.FeedServerClientTool

/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.feedserver.tools;

import com.google.feedserver.client.TypelessFeedServerClient;
import com.google.feedserver.util.CommonsCliHelper;
import com.google.feedserver.util.FeedServerClientException;
import com.google.feedserver.util.FileUtil;
import com.google.gdata.client.GoogleService;
import com.google.gdata.util.AuthenticationException;

import org.apache.commons.lang.StringEscapeUtils;

import java.io.Console;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Generic Google Feed Server Client Tool. See files in resources/clientTool for
* examples of how to invoke it with various command line arguments and the
* format of the input files.
*
*/
public class FeedServerClientTool {

  public static final String OPERATION_GET_FEED = "getFeed";
  public static final String OPERATION_GET_ENTRY = "getEntry";
  public static final String OPERATION_INSERT = "insert";
  public static final String OPERATION_UPDATE = "update";
  public static final String OPERATION_DELETE = "delete";
  public static final String OPERATION_INSERT_GADGETSPEC = "insertGadgetSpec";
  public static final String OPERATION_UPDATE_GADGETSPEC = "updateGadgetSpec";
  public static final String ALL_OPERATIONS =
      OPERATION_GET_FEED + ", " + OPERATION_GET_ENTRY + ", " + OPERATION_INSERT + ", "
          + OPERATION_UPDATE + OPERATION_DELETE + OPERATION_INSERT_GADGETSPEC + " or "
          + OPERATION_UPDATE_GADGETSPEC;

  public static String url_FLAG = null;
  public static String url_HELP = "URL to feed or entry";

  public static String op_FLAG = null;
  public static String op_HELP = "Operation to perform on feed or entry (" + ALL_OPERATIONS + ")";

  public static String entryFilePath_FLAG = null;
  public static String entryFilePath_HELP = "Path to Atom XML file to insert or update";

  public static String username_FLAG = null;
  public static String username_HELP =
      "Optional user name used for login. " + "Can be entered on console";

  public static String password_FLAG = null;
  public static String password_HELP =
      "Optional password used for login. " + "Can be entered on console";

  public static String authnURL_FLAG = null;
  public static String authnURL_HELP =
      "The URL of the server that will handle authentication and return a token to be used with every request. The format is host:portNo";
  public static String authnURLProtocol_FLAG = "http";
  public static String authnURLProtocol_HELP =
      "Optional. The default protocol assumed is 'http'." + "Explicitly specify if its 'https'";

  public static String serviceName_FLAG = null;
  public static String serviceName_HELP =
      "The name of the service with which the user account is associated with";

  public static String gadgetName_FLAG = null;
  public static String gadgetName_HELP = "The name of the gadget";

  public static String gadgetSpecFile_FLAG = null;
  public static String gadgetSpecFile_HELP = "The path of the gadget spec xml file";

  public static String gadgetSpecEntityFile_FLAG = null;
  public static String gadgetSpecEntityFile_HELP =
      "The gadget spec entity file. This will define the feed entry schema used for storing gadget specs";

  public static final int TAB_STOP = 2;

  protected TypelessFeedServerClient feedServerClient;
  protected ThreadLocal<Integer> indentation;
  protected FileUtil fileUtil = new FileUtil();

  public static void main(String[] args) throws Exception {
    FeedServerClientTool tool = new FeedServerClientTool();
    tool.run(args);
  }

  public FeedServerClientTool() {
    indentation = new ThreadLocal<Integer>();
    indentation.set(0);
  }

  public FeedServerClientTool(TypelessFeedServerClient feedServerClient) {
    // initialize indentation for print result
    indentation = new ThreadLocal<Integer>();
    indentation.set(0);
    this.feedServerClient = feedServerClient;
  }

  public void run(String[] args) {
    try {
    // register command line flags
    CommonsCliHelper cliHelper = createClientHelper(args, getClass());

    checkServiceAndAuthNParams(cliHelper);

    // Process the request
    processRequest(cliHelper);
    } catch(Exception e) {
      System.err.println("Error: " + e.getMessage());
    }
  }

  /**
   * Creates a client helper for the given command line arguments and the given
   * class
   *
   * @param args The command line arguments
   * @param clazz The class that will process the command line arguments
   * @return The client helper
   */
  @SuppressWarnings("unchecked")
  protected CommonsCliHelper createClientHelper(String[] args, Class clazz) {
    CommonsCliHelper cliHelper = new CommonsCliHelper();
    cliHelper.register(clazz);
    cliHelper.parse(args);

    return cliHelper;
  }

  /**
   * Processes the request by forwarding the request to appropriate methods
   * matching the specified operation
   *
   * @param cliHelper The client helper for retrieving the required paramater
   *        values
   * @throws FeedServerClientException
   * @throws MalformedURLException
   * @throws IOException
   * @throws AuthenticationException
   */
  protected void processRequest(CommonsCliHelper cliHelper) throws FeedServerClientException,
      MalformedURLException, IOException, AuthenticationException {
    // Check and process the specified request
    if (OPERATION_GET_FEED.equals(op_FLAG)) {
      getUserCredentials();
      printFeed(getFeed(url_FLAG));
    } else if (OPERATION_GET_ENTRY.equals(op_FLAG)) {
      getUserCredentials();
      printEntry(getEntry(url_FLAG));
    } else if (OPERATION_INSERT.equals(op_FLAG)) {
      getUserCredentials();
      printEntry(insert(url_FLAG, readFile(new File(entryFilePath_FLAG))));
    } else if (OPERATION_UPDATE.equals(op_FLAG)) {
      getUserCredentials();
      printEntry(update(url_FLAG, readFile(new File(entryFilePath_FLAG))));
    } else if (OPERATION_DELETE.equals(op_FLAG)) {
      getUserCredentials();
      delete(url_FLAG);
    } else if (OPERATION_INSERT_GADGETSPEC.equals(op_FLAG)) {
      getUserCredentials();
      printEntry(insert(url_FLAG, constructGadgetSpecEntryXml(gadgetSpecEntityFile_FLAG,
          gadgetName_FLAG, gadgetSpecFile_FLAG)));
    } else if (OPERATION_UPDATE_GADGETSPEC.equals(op_FLAG)) {
      getUserCredentials();
      printEntry(update(url_FLAG, constructGadgetSpecEntryXml(gadgetSpecEntityFile_FLAG,
          gadgetName_FLAG, gadgetSpecFile_FLAG)));
    } else {
      if (op_FLAG != null) {
        System.err.println("Unknown operation.  Must use " + ALL_OPERATIONS + ".");
      }
      cliHelper.usage();
    }
  }

  /**
   * Checks that the user has specified the service and authn parameters
   *
   * @param cliHelper The client helper for retrieving the required paramater
   *        values
   */
  protected void checkServiceAndAuthNParams(CommonsCliHelper cliHelper) {
    // Check for the URL to be connected for authenticating and getting the
    // authZ token
    if (authnURL_FLAG == null) {
      System.err.println("Must specify the URL of the server that will handle authentication");
      cliHelper.usage();
      return;
    }

    // Check for the URL to be connected for authenticating and getting the
    // authZ token
    if (serviceName_FLAG == null) {
      System.err.println("Must specify the service name that will be used to authenticate users");
      cliHelper.usage();
      return;
    }

    // Initialize the feedserver client with the given authN URL and protocol
    this.feedServerClient =
        new TypelessFeedServerClient(new GoogleService(serviceName_FLAG, FeedServerClientTool.class
            .getName(), authnURLProtocol_FLAG, authnURL_FLAG));
  }

  /**
   * Gets user name and password from command line, or if missing, from console
   * and sets it on FeedServer client
   *
   * @throws AuthenticationException
   */
  protected void getUserCredentials() throws AuthenticationException {
    String username = username_FLAG;

    while (username == null || username.trim().isEmpty()) {
      getConsole().printf("The username cannot be null or blank");
      username = getConsole().readLine("\nUsername: ");
    }

    String password = password_FLAG;

    while (password == null || password.trim().isEmpty()) {
      getConsole().printf("The password cannot be null or blank");
      password = new String(getConsole().readPassword("\nPassword: "));
    }

    feedServerClient.setUserCredentials(username, password);
  }

  protected Console getConsole() {
    Console console = System.console();
    if (console == null) {
      throw new NullPointerException("no console");
    } else {
      return console;
    }
  }

  /**
   * Gets a feed at the given URL
   *
   * @param url URL of the feed
   * @return A feed of entries as a List of Maps
   * @throws MalformedURLException
   * @throws FeedServerClientException
   */
  public List<Map<String, Object>> getFeed(String url) throws MalformedURLException,
      FeedServerClientException {
    return feedServerClient.getEntries(new URL(url));
  }

  /**
   * Gets an entry at the given URL
   *
   * @param url URL of the entry
   * @return The entity as a Map
   * @throws MalformedURLException
   * @throws FeedServerClientException
   */
  public Map<String, Object> getEntry(String url) throws MalformedURLException,
      FeedServerClientException {
    return feedServerClient.getEntry(new URL(url));
  }

  /**
   * Inserts a new entry into a feed given a file containing its Atom XML
   * representation
   *
   * @param url URL to the feed
   * @param entryFile File containing the Atom XML representation of the new
   *        entry
   * @return The inserted entity as a Map
   * @throws IOException
   * @throws FeedServerClientException
   * @throws MalformedURLException
   */
  public Map<String, Object> insert(String url, File entryFile) throws IOException,
      FeedServerClientException, MalformedURLException {
    return insert(url, readFile(entryFile));
  }

  /**
   * Inserts a new entry into a feed given its Atom XML representation
   *
   * @param url URL to the feed
   * @param entryXml Atom XML representation of the new entry
   * @return The inserted entity as a Map
   * @throws IOException
   * @throws FeedServerClientException
   * @throws MalformedURLException
   */
  public Map<String, Object> insert(String url, String entryXml) throws IOException,
      FeedServerClientException, MalformedURLException {
    return insert(url, feedServerClient.getMapFromXml(entryXml));
  }

  /**
   * Inserts a new entry into a feed given the entry as a Map
   *
   * @param url URL to the feed
   * @param entity Entity to insert into feed
   * @return The inserted entity as a Map
   * @throws IOException
   * @throws FeedServerClientException
   * @throws MalformedURLException
   */
  public Map<String, Object> insert(String url, Map<String, Object> entity) throws IOException,
      FeedServerClientException, MalformedURLException {
    return feedServerClient.insertEntry(new URL(url), entity);
  }

  /**
   * Updates an entry given the file to its Atom XML representation
   *
   * @param url URL to the entry
   * @param entryFile File containing the Atom XML representation of the new
   *        entry
   * @return Updated entity as a Map
   * @throws IOException
   * @throws FeedServerClientException
   * @throws MalformedURLException
   */
  public Map<String, Object> update(String url, File entryFile) throws IOException,
      FeedServerClientException, MalformedURLException {
    return update(url, readFile(entryFile));
  }

  /**
   * Updates an entry given its Atom XML representation
   *
   * @param url URL to the entry
   * @param entryXml Atom XML representation of the entry
   * @return Updated entity as a Map
   * @throws IOException
   * @throws FeedServerClientException
   * @throws MalformedURLException
   */
  public Map<String, Object> update(String url, String entryXml) throws IOException,
      FeedServerClientException, MalformedURLException {
    return update(url, feedServerClient.getMapFromXml(entryXml));
  }

  /**
   * Updates an entry given its entity
   *
   * @param url URL to entry
   * @param entity Entity to update to for the entry
   * @return Updated entity as a Map
   * @throws IOException
   * @throws FeedServerClientException
   * @throws MalformedURLException
   */
  public Map<String, Object> update(String url, Map<String, Object> entity) throws IOException,
      FeedServerClientException, MalformedURLException {
    return feedServerClient.updateEntry(new URL(url), entity);
  }

  /**
   * Deletes an entry at the give URL
   *
   * @param url URL to the entry to delete
   * @throws FeedServerClientException
   * @throws MalformedURLException
   */
  public void delete(String url) throws FeedServerClientException, MalformedURLException {
    feedServerClient.deleteEntry(new URL(url));
  }

  /**
   * Prints a feed
   *
   * @param feed Feed to print as a List of Maps
   */
  public void printFeed(List<Map<String, Object>> feed) {
    printFeed(feed, System.out);
  }

  /**
   * Prints a feed on a stream
   *
   * @param feed Feed to print
   * @param out Stream to print on
   */
  public void printFeed(List<Map<String, Object>> feed, PrintStream out) {
    if (feed == null) {
      println(out, "Resource not found");
    } else {
      println(out, "<entities>");
      indentMore();
      for (Map<String, Object> entry : feed) {
        printEntry(entry, out);
      }
      indentLess();
      println(out, "</entities>");
    }
  }

  protected void printList(List<Map<String, Object>> feed) {
    printList(feed, System.out);
  }

  protected void printList(List<Map<String, Object>> feed, PrintStream out) {
    for (Map<String, Object> entry : feed) {
      printMap(entry, out);
    }
  }

  /**
   * Prints an entry
   *
   * @param entry Entry to print
   */
  public void printEntry(Map<String, Object> entry) {
    printEntry(entry, System.out);
  }

  /**
   * Prints an entry on a stream
   *
   * @param entry Entry to print
   * @param out Stream to print on
   */
  public void printEntry(Map<String, Object> entry, PrintStream out) {
    if (entry == null) {
      println(out, "Resource not found");
    } else {
      println(out, "<entity>");
      indentMore();
      printMap(entry);
      indentLess();
      println(out, "</entity>");
    }
  }

  /**
   * Prints error message on error output.
   * @param message Message to print
   */
  public void printError(String message) {
    System.err.println("Error: " + message);
  }

  protected void printMap(Map<String, Object> entry) {
    printMap(entry, System.out);
  }

  protected void printMap(Map<String, Object> entity, PrintStream out) {
    for (Map.Entry<String, Object> e : entity.entrySet()) {
      printProperty(e.getKey(), e.getValue(), out);
    }
  }

  protected void printProperty(Map<String, Object> entity, String name, PrintStream out) {
    printProperty(name, entity.get(name), out);
  }

  @SuppressWarnings("unchecked")
  protected void printProperty(String name, Object value, PrintStream out) {
    if (value != null && value instanceof Object[]) {
      Object[] values = (Object[]) value;
      for (int i = 0; i < values.length; i++) {
        print(out, "<" + name + (i == 0 ? " repeatable=\"true\"" : "") + ">");
        if (values[i] instanceof Map) {
          out.println();
          indentMore();
          printMap((Map<String, Object>) values[i], out);
          indentLess();
        } else {
          out.print(values[i] == null ? "" : StringEscapeUtils.escapeXml(values[i].toString()));
        }
        println(out, "</" + name + ">");
      }
    } else if (value != null && value instanceof Map) {
      println(out, "<" + name + ">");
      indentMore();
      printMap((Map<String, Object>) value, out);
      indentLess();
      println(out, "</" + name + ">");
    } else {
      print(out, "<" + name + ">");
      out.print(value == null ? "" : StringEscapeUtils.escapeXml(value.toString()));
      out.println("</" + name + ">");
    }
  }

  protected void indentMore() {
    indentation.set(indentation.get() + TAB_STOP);
  }

  protected void indentLess() {
    indentation.set(indentation.get() - TAB_STOP);
  }

  protected void printIndentation(PrintStream out) {
    for (int i = 0; i < indentation.get(); i++) {
      out.print(' ');
    }
  }

  protected void print(PrintStream out, String s) {
    printIndentation(out);
    out.print(s);
  }

  protected void println(PrintStream out, String s) {
    printIndentation(out);
    out.println(s);
  }

  /**
   * Helper function that reads contents of specified file into a String.
   *
   * @param file File to read.
   * @return string with file contents.
   * @throws IOException if any file operations fail.
   */
  protected String readFile(File file) throws IOException {
    return resolveEmbeddedFiles(fileUtil.readFileContents(file), file.getParentFile());
  }

  /**
   * The pattern to get the name tag in the feed schema
   */
  protected final static Pattern gadgetSpecNameTag = Pattern.compile("<name>.*?</name>");

  /**
   * The pattern to get the speccontent tag in the feed schema
   */
  protected final static Pattern gadgetSpecSpecContentTag =
      Pattern.compile("<specContent>.*?</specContent>");

  /**
   * The file path indicator
   */
  protected final static String FILE_PATH_INDICATOR = "@";

  /**
   * Constructs the gadget spec entry that will be used for creating a new entry
   * or updating an existing entry
   *
   * @param gadgetSpecEntityFile The gadget spec entity file which serves as the
   *        feed schema for the the gadget entry
   * @param gadgetName The gadget name
   * @param gadgetSpecFilePath The gadget spec file path
   * @return The gadget spec entry xml
   * @throws IOException If any exceptions are encountered
   */
  protected String constructGadgetSpecEntryXml(String gadgetSpecEntityFile, String gadgetName,
      String gadgetSpecFilePath) throws IOException {

    while (gadgetName == null || gadgetName.trim().isEmpty()) {
      getConsole().printf("The gadget name cannot be null or blank");
      gadgetName = getConsole().readLine("\nGadget name: ");
    }

    while (gadgetSpecFilePath == null || gadgetSpecFilePath.trim().isEmpty()) {
      getConsole().printf("The gadget spec file cannot be null or blank");
      gadgetName = getConsole().readLine("\nGadget spec file: ");
    }

    // Get the gadget spec feed schema
    File file = new File(gadgetSpecEntityFile);
    String gadgetSpecXml = fileUtil.readFileContents(file);
    StringBuilder fileContents = new StringBuilder();

    int lastStart = 0;

    // Add the given gadget name in the feed schema
    for (Matcher matcher = gadgetSpecNameTag.matcher(gadgetSpecXml); matcher.find();) {
      fileContents.append(gadgetSpecXml.substring(0, matcher.start() + 6));
      fileContents.append(gadgetName);
      lastStart = matcher.end() - 7;
    }

    // Add the given gadget file path in the feed schema
    for (Matcher matcher = gadgetSpecSpecContentTag.matcher(gadgetSpecXml); matcher.find();) {
      fileContents.append(gadgetSpecXml.substring(lastStart, lastStart + 7));
      lastStart += 7;
      fileContents.append(gadgetSpecXml.substring(lastStart, matcher.start() + 13));
      fileContents.append(FILE_PATH_INDICATOR).append(gadgetSpecFilePath);
      lastStart = matcher.end() - 14;
    }

    fileContents.append(gadgetSpecXml.substring((lastStart)));

    // Get the final gadget spec entry xml
    return resolveEmbeddedFiles(fileContents.toString(), file.getParentFile());
  }

  /**
   * Reads a file and returns its content as a string
   *
   * @param directory Directory relative to which the file is
   * @param filePath Path to file relative to directory
   * @return Content of file
   * @throws IOException
   */
  protected String readFile(File directory, String filePath) throws IOException {
    File file = new File(directory, filePath);
    return readFile(file);
  }

  /**
   * Pattern for embedded file path
   */
  protected final static Pattern embeddedFilePathPattern = Pattern.compile(">@.*?<");

  /**
   * Replaces all occurrences of ">@embeddedFilePath<" with ">the XML escaped
   * content of
   * embeddedFilePath<".  For example, if file "abc.xml"'s content is "
   * <abc>value</abc>", then "<xyz>@abc.xml</xyz>" becomes
   * "<xyz>&lt;abc&gt;value&lt;/abc&gt;".
   *
   * @param content Input content
   * @param directory Directory where embedded files are to be found
   * @return Content with all content of embedded files
   * @throws IOException
   */
  protected String resolveEmbeddedFiles(String content, File directory) throws IOException {
    StringBuilder builder = new StringBuilder();
    int lastStart = 0;
    for (Matcher matcher = embeddedFilePathPattern.matcher(content); matcher.find();) {
      // add before embedded file
      builder.append(content.substring(lastStart, matcher.start() + 1));

      // add embedded file
      String group = matcher.group();
      String embeddedFilePath = group.substring(2, group.length() - 1);
      String embeddedFileContent = readFile(directory, embeddedFilePath);
      builder.append(StringEscapeUtils.escapeXml(embeddedFileContent));

      lastStart = matcher.end() - 1;
    }
    builder.append(content.substring(lastStart));

    return builder.toString();
  }
}
TOP

Related Classes of com.google.feedserver.tools.FeedServerClientTool

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.