Author: jcian
Date: Tue Nov 15 16:25:34 2011
New Revision: 1202283

URL: http://svn.apache.org/viewvc?rev=1202283&view=rev
Log:
SHINDIG-1660: Allow ContainerConfig stack to load property values from external 
resources and update BlobCrypterSecurityTokenCodec to use this new feature.

Added:
    
shindig/trunk/java/common/src/test/resources/classpath-accessible-test-file.txt
Modified:
    shindig/trunk/config/container.js
    
shindig/trunk/java/common/src/main/java/org/apache/shindig/auth/BlobCrypterSecurityTokenCodec.java
    
shindig/trunk/java/common/src/main/java/org/apache/shindig/auth/DefaultSecurityTokenCodec.java
    
shindig/trunk/java/common/src/main/java/org/apache/shindig/common/util/ResourceLoader.java
    
shindig/trunk/java/common/src/main/java/org/apache/shindig/config/JsonContainerConfigLoader.java
    
shindig/trunk/java/common/src/test/java/org/apache/shindig/auth/BlobCrypterSecurityTokenCodecTest.java
    
shindig/trunk/java/common/src/test/java/org/apache/shindig/auth/DefaultSecurityTokenCodecTest.java
    
shindig/trunk/java/common/src/test/java/org/apache/shindig/config/JsonContainerConfigLoaderTest.java

Modified: shindig/trunk/config/container.js
URL: 
http://svn.apache.org/viewvc/shindig/trunk/config/container.js?rev=1202283&r1=1202282&r2=1202283&view=diff
==============================================================================
--- shindig/trunk/config/container.js (original)
+++ shindig/trunk/config/container.js Tue Nov 15 16:25:34 2011
@@ -44,6 +44,9 @@
 
 // Container must be an array; this allows multiple containers
 // to share configuration.
+
+// Note that you can embed values directly or you can choose to have values 
read from a file on disk
+// or read from the classpath ("foo-key" : "file:///foo-file.txt" || "foo-key" 
: "res://foo-file.txt")
 // TODO: Move out accel container config into a separate accel.js file.
 {"gadgets.container" : ["default", "accel"],
 
@@ -88,22 +91,23 @@
 // Callback URL.  Scheme relative URL for easy switch between https/http.
 "gadgets.uri.oauth.callbackTemplate" : 
"//%host%${CONTEXT_ROOT}/gadgets/oauthcallback",
 
-// Use an insecure security token by default
-"gadgets.securityTokenType" : "insecure",
-
 // Config param to load Opensocial data for social
 // preloads in data pipelining.  %host% will be
 // substituted with the current host.
 "gadgets.osDataUri" : "http://%host%${CONTEXT_ROOT}/rpc";,
 
-// Uncomment these to switch to a secure version. If both a key file and key 
are provided, the key
-// will take precedence; thus, to use a key file, you must explicitly not 
provide a key. The
-// best way to generate a key is to do something like this:
+// Use an insecure security token by default
+"gadgets.securityTokenType" : "insecure",
+
+// Uncomment the securityTokenType and one of the securityTokenKey's to switch 
to a secure version.
+// Note that you can choose to use an embedded key, a filesystem reference or 
a classpath reference.
+// The best way to generate a key is to do something like this:
 // dd if=/dev/random bs=32 count=1 | openssl base64
 //
-// "gadgets.securityTokenType" : "secure",
-// "gadgets.securityTokenKeyFile" : "/path/to/key/file.txt",
-// "gadgets.securityTokenKey" : "",
+//"gadgets.securityTokenType" : "secure",
+//"gadgets.securityTokenKey" : "default-insecure-embedded-key",
+//"gadgets.securityTokenKey" : "file:///path/to/key/file.txt",
+//"gadgets.securityTokenKey" : "res://some-file-on-the-classpath.txt",
 
 // OS 2.0 Gadget DOCTYPE: used in Gadgets with @specificationVersion 2.0 or 
greater and
 // quirksmode on Gadget has not been set.

Modified: 
shindig/trunk/java/common/src/main/java/org/apache/shindig/auth/BlobCrypterSecurityTokenCodec.java
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/common/src/main/java/org/apache/shindig/auth/BlobCrypterSecurityTokenCodec.java?rev=1202283&r1=1202282&r2=1202283&view=diff
==============================================================================
--- 
shindig/trunk/java/common/src/main/java/org/apache/shindig/auth/BlobCrypterSecurityTokenCodec.java
 (original)
+++ 
shindig/trunk/java/common/src/main/java/org/apache/shindig/auth/BlobCrypterSecurityTokenCodec.java
 Tue Nov 15 16:25:34 2011
@@ -24,15 +24,12 @@ import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.shindig.common.crypto.BasicBlobCrypter;
 import org.apache.shindig.common.crypto.BlobCrypter;
 import org.apache.shindig.common.crypto.BlobCrypterException;
-import org.apache.shindig.common.util.ResourceLoader;
 import org.apache.shindig.config.ContainerConfig;
 
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.Maps;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
@@ -56,8 +53,6 @@ import com.google.inject.Singleton;
 public class BlobCrypterSecurityTokenCodec implements SecurityTokenCodec, 
ContainerConfig.ConfigObserver {
   private static final Logger LOG = 
Logger.getLogger(BlobCrypterSecurityTokenCodec.class.getName());
 
-  public static final String SECURITY_TOKEN_KEY_FILE = 
"gadgets.securityTokenKeyFile";
-
   public static final String SECURITY_TOKEN_KEY = "gadgets.securityTokenKey";
 
   public static final String SIGNED_FETCH_DOMAIN = "gadgets.signedFetchDomain";
@@ -109,14 +104,10 @@ public class BlobCrypterSecurityTokenCod
   private void loadContainers(ContainerConfig config, Collection<String> 
containers,
       Map<String, BlobCrypter> crypters, Map<String, String> domains) throws 
IOException {
     for (String container : containers) {
-      String keyFile = config.getString(container, SECURITY_TOKEN_KEY_FILE);
       String key = config.getString(container, SECURITY_TOKEN_KEY);
       if (key != null) {
         BlobCrypter crypter = loadCrypter(key);
         crypters.put(container, crypter);
-      } else if (keyFile != null) {
-        BlobCrypter crypter = loadCrypter(getKeyFromFile(keyFile));
-        crypters.put(container, crypter);
       }
       String domain = config.getString(container, SIGNED_FETCH_DOMAIN);
       domains.put(container, domain);
@@ -124,26 +115,13 @@ public class BlobCrypterSecurityTokenCod
   }
 
   /**
-   * Gets a key from the given keyFile.
-   *
-   * @param keyFile the key file from which to read the key
-   * @return the key
-   * @throws IOException if there was an error read the key file
-   */
-  @VisibleForTesting
-  protected String getKeyFromFile(String keyFile) throws IOException {
-    return IOUtils.toString(ResourceLoader.open(keyFile), "UTF-8");
-  }
-
-  /**
-   * Load a BlobCrypter from the key file.  Override this if you have your own
-   * BlobCrypter implementation.
+   * Load a BlobCrypter using the specified key.  Override this if you have 
your own BlobCrypter
+   * implementation.
    *
-   * @param key The key to use for encryption
+   * @param key The security token key.
    * @return The BlobCrypter.
-   * @throws IOException If the key file is invalid.
    */
-  protected BlobCrypter loadCrypter(String key) throws IOException {
+  protected BlobCrypter loadCrypter(String key) {
     return new BasicBlobCrypter(key);
   }
 

Modified: 
shindig/trunk/java/common/src/main/java/org/apache/shindig/auth/DefaultSecurityTokenCodec.java
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/common/src/main/java/org/apache/shindig/auth/DefaultSecurityTokenCodec.java?rev=1202283&r1=1202282&r2=1202283&view=diff
==============================================================================
--- 
shindig/trunk/java/common/src/main/java/org/apache/shindig/auth/DefaultSecurityTokenCodec.java
 (original)
+++ 
shindig/trunk/java/common/src/main/java/org/apache/shindig/auth/DefaultSecurityTokenCodec.java
 Tue Nov 15 16:25:34 2011
@@ -18,6 +18,7 @@
  */
 package org.apache.shindig.auth;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
@@ -75,6 +76,11 @@ public class DefaultSecurityTokenCodec i
     return codec.encodeToken(token);
   }
 
+  @VisibleForTesting
+  protected SecurityTokenCodec getCodec() {
+    return codec;
+  }
+
   public int getTokenTimeToLive() {
     return codec.getTokenTimeToLive();
   }

Modified: 
shindig/trunk/java/common/src/main/java/org/apache/shindig/common/util/ResourceLoader.java
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/util/ResourceLoader.java?rev=1202283&r1=1202282&r2=1202283&view=diff
==============================================================================
--- 
shindig/trunk/java/common/src/main/java/org/apache/shindig/common/util/ResourceLoader.java
 (original)
+++ 
shindig/trunk/java/common/src/main/java/org/apache/shindig/common/util/ResourceLoader.java
 Tue Nov 15 16:25:34 2011
@@ -31,19 +31,24 @@ import java.io.InputStream;
  * Handles loading contents from resource and file system files.
  */
 public final class ResourceLoader {
+  public static final String RESOURCE_PREFIX = "res://";
+  public static final String FILE_PREFIX = "file://";
+
   private ResourceLoader() {}
   /**
    * Opens a given path as either a resource or a file, depending on the path
    * name.
    *
    * If path starts with res://, we interpret it as a resource.
-   * Otherwise we attempt to load it as a file.
+   * If path starts with file://, or path has no prefix, we interpret it as a 
file.
    * @param path
    * @return The opened input stream
    */
   public static InputStream open(String path) throws IOException {
-    if (path.startsWith("res://")) {
-      return openResource(path.substring(6));
+    if (path.startsWith(RESOURCE_PREFIX)) {
+      return openResource(path.substring(RESOURCE_PREFIX.length()));
+    } else if (path.startsWith(FILE_PREFIX)) {
+      path = path.substring(FILE_PREFIX.length());
     }
     File file = new File(path);
     return new FileInputStream(file);

Modified: 
shindig/trunk/java/common/src/main/java/org/apache/shindig/config/JsonContainerConfigLoader.java
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/common/src/main/java/org/apache/shindig/config/JsonContainerConfigLoader.java?rev=1202283&r1=1202282&r2=1202283&view=diff
==============================================================================
--- 
shindig/trunk/java/common/src/main/java/org/apache/shindig/config/JsonContainerConfigLoader.java
 (original)
+++ 
shindig/trunk/java/common/src/main/java/org/apache/shindig/config/JsonContainerConfigLoader.java
 Tue Nov 15 16:25:34 2011
@@ -25,6 +25,7 @@ import com.google.common.collect.Immutab
 import com.google.common.collect.Lists;
 
 import com.google.common.collect.Maps;
+import org.apache.commons.io.IOUtils;
 import org.apache.shindig.common.logging.i18n.MessageKeys;
 import org.apache.shindig.common.util.ResourceLoader;
 import org.apache.shindig.config.ContainerConfig.Transaction;
@@ -273,6 +274,20 @@ public class JsonContainerConfigLoader {
     Map<String, Object> values = new HashMap<String, Object>(json.length(), 1);
     for (String key : keys) {
       Object val = jsonToConfig(json.opt(key));
+      //If this is a string see if its a pointer to an external resource, and 
if so, load the resource
+      if (val instanceof String) {
+        String stringVal = (String) val;
+        if (stringVal.startsWith(ResourceLoader.RESOURCE_PREFIX) ||
+            stringVal.startsWith(ResourceLoader.FILE_PREFIX)) {
+          try {
+            val = IOUtils.toString(ResourceLoader.open(stringVal), "UTF-8");
+          } catch (IOException e) {
+            if (LOG.isLoggable(Level.WARNING)) {
+              LOG.logp(Level.WARNING, classname, "jsonToMap", 
MessageKeys.READING_CONFIG, e);
+            }
+          }
+        }
+      }
       values.put(key, val);
     }
     return Collections.unmodifiableMap(values);

Modified: 
shindig/trunk/java/common/src/test/java/org/apache/shindig/auth/BlobCrypterSecurityTokenCodecTest.java
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/common/src/test/java/org/apache/shindig/auth/BlobCrypterSecurityTokenCodecTest.java?rev=1202283&r1=1202282&r2=1202283&view=diff
==============================================================================
--- 
shindig/trunk/java/common/src/test/java/org/apache/shindig/auth/BlobCrypterSecurityTokenCodecTest.java
 (original)
+++ 
shindig/trunk/java/common/src/test/java/org/apache/shindig/auth/BlobCrypterSecurityTokenCodecTest.java
 Tue Nov 15 16:25:34 2011
@@ -22,14 +22,12 @@ import static org.junit.Assert.assertEqu
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.shindig.auth.AbstractSecurityToken.Keys;
 import org.apache.shindig.common.crypto.BasicBlobCrypter;
 import org.apache.shindig.common.crypto.BlobCrypter;
-import org.apache.shindig.common.util.CharsetUtil;
 import org.apache.shindig.common.util.FakeTimeSource;
 import org.apache.shindig.config.BasicContainerConfig;
 import org.apache.shindig.config.ContainerConfig;
@@ -56,71 +54,32 @@ public class BlobCrypterSecurityTokenCod
         .addContainer(makeContainer("default"))
         .addContainer(makeContainer("container"))
         .addContainer(makeContainer("example"))
-        .addContainer(makeContainer("keyOnlyNoFile", true))
         .commit();
-    codec = new CodecWithLoadStubbedOut(config);
+    codec = new BlobCrypterSecurityTokenCodec(config);
     timeSource = new FakeTimeSource();
   }
 
   protected Map<String, Object> makeContainer(String container) {
-    return makeContainer(container, false);
-  }
-
-  protected Map<String, Object> makeContainer(String container, boolean 
insertKey) {
-    if (insertKey) {
-      return ImmutableMap.<String, Object>of(ContainerConfig.CONTAINER_KEY,
-          ImmutableList.of(container),
-          BlobCrypterSecurityTokenCodec.SECURITY_TOKEN_KEY_FILE,
-          container,
-          BlobCrypterSecurityTokenCodec.SECURITY_TOKEN_KEY,
-          getContainerKey(container),
-          BlobCrypterSecurityTokenCodec.SIGNED_FETCH_DOMAIN,
-          container + ".com");
-    } else {
-      return ImmutableMap.<String, Object>of(ContainerConfig.CONTAINER_KEY,
-              ImmutableList.of(container),
-              BlobCrypterSecurityTokenCodec.SECURITY_TOKEN_KEY_FILE,
-              container,
-              BlobCrypterSecurityTokenCodec.SIGNED_FETCH_DOMAIN,
-              container + ".com");
-    }
+    return ImmutableMap.<String, Object>of(ContainerConfig.CONTAINER_KEY,
+        ImmutableList.of(container),
+        BlobCrypterSecurityTokenCodec.SECURITY_TOKEN_KEY,
+        getContainerKey(container),
+        BlobCrypterSecurityTokenCodec.SIGNED_FETCH_DOMAIN,
+        container + ".com");
   }
 
   protected String getContainerKey(String container) {
     return "KEY FOR CONTAINER " + container;
   }
 
-  protected BlobCrypter getBlobCrypter(String fileName) {
-    BasicBlobCrypter c = new 
BasicBlobCrypter(CharsetUtil.getUtf8Bytes(fileName));
+  protected BlobCrypter getBlobCrypter(String key) {
+    BasicBlobCrypter c = new BasicBlobCrypter(key);
     c.timeSource = timeSource;
     return c;
   }
 
-  /**
-   * Stubs out loading the key file.
-   */
-  private class CodecWithLoadStubbedOut extends BlobCrypterSecurityTokenCodec {
-
-    public CodecWithLoadStubbedOut(ContainerConfig config) {
-      super(config);
-    }
-
-    /**
-     * @param file the location of the file.
-     * @return a crypter based on the name of the file passed in, rather than 
the contents.
-     * @throws IOException when passed a filename with 'fail' in it.
-     */
-    @Override
-    protected String getKeyFromFile(String file) throws IOException {
-      if (file.contains("fail")) {
-        throw new IOException("Load failed: " + file);
-      }
-      return getContainerKey(file);
-    }
-  }
-
   @Test
-  public void testCreateTokenUsingKeyFile() throws Exception {
+  public void testCreateToken() throws Exception {
     Map<String, String> values = new HashMap<String, String>();
     values.put(Keys.APP_URL.getKey(), "http://www.example.com/gadget.xml";);
     values.put(Keys.MODULE_ID.getKey(), Long.toString(12345L, 10));
@@ -227,18 +186,6 @@ public class BlobCrypterSecurityTokenCod
   }
 
   @Test
-  public void testLoadFailure() throws Exception {
-    config.newTransaction().addContainer(makeContainer("failure")).commit();
-
-    try {
-      new CodecWithLoadStubbedOut(config);
-      fail("Should have failed to load crypter");
-    } catch (RuntimeException e) {
-      assertTrue(e.getMessage(), e.getMessage().contains("Load failed"));
-    }
-  }
-
-  @Test
   public void testChangingContainers() throws Exception {
     String newContainer = "newcontainer";
     Map<String, String> values = new HashMap<String, String>();
@@ -270,27 +217,4 @@ public class BlobCrypterSecurityTokenCod
       // pass
     }
   }
-
-  @Test
-  public void testCreateTokenUsingKey() throws Exception {
-    Map<String, String> values = new HashMap<String, String>();
-    values.put(Keys.APP_URL.getKey(), "http://www.example.com/gadget.xml";);
-    values.put(Keys.MODULE_ID.getKey(), Long.toString(12345L, 10));
-    values.put(Keys.OWNER.getKey(), "owner");
-    values.put(Keys.VIEWER.getKey(), "viewer");
-    values.put(Keys.TRUSTED_JSON.getKey(), "trusted");
-
-    BlobCrypterSecurityToken t = new BlobCrypterSecurityToken("keyOnlyNoFile", 
null, null, values);
-    String encrypted = t.getContainer() + ":" + 
getBlobCrypter(getContainerKey("keyOnlyNoFile")).wrap(t.toMap());
-
-    SecurityToken t2 = 
codec.createToken(ImmutableMap.of(SecurityTokenCodec.SECURITY_TOKEN_NAME, 
encrypted));
-
-    assertEquals("http://www.example.com/gadget.xml";, t2.getAppId());
-    assertEquals("http://www.example.com/gadget.xml";, t2.getAppUrl());
-    assertEquals("keyOnlyNoFile.com", t2.getDomain());
-    assertEquals(12345L, t2.getModuleId());
-    assertEquals("owner", t2.getOwnerId());
-    assertEquals("viewer", t2.getViewerId());
-    assertEquals("trusted", t2.getTrustedJson());
-  }
 }

Modified: 
shindig/trunk/java/common/src/test/java/org/apache/shindig/auth/DefaultSecurityTokenCodecTest.java
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/common/src/test/java/org/apache/shindig/auth/DefaultSecurityTokenCodecTest.java?rev=1202283&r1=1202282&r2=1202283&view=diff
==============================================================================
--- 
shindig/trunk/java/common/src/test/java/org/apache/shindig/auth/DefaultSecurityTokenCodecTest.java
 (original)
+++ 
shindig/trunk/java/common/src/test/java/org/apache/shindig/auth/DefaultSecurityTokenCodecTest.java
 Tue Nov 15 16:25:34 2011
@@ -22,7 +22,6 @@ import static org.junit.Assert.assertEqu
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.io.FileNotFoundException;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
@@ -50,7 +49,7 @@ public class DefaultSecurityTokenCodecTe
         if ("default".equals(container)) {
           return tokenType;
         }
-      } else if ("gadgets.securityTokenKeyFile".equals(parameter)) {
+      } else if ("gadgets.securityTokenKey".equals(parameter)) {
         return "container key file: " + container;
       }
       return null;
@@ -101,12 +100,7 @@ public class DefaultSecurityTokenCodecTe
   @Test
   public void testRealDecoder() throws Exception {
     // Just verifies that "secure" tokens get routed to the right decoder 
class.
-    try {
-      new DefaultSecurityTokenCodec(new FakeContainerConfig("secure"));
-      fail("Should have thrown");
-    } catch (RuntimeException e) {
-      assertTrue("root cause should have been FileNotFoundException: " + e,
-          e.getCause() instanceof FileNotFoundException);
-    }
+    DefaultSecurityTokenCodec securityTokenCodec = new 
DefaultSecurityTokenCodec(new FakeContainerConfig("secure"));
+    assertTrue(securityTokenCodec.getCodec() instanceof 
BlobCrypterSecurityTokenCodec);
   }
 }

Modified: 
shindig/trunk/java/common/src/test/java/org/apache/shindig/config/JsonContainerConfigLoaderTest.java
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/common/src/test/java/org/apache/shindig/config/JsonContainerConfigLoaderTest.java?rev=1202283&r1=1202282&r2=1202283&view=diff
==============================================================================
--- 
shindig/trunk/java/common/src/test/java/org/apache/shindig/config/JsonContainerConfigLoaderTest.java
 (original)
+++ 
shindig/trunk/java/common/src/test/java/org/apache/shindig/config/JsonContainerConfigLoaderTest.java
 Tue Nov 15 16:25:34 2011
@@ -23,7 +23,9 @@ import static org.apache.shindig.config.
 import static org.apache.shindig.config.ContainerConfig.CONTAINER_KEY;
 import static org.apache.shindig.config.ContainerConfig.PARENT_KEY;
 import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
 
+import org.apache.shindig.common.util.ResourceLoader;
 import org.apache.shindig.expressions.Expressions;
 import org.json.JSONObject;
 import org.junit.Before;
@@ -55,13 +57,15 @@ public class JsonContainerConfigLoaderTe
   private static final String[] ARRAY_VALUE = {"Hello", "World"};
   private static final String ARRAY_ALT_VALUE = "Not an array";
 
+  public static final String DYNAMICALLY_LOADED_VALUE_KEY = 
"dynamicallyLoadedValueKey";
+
   private ExpressionContainerConfig config;
 
-  private File createContainer(JSONObject json) throws Exception {
-    File file = File.createTempFile(getClass().getName(), ".json");
+  private File createTemporaryFile(Object content, String extension) throws 
Exception {
+    File file = File.createTempFile(getClass().getName(), extension);
     file.deleteOnExit();
     BufferedWriter out = new BufferedWriter(new FileWriter(file));
-    out.write(json.toString());
+    out.write(content.toString());
     out.close();
     return file;
   }
@@ -79,7 +83,7 @@ public class JsonContainerConfigLoaderTe
     nested.put(NESTED_NAME, NESTED_VALUE);
 
     json.put(NESTED_KEY, nested);
-    return createContainer(json);
+    return createTemporaryFile(json, ".json");
   }
 
   private void createConfigForTest(String containers) throws 
ContainerConfigException {
@@ -117,7 +121,7 @@ public class JsonContainerConfigLoaderTe
         .put(NESTED_KEY, NESTED_VALUE);
 
     File parentFile = createDefaultContainer();
-    File childFile = createContainer(json);
+    File childFile = createTemporaryFile(json, ".json");
 
     createConfigForTest(childFile.getAbsolutePath() +
         JsonContainerConfigLoader.FILE_SEPARATOR + 
parentFile.getAbsolutePath());
@@ -139,7 +143,7 @@ public class JsonContainerConfigLoaderTe
 
     json.put(NESTED_KEY, nested);
 
-    File childFile = createContainer(json);
+    File childFile = createTemporaryFile(json, ".json");
     File parentFile = createDefaultContainer();
     createConfigForTest(childFile.getAbsolutePath() +
         JsonContainerConfigLoader.FILE_SEPARATOR + 
parentFile.getAbsolutePath());
@@ -179,7 +183,7 @@ public class JsonContainerConfigLoaderTe
     json.put(PARENT_KEY, "bad bad bad parent!");
     json.put(ARRAY_NAME, ARRAY_ALT_VALUE);
 
-    createConfigForTest(createContainer(json).getAbsolutePath());
+    createConfigForTest(createTemporaryFile(json, ".json").getAbsolutePath());
   }
 
   @Test
@@ -198,7 +202,7 @@ public class JsonContainerConfigLoaderTe
     json.put("expression", "Hello, ${world}!");
     json.put("world", "Earth");
 
-    createConfigForTest(createContainer(json).getAbsolutePath());
+    createConfigForTest(createTemporaryFile(json, ".json").getAbsolutePath());
 
     assertEquals("Hello, Earth!", config.getString(DEFAULT_CONTAINER, 
"expression"));
   }
@@ -210,7 +214,7 @@ public class JsonContainerConfigLoaderTe
     json.put(CONTAINER_KEY, new String[]{DEFAULT_CONTAINER});
     json.put("expression", "port=${SERVER_PORT}");
 
-    createConfigForTest(createContainer(json).getAbsolutePath());
+    createConfigForTest(createTemporaryFile(json, ".json").getAbsolutePath());
 
     assertEquals("port=8080", config.getString(DEFAULT_CONTAINER, 
"expression"));
   }
@@ -223,7 +227,7 @@ public class JsonContainerConfigLoaderTe
     json.put("port", "${SERVER_PORT}");
     json.put("host", "${SERVER_HOST}");
 
-    createConfigForTest(createContainer(json).getAbsolutePath());
+    createConfigForTest(createTemporaryFile(json, ".json").getAbsolutePath());
 
     assertEquals("8080", config.getString(DEFAULT_CONTAINER, "port"));
     assertEquals("8080", config.getString("testContainer", "port"));
@@ -239,7 +243,7 @@ public class JsonContainerConfigLoaderTe
     json.put(PARENT_KEY, DEFAULT_CONTAINER);
     json.put("parentExpression", "${parent['" + TOP_LEVEL_NAME + "']}");
 
-    File childFile = createContainer(json);
+    File childFile = createTemporaryFile(json, ".json");
     File parentFile = createDefaultContainer();
     createConfigForTest(childFile.getAbsolutePath() +
         JsonContainerConfigLoader.FILE_SEPARATOR + 
parentFile.getAbsolutePath());
@@ -251,7 +255,7 @@ public class JsonContainerConfigLoaderTe
   public void nullEntryEvaluation() throws Exception {
     // We use a JSON Object here to guarantee that we're well formed up front.
     JSONObject json = new JSONObject("{ 'gadgets.container' : ['default'], 
features : { osapi : null }}");
-    createConfigForTest(createContainer(json).getAbsolutePath());
+    createConfigForTest(createTemporaryFile(json, ".json").getAbsolutePath());
     assertNull(config.getMap("default", "features").get("osapi"));
   }
   
@@ -261,11 +265,74 @@ public class JsonContainerConfigLoaderTe
     JSONObject parent = new JSONObject("{ 'gadgets.container' : ['default'], 
features : { osapi : 'foo' }}");    
     JSONObject child = new JSONObject("{ 'gadgets.container' : ['child'], 
features : null}");    
     JSONObject grand = new JSONObject("{ 'gadgets.container' : ['grand'], 
parent : 'child'}");    
-    createConfigForTest(createContainer(parent).getAbsolutePath());
-    createConfigForTest(createContainer(child).getAbsolutePath());
-    createConfigForTest(createContainer(grand).getAbsolutePath());
+    createConfigForTest(createTemporaryFile(parent, 
".json").getAbsolutePath());
+    createConfigForTest(createTemporaryFile(child, ".json").getAbsolutePath());
+    createConfigForTest(createTemporaryFile(grand, ".json").getAbsolutePath());
     assertEquals("foo", config.getMap("default", "features").get("osapi"));
     assertNull(config.getProperty("child", "features"));
     assertNull(config.getProperty("grand", "features"));
   }
+
+  @Test
+  public void resourceLoaderClasspathTest() throws Exception {
+    // Pointer to a file that we'll load from the classpath
+    String testFile = "classpath-accessible-test-file.txt";
+
+    // We use a JSON Object here to guarantee that we're well formed up front.
+    JSONObject json = new JSONObject();
+    json.put(CONTAINER_KEY, new String[]{DEFAULT_CONTAINER});
+    json.put(DYNAMICALLY_LOADED_VALUE_KEY, ResourceLoader.RESOURCE_PREFIX + 
testFile);
+
+    createConfigForTest(createTemporaryFile(json, ".json").getAbsolutePath());
+
+    assertEquals(testFile, config.getString(DEFAULT_CONTAINER, 
DYNAMICALLY_LOADED_VALUE_KEY).trim());
+  }
+
+  @Test
+  public void resourceLoaderFileTest() throws Exception {
+    // Create a temporary file that we can load from
+    String dynamicValue = "dynamic value";
+    File temporaryFile = createTemporaryFile(dynamicValue, ".txt");
+
+    // We use a JSON Object here to guarantee that we're well formed up front.
+    JSONObject json = new JSONObject();
+    json.put(CONTAINER_KEY, new String[]{DEFAULT_CONTAINER});
+    json.put(DYNAMICALLY_LOADED_VALUE_KEY, ResourceLoader.FILE_PREFIX + 
temporaryFile.getAbsolutePath());
+
+    createConfigForTest(createTemporaryFile(json, ".json").getAbsolutePath());
+
+    assertEquals(dynamicValue, config.getString(DEFAULT_CONTAINER, 
DYNAMICALLY_LOADED_VALUE_KEY).trim());
+  }
+
+  @Test
+  public void resourceLoaderClasspathFailureTest() throws Exception {
+    // Pointer to an invalid resource reference
+    String invalidResource = ResourceLoader.RESOURCE_PREFIX + "does-not-exist";
+
+    // We use a JSON Object here to guarantee that we're well formed up front.
+    JSONObject json = new JSONObject();
+    json.put(CONTAINER_KEY, new String[]{DEFAULT_CONTAINER});
+    json.put(DYNAMICALLY_LOADED_VALUE_KEY, invalidResource);
+
+    createConfigForTest(createTemporaryFile(json, ".json").getAbsolutePath());
+
+    // If we fail to load a resource a warning is logged and we just end up 
with the raw value back
+    assertEquals(invalidResource, config.getString(DEFAULT_CONTAINER, 
DYNAMICALLY_LOADED_VALUE_KEY));
+  }
+
+  @Test
+  public void resourceLoaderFileFailureTest() throws Exception {
+    // Pointer to an invalid resource reference
+    String invalidResource = ResourceLoader.FILE_PREFIX + "does-not-exist";
+
+    // We use a JSON Object here to guarantee that we're well formed up front.
+    JSONObject json = new JSONObject();
+    json.put(CONTAINER_KEY, new String[]{DEFAULT_CONTAINER});
+    json.put(DYNAMICALLY_LOADED_VALUE_KEY, invalidResource);
+
+    createConfigForTest(createTemporaryFile(json, ".json").getAbsolutePath());
+
+    // If we fail to load a resource a warning is logged and we just end up 
with the raw value back
+    assertEquals(invalidResource, config.getString(DEFAULT_CONTAINER, 
DYNAMICALLY_LOADED_VALUE_KEY));
+  }
 }

Added: 
shindig/trunk/java/common/src/test/resources/classpath-accessible-test-file.txt
URL: 
http://svn.apache.org/viewvc/shindig/trunk/java/common/src/test/resources/classpath-accessible-test-file.txt?rev=1202283&view=auto
==============================================================================
--- 
shindig/trunk/java/common/src/test/resources/classpath-accessible-test-file.txt 
(added)
+++ 
shindig/trunk/java/common/src/test/resources/classpath-accessible-test-file.txt 
Tue Nov 15 16:25:34 2011
@@ -0,0 +1 @@
+classpath-accessible-test-file.txt
\ No newline at end of file


Reply via email to