You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by et...@apache.org on 2008/10/02 01:54:29 UTC

svn commit: r700975 [1/2] - in /incubator/shindig/trunk/java: common/src/main/java/org/apache/shindig/common/uri/ common/src/main/java/org/apache/shindig/common/xml/ common/src/test/java/org/apache/shindig/common/xml/ gadgets/src/main/java/org/apache/s...

Author: etnu
Date: Wed Oct  1 16:54:27 2008
New Revision: 700975

URL: http://svn.apache.org/viewvc?rev=700975&view=rev
Log:
First phase of support for relative urls for proxied rendering.

This does not yet address relative images, css, etc., but all other links within the gadget spec will resolve as relative.

The image issue is somewhat separate, and will be dealt with in the next patch.


Removed:
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/ViewContentFetcher.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/ViewContentFetcherTest.java
Modified:
    incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/uri/Uri.java
    incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/xml/XmlUtil.java
    incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/common/xml/XmlUtilTest.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/AbstractMessageBundleFactory.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetSpecFactory.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicMessageBundleFactory.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetSpecFactory.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/GadgetOAuthTokenStore.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/preload/HttpPreloader.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/HtmlRenderer.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/Renderer.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/CssRewriter.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/HtmlContentRewriter.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/JsTagConcatContentRewriter.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/StyleLinksContentRewriter.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/lexer/DefaultContentRewriter.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/GadgetSpec.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/LinkSpec.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/LocaleSpec.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/ModulePrefs.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuthService.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuthSpec.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/Preload.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/RequestAuthenticationInfo.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/View.java
    incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/variables/Substitutions.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/BasicGadgetSpecFactoryTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/BasicMessageBundleFactoryTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/DefaultUrlGeneratorTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/FakeGadgetSpecFactory.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/GadgetTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/HashLockedDomainServiceTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/oauth/OAuthArgumentsTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/preload/HttpPreloaderTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/process/ProcessorTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/HtmlRendererTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RendererTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderingContentRewriterTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/BaseRewriterTestCase.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/CachingContentRewriterRegistryTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/DefaultContentRewriterRegistryTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/FeatureBasedRewriterTestBase.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/JsTagConcatContentRewriterTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/ProxyingLinkRewriterTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/servlet/JsonRpcHandlerTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/GadgetSpecTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/LinkSpecTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/LocaleSpecTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/MessageBundleTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/ModulePrefsTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/OAuthServiceTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/OAuthSpecTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/PreloadTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/spec/ViewTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/variables/UserPrefSubstituterTest.java
    incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/variables/VariableSubstituterTest.java

Modified: incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/uri/Uri.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/uri/Uri.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/uri/Uri.java (original)
+++ incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/uri/Uri.java Wed Oct  1 16:54:27 2008
@@ -121,6 +121,9 @@
    */
   public Uri resolve(Uri other) {
     // TODO: We can probably make this more efficient by implementing resolve ourselves.
+    if (other == null) {
+      return null;
+    }
     return fromJavaUri(toJavaUri().resolve(other.toJavaUri()));
   }
 

Modified: incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/xml/XmlUtil.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/xml/XmlUtil.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/xml/XmlUtil.java (original)
+++ incubator/shindig/trunk/java/common/src/main/java/org/apache/shindig/common/xml/XmlUtil.java Wed Oct  1 16:54:27 2008
@@ -18,6 +18,8 @@
 
 package org.apache.shindig.common.xml;
 
+import org.apache.shindig.common.uri.Uri;
+
 import com.google.common.collect.Lists;
 
 import org.w3c.dom.Element;
@@ -30,8 +32,6 @@
 
 import java.io.IOException;
 import java.io.StringReader;
-import java.net.URI;
-import java.net.URISyntaxException;
 import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -147,12 +147,12 @@
    * @return The parsed uri, or def if the attribute doesn't exist or can not
    *     be parsed as a URI.
    */
-  public static URI getUriAttribute(Node node, String attr, URI def) {
+  public static Uri getUriAttribute(Node node, String attr, Uri def) {
     String uri = getAttribute(node, attr);
     if (uri != null) {
       try {
-        return new URI(uri);
-      } catch (URISyntaxException e) {
+        return Uri.parse(uri);
+      } catch (IllegalArgumentException e) {
         return def;
       }
     }
@@ -165,7 +165,7 @@
    * @param attr
    * @return The parsed uri, or null.
    */
-  public static URI getUriAttribute(Node node, String attr) {
+  public static Uri getUriAttribute(Node node, String attr) {
     return getUriAttribute(node, attr, null);
   }
 
@@ -178,8 +178,8 @@
    * @return the parsed uri, or def if the attribute is not a valid http or
    * https URI.
    */
-  public static URI getHttpUriAttribute(Node node, String attr, URI def) {
-    URI uri = getUriAttribute(node, attr, def);
+  public static Uri getHttpUriAttribute(Node node, String attr, Uri def) {
+    Uri uri = getUriAttribute(node, attr, def);
     if (uri == null) {
       return def;
     }
@@ -190,14 +190,13 @@
   }
 
   /**
-   * Retrieves an attribute as a URI, and verifies that the URI is an http
-   * or https URI.
+   * Retrieves an attribute as a URI, and verifies that the URI is an http or https URI.
    * @param node
    * @param attr
    * @return the parsed uri, or null if the attribute is not a valid http or
    * https URI.
    */
-  public static URI getHttpUriAttribute(Node node, String attr) {
+  public static Uri getHttpUriAttribute(Node node, String attr) {
     return getHttpUriAttribute(node, attr, null);
   }
 

Modified: incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/common/xml/XmlUtilTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/common/xml/XmlUtilTest.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/common/xml/XmlUtilTest.java (original)
+++ incubator/shindig/trunk/java/common/src/test/java/org/apache/shindig/common/xml/XmlUtilTest.java Wed Oct  1 16:54:27 2008
@@ -23,12 +23,12 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import org.apache.shindig.common.uri.Uri;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.w3c.dom.Element;
 
-import java.net.URI;
-
 /**
  * Tests for XmlUtil
  */
@@ -40,13 +40,13 @@
   private final static String BOOL_TRUE_ATTR = "bool-true";
   private final static String BOOL_FALSE_ATTR = "bool-false";
   private final static String URI_ATTR = "uri";
-  private final static URI URI_VALUE = URI.create("http://example.org/file");
+  private final static Uri URI_VALUE = Uri.parse("http://example.org/file");
   private final static String URI_MALFORMED_ATTR = "uri-malformed";
   private final static String FAKE_ATTR = "fake";
   private final static String HTTPS_URI_ATTR = "httpsuri";
-  private final static URI HTTPS_URI_VALUE = URI.create("https://example.org");
+  private final static Uri HTTPS_URI_VALUE = Uri.parse("https://example.org");
   private final static String FTP_URI_ATTR = "ftpuri";
-  private final static URI FTP_URI_VALUE = URI.create("ftp://ftp.example.org");
+  private final static Uri FTP_URI_VALUE = Uri.parse("ftp://ftp.example.org");
 
   private final static String XML
       = "<Element " +
@@ -103,7 +103,7 @@
         XmlUtil.getUriAttribute(node, FAKE_ATTR));
     assertEquals(FTP_URI_VALUE, XmlUtil.getUriAttribute(node, FTP_URI_ATTR));
   }
-  
+
   @Test
   public void testHttpUriAttribute() {
     assertEquals(HTTPS_URI_VALUE, XmlUtil.getHttpUriAttribute(node, HTTPS_URI_ATTR));

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/AbstractMessageBundleFactory.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/AbstractMessageBundleFactory.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/AbstractMessageBundleFactory.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/AbstractMessageBundleFactory.java Wed Oct  1 16:54:27 2008
@@ -17,12 +17,12 @@
  */
 package org.apache.shindig.gadgets;
 
+import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.gadgets.spec.GadgetSpec;
 import org.apache.shindig.gadgets.spec.LocaleSpec;
 import org.apache.shindig.gadgets.spec.MessageBundle;
 
 import java.util.Locale;
-import java.net.URI;
 
 /**
  * Core implementation of MessageBundleFactory that ensures proper MessageBundle creation and
@@ -39,7 +39,7 @@
     if (localeSpec == null) {
       return parent == null ? MessageBundle.EMPTY : parent;
     }
-    URI messages = localeSpec.getMessages();
+    Uri messages = localeSpec.getMessages();
     if (messages == null || messages.toString().length() == 0) {
       child = localeSpec.getMessageBundle();
     } else {

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetSpecFactory.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetSpecFactory.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetSpecFactory.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicGadgetSpecFactory.java Wed Oct  1 16:54:27 2008
@@ -39,12 +39,12 @@
 @Singleton
 public class BasicGadgetSpecFactory implements GadgetSpecFactory {
   static final String RAW_GADGETSPEC_XML_PARAM_NAME = "rawxml";
-  static final URI RAW_GADGET_URI = URI.create("http://localhost/raw.xml");
+  static final Uri RAW_GADGET_URI = Uri.parse("http://localhost/raw.xml");
 
   static final Logger logger = Logger.getLogger(BasicGadgetSpecFactory.class.getName());
 
   private final HttpFetcher fetcher;
-  private final TtlCache<URI, GadgetSpec> ttlCache;
+  private final TtlCache<Uri, GadgetSpec> ttlCache;
 
    @Inject
   public BasicGadgetSpecFactory(HttpFetcher fetcher,
@@ -53,7 +53,7 @@
                                 @Named("shindig.gadget-spec.cache.minTTL") long minTtl,
                                 @Named("shindig.gadget-spec.cache.maxTTL") long maxTtl) {
     this.fetcher = fetcher;
-    this.ttlCache = new TtlCache<URI, GadgetSpec>(cacheProvider, capacity, minTtl, maxTtl);
+    this.ttlCache = new TtlCache<Uri, GadgetSpec>(cacheProvider, capacity, minTtl, maxTtl);
   }
 
   public GadgetSpec getGadgetSpec(GadgetContext context) throws GadgetException {
@@ -71,24 +71,25 @@
    * Retrieves a gadget specification from the cache or from the Internet.
    */
   public GadgetSpec getGadgetSpec(URI gadgetUri, boolean ignoreCache) throws GadgetException {
+    Uri uri = Uri.fromJavaUri(gadgetUri);
     if (ignoreCache) {
-      return fetchObjectAndCache(gadgetUri, ignoreCache);
+      return fetchObjectAndCache(uri, ignoreCache);
     }
 
     TtlCache.CachedObject<GadgetSpec> cached = null;
     synchronized(ttlCache) {
-      cached = ttlCache.getElementWithExpiration(gadgetUri);
+      cached = ttlCache.getElementWithExpiration(uri);
     }
 
     if (cached.obj == null || cached.isExpired) {
       try {
-        return fetchObjectAndCache(gadgetUri, ignoreCache);
+        return fetchObjectAndCache(uri, ignoreCache);
       } catch (GadgetException e) {
         // Failed to re-fetch raw object. Use cached object if it exists.
         if (cached.obj == null) {
           throw e;
         } else {
-          logger.info("GadgetSpec fetch failed for " + gadgetUri + " -  using cached.");
+          logger.info("GadgetSpec fetch failed for " + uri + " -  using cached.");
         }
       }
     }
@@ -100,8 +101,8 @@
    * Retrieves a gadget specification from the Internet, processes its views and
    * adds it to the cache.
    */
-  private GadgetSpec fetchObjectAndCache(URI url, boolean ignoreCache) throws GadgetException {
-    HttpRequest request = new HttpRequest(Uri.fromJavaUri(url)).setIgnoreCache(ignoreCache);
+  private GadgetSpec fetchObjectAndCache(Uri url, boolean ignoreCache) throws GadgetException {
+    HttpRequest request = new HttpRequest(url).setIgnoreCache(ignoreCache);
     HttpResponse response = fetcher.fetch(request);
     if (response.getHttpStatusCode() != HttpResponse.SC_OK) {
       throw new GadgetException(GadgetException.Code.FAILED_TO_RETRIEVE_CONTENT,

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicMessageBundleFactory.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicMessageBundleFactory.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicMessageBundleFactory.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/BasicMessageBundleFactory.java Wed Oct  1 16:54:27 2008
@@ -31,7 +31,6 @@
 import com.google.inject.Singleton;
 import com.google.inject.name.Named;
 
-import java.net.URI;
 import java.util.logging.Logger;
 
 /**
@@ -41,21 +40,31 @@
 public class BasicMessageBundleFactory extends AbstractMessageBundleFactory {
   static final Logger logger = Logger.getLogger(BasicMessageBundleFactory.class.getName());
   private final HttpFetcher fetcher;
-  private final TtlCache<URI, MessageBundle> ttlCache;
-  
+  private final TtlCache<Uri, MessageBundle> ttlCache;
+
+  @Inject
+  public BasicMessageBundleFactory(HttpFetcher fetcher,
+                                   CacheProvider cacheProvider,
+                                   @Named("shindig.message-bundle.cache.capacity")int capacity,
+                                   @Named("shindig.message-bundle.cache.minTTL")long minTtl,
+                                   @Named("shindig.message-bundle.cache.maxTTL")long maxTtl) {
+    this.fetcher = fetcher;
+    this.ttlCache = new TtlCache<Uri, MessageBundle>(cacheProvider, capacity, minTtl, maxTtl);
+  }
+
   @Override
   protected MessageBundle fetchBundle(LocaleSpec locale, boolean ignoreCache)
       throws GadgetException {
     if (ignoreCache) {
       return fetchAndCacheBundle(locale, ignoreCache);
     }
-    
+
     TtlCache.CachedObject<MessageBundle> cached = null;
-    
+
     synchronized(ttlCache) {
       cached = ttlCache.getElementWithExpiration(locale.getMessages());
     }
-    
+
     if (cached.obj == null || cached.isExpired) {
       try {
         return fetchAndCacheBundle(locale, ignoreCache);
@@ -67,14 +76,14 @@
         }
       }
     }
-    
+
     return cached.obj;
   }
 
-  private MessageBundle fetchAndCacheBundle(LocaleSpec locale,
-      boolean ignoreCache) throws GadgetException {
-    URI url = locale.getMessages();
-    HttpRequest request = new HttpRequest(Uri.fromJavaUri(url)).setIgnoreCache(ignoreCache);
+  private MessageBundle fetchAndCacheBundle(LocaleSpec locale, boolean ignoreCache)
+      throws GadgetException {
+    Uri url = locale.getMessages();
+    HttpRequest request = new HttpRequest(url).setIgnoreCache(ignoreCache);
     HttpResponse response = fetcher.fetch(request);
     if (response.getHttpStatusCode() != HttpResponse.SC_OK) {
       throw new GadgetException(GadgetException.Code.FAILED_TO_RETRIEVE_CONTENT,
@@ -86,14 +95,4 @@
     ttlCache.addElement(url, bundle, response.getCacheExpiration());
     return bundle;
   }
-
-  @Inject
-  public BasicMessageBundleFactory(HttpFetcher fetcher,
-                                   CacheProvider cacheProvider,
-                                   @Named("shindig.message-bundle.cache.capacity")int capacity,
-                                   @Named("shindig.message-bundle.cache.minTTL")long minTtl,
-                                   @Named("shindig.message-bundle.cache.maxTTL")long maxTtl) {
-    this.fetcher = fetcher;
-    this.ttlCache = new TtlCache<URI, MessageBundle>(cacheProvider, capacity, minTtl, maxTtl);
-  }
 }

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetSpecFactory.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetSpecFactory.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetSpecFactory.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/GadgetSpecFactory.java Wed Oct  1 16:54:27 2008
@@ -20,10 +20,10 @@
 
 import org.apache.shindig.gadgets.spec.GadgetSpec;
 
-import java.net.URI;
-
 import com.google.inject.ImplementedBy;
 
+import java.net.URI;
+
 /** Factory of gadget specs */
 
 @ImplementedBy(BasicGadgetSpecFactory.class)

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/GadgetOAuthTokenStore.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/GadgetOAuthTokenStore.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/GadgetOAuthTokenStore.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth/GadgetOAuthTokenStore.java Wed Oct  1 16:54:27 2008
@@ -17,11 +17,6 @@
  */
 package org.apache.shindig.gadgets.oauth;
 
-import com.google.inject.Inject;
-
-import net.oauth.OAuthServiceProvider;
-
-import org.apache.commons.lang.StringUtils;
 import org.apache.shindig.auth.SecurityToken;
 import org.apache.shindig.gadgets.GadgetException;
 import org.apache.shindig.gadgets.GadgetSpecFactory;
@@ -35,6 +30,12 @@
 import org.apache.shindig.gadgets.spec.OAuthService.Location;
 import org.apache.shindig.gadgets.spec.OAuthService.Method;
 
+import com.google.inject.Inject;
+
+import net.oauth.OAuthServiceProvider;
+
+import org.apache.commons.lang.StringUtils;
+
 import java.net.URI;
 import java.net.URISyntaxException;
 
@@ -64,19 +65,19 @@
   /**
    * Retrieve an AccessorInfo and OAuthAccessor that are ready for signing OAuthMessages.  To do
    * this, we need to figure out:
-   * 
+   *
    * - what consumer key/secret to use for signing.
-   * - if an access token should be used for the request, and if so what it is.   *   
+   * - if an access token should be used for the request, and if so what it is.   *
    * - the OAuth request/authorization/access URLs.
    * - what HTTP method to use for request token and access token requests
    * - where the OAuth parameters are located.
-   * 
+   *
    * Note that most of that work gets skipped for signed fetch, we just look up the consumer key
    * and secret for that.  Signed fetch always sticks the parameters in the query string.
    */
   public AccessorInfo getOAuthAccessor(SecurityToken securityToken,
       OAuthArguments arguments, OAuthClientState clientState) throws GadgetException {
-    
+
     AccessorInfoBuilder accessorBuilder = new AccessorInfoBuilder();
 
     // Does the gadget spec tell us any details about the service provider, like where to put the
@@ -88,7 +89,7 @@
       // This is plain old signed fetch.
       accessorBuilder.setParameterLocation(AccessorInfo.OAuthParamLocation.URI_QUERY);
     }
-    
+
     // What consumer key/secret should we use?
     ConsumerInfo consumer = store.getConsumerKeyAndSecret(
         securityToken, arguments.getServiceName(), provider);
@@ -98,13 +99,13 @@
     // if owner == viewer.
     if (arguments.mayUseToken()
         && securityToken.getOwnerId() != null
-        && securityToken.getViewerId().equals(securityToken.getOwnerId())) {  
+        && securityToken.getViewerId().equals(securityToken.getOwnerId())) {
       lookupToken(securityToken, consumer, arguments, clientState, accessorBuilder);
     }
-   
+
     return accessorBuilder.create();
   }
-  
+
   /**
    * Lookup information contained in the gadget spec.
    */
@@ -125,28 +126,28 @@
     accessorBuilder.setParameterLocation(getStoreLocation(service.getRequestUrl().location));
     accessorBuilder.setMethod(getStoreMethod(service.getRequestUrl().method));
     OAuthServiceProvider provider = new OAuthServiceProvider(
-        service.getRequestUrl().url.toASCIIString(),
-        service.getAuthorizationUrl().toASCIIString(),
-        service.getAccessUrl().url.toASCIIString());
+        service.getRequestUrl().url.toJavaUri().toASCIIString(),
+        service.getAuthorizationUrl().toJavaUri().toASCIIString(),
+        service.getAccessUrl().url.toJavaUri().toASCIIString());
     return provider;
   }
-  
+
   /**
    * Figure out the OAuth token that should be used with this request.  We check for this in three
    * places.  In order of priority:
-   * 
+   *
    * 1) From information we cached on the client.
    *    We encrypt the token and cache on the client for performance.
-   *    
+   *
    * 2) From information we have in our persistent state.
    *    We persist the token server-side so we can look it up if necessary.
-   *    
+   *
    * 3) From information the gadget developer tells us to use (a preapproved request token.)
    *    Gadgets can be initialized with preapproved request tokens.  If the user tells the service
    *    provider they want to add a gadget to a gadget container site, the service provider can
    *    create a preapproved request token for that site and pass it to the gadget as a user
    *    preference.
-   * @throws GadgetException 
+   * @throws GadgetException
    */
   private void lookupToken(SecurityToken securityToken, ConsumerInfo consumerInfo,
       OAuthArguments arguments, OAuthClientState clientState, AccessorInfoBuilder accessorBuilder)
@@ -188,7 +189,7 @@
     throw new GadgetException(GadgetException.Code.INTERNAL_SERVER_ERROR,
         "Unknown parameter location " + location);
   }
-  
+
   private HttpMethod getStoreMethod(Method method) throws GadgetException {
     switch(method) {
     case GET:
@@ -210,7 +211,7 @@
       throw new UserVisibleOAuthException("could not fetch gadget spec, gadget URI invalid", e);
     }
   }
-  
+
   private GadgetException serviceNotFoundEx(SecurityToken securityToken, OAuthSpec oauthSpec,
       String serviceName) {
     StringBuilder message = new StringBuilder()
@@ -230,7 +231,7 @@
         .append(" does not contain OAuth element.");
     return new UserVisibleOAuthException(message.toString());
   }
-  
+
   /**
    * Store an access token for the given user/gadget/service/token name
    */

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/preload/HttpPreloader.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/preload/HttpPreloader.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/preload/HttpPreloader.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/preload/HttpPreloader.java Wed Oct  1 16:54:27 2008
@@ -27,12 +27,13 @@
 import org.apache.shindig.gadgets.oauth.OAuthArguments;
 import org.apache.shindig.gadgets.spec.GadgetSpec;
 import org.apache.shindig.gadgets.spec.Preload;
-import org.json.JSONException;
-import org.json.JSONObject;
 
 import com.google.common.collect.Maps;
 import com.google.inject.Inject;
 
+import org.json.JSONException;
+import org.json.JSONObject;
+
 import java.util.Map;
 import java.util.concurrent.Callable;
 
@@ -73,7 +74,7 @@
     public PreloadedData call() throws Exception {
       // TODO: This should be extracted into a common helper that takes any
       // org.apache.shindig.gadgets.spec.RequestAuthenticationInfo.
-      HttpRequest request = new HttpRequest(Uri.fromJavaUri(preload.getHref()))
+      HttpRequest request = new HttpRequest(preload.getHref())
           .setSecurityToken(context.getToken())
           .setOAuthArguments(new OAuthArguments(preload))
           .setAuthType(preload.getAuthType())

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/HtmlRenderer.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/HtmlRenderer.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/HtmlRenderer.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/HtmlRenderer.java Wed Oct  1 16:54:27 2008
@@ -77,7 +77,7 @@
         return rewriter.rewriteGadget(gadget, view.getContent());
       } else {
         // TODO: Add current url to GadgetContext to support transitive proxying.
-        HttpRequest request = new HttpRequest(Uri.fromJavaUri(view.getHref()))
+        HttpRequest request = new HttpRequest(view.getHref())
             .setIgnoreCache(context.getIgnoreCache())
             .setOAuthArguments(new OAuthArguments(view))
             .setAuthType(view.getAuthType())

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/Renderer.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/Renderer.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/Renderer.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/Renderer.java Wed Oct  1 16:54:27 2008
@@ -72,7 +72,7 @@
 
     try {
       Gadget gadget = processor.process(context);
-      
+
       if (gadget.getCurrentView() == null) {
         return RenderingResults.error("Unable to locate an appropriate view in this gadget. " +
             "Requested: '" + gadget.getContext().getView() +
@@ -135,7 +135,7 @@
     // never happen.
     View view = gadget.getCurrentView();
     if (view.getType() == View.ContentType.URL) {
-      return Uri.fromJavaUri(gadget.getCurrentView().getHref());
+      return gadget.getCurrentView().getHref();
     }
     // TODO
     return null;

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/CssRewriter.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/CssRewriter.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/CssRewriter.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/CssRewriter.java Wed Oct  1 16:54:27 2008
@@ -72,8 +72,7 @@
     }
   }
 
-  private static String rewriteLink(Token<CssTokenType> token,
-      URI base, LinkRewriter rewriter) {
+  private static String rewriteLink(Token<CssTokenType> token, URI base, LinkRewriter rewriter) {
     Matcher matcher = urlMatcher.matcher(token.text);
     if (!matcher.find()) return token.text;
     return "url(\"" + rewriter.rewrite(matcher.group(2).trim(), base) + "\")";

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/HtmlContentRewriter.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/HtmlContentRewriter.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/HtmlContentRewriter.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/HtmlContentRewriter.java Wed Oct  1 16:54:27 2008
@@ -18,10 +18,12 @@
  */
 package org.apache.shindig.gadgets.rewrite;
 
+import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.gadgets.Gadget;
 import org.apache.shindig.gadgets.http.HttpRequest;
 import org.apache.shindig.gadgets.http.HttpResponse;
 import org.apache.shindig.gadgets.parse.GadgetHtmlNode;
+import org.apache.shindig.gadgets.spec.View;
 
 import java.net.URI;
 
@@ -53,7 +55,12 @@
   }
 
   public RewriterResults rewrite(Gadget gadget, MutableContent content) {
-    return rewriteHtml(content.getParseTree(), gadget.getSpec().getUrl());
+    Uri base = gadget.getSpec().getUrl();
+    View view = gadget.getCurrentView();
+    if (view != null && view.getHref() != null) {
+      base = view.getHref();
+    }
+    return rewriteHtml(content.getParseTree(), base.toJavaUri());
   }
 
   private RewriterResults rewriteHtml(GadgetHtmlNode root, URI baseUri) {

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/JsTagConcatContentRewriter.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/JsTagConcatContentRewriter.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/JsTagConcatContentRewriter.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/JsTagConcatContentRewriter.java Wed Oct  1 16:54:27 2008
@@ -18,6 +18,7 @@
  */
 package org.apache.shindig.gadgets.rewrite;
 
+import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.common.util.Utf8UrlCoder;
 import org.apache.shindig.gadgets.Gadget;
 import org.apache.shindig.gadgets.http.HttpRequest;
@@ -25,6 +26,7 @@
 import org.apache.shindig.gadgets.parse.GadgetHtmlNode;
 import org.apache.shindig.gadgets.servlet.ProxyBase;
 import org.apache.shindig.gadgets.spec.GadgetSpec;
+import org.apache.shindig.gadgets.spec.View;
 
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
@@ -68,8 +70,7 @@
 
     // Bootstrap queue of children over which to iterate,
     // ie. lists of siblings to potentially combine
-    Queue<GadgetHtmlNode> nodesToProcess =
-        new LinkedList<GadgetHtmlNode>();
+    Queue<GadgetHtmlNode> nodesToProcess = new LinkedList<GadgetHtmlNode>();
     nodesToProcess.add(content.getParseTree());
 
     String concatBase = getJsConcatBase(gadget.getSpec(), rewriterFeature);
@@ -95,12 +96,16 @@
                cur.hasAttribute("src")) {
             URI scriptUri = null;
             try {
-              scriptUri =
-                  gadget.getSpec().getUrl().resolve(new URI(cur.getAttributeValue("src")));
-            } catch (URISyntaxException use) {
+              Uri base = gadget.getSpec().getUrl();
+              View view = gadget.getCurrentView();
+              if (view != null && view.getHref() != null) {
+                base = view.getHref();
+              }
+              scriptUri = base.resolve(Uri.parse(cur.getAttributeValue("src"))).toJavaUri();
+            } catch (IllegalArgumentException e) {
               // Same behavior as JavascriptTagMerger
               // Perhaps switch to ignoring script src instead?
-              throw new RuntimeException(use);
+              throw new RuntimeException(e);
             }
             scripts.add(scriptUri);
             toRemove.add(cur);

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/StyleLinksContentRewriter.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/StyleLinksContentRewriter.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/StyleLinksContentRewriter.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/StyleLinksContentRewriter.java Wed Oct  1 16:54:27 2008
@@ -18,10 +18,12 @@
  */
 package org.apache.shindig.gadgets.rewrite;
 
+import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.gadgets.Gadget;
 import org.apache.shindig.gadgets.http.HttpRequest;
 import org.apache.shindig.gadgets.http.HttpResponse;
 import org.apache.shindig.gadgets.parse.GadgetHtmlNode;
+import org.apache.shindig.gadgets.spec.View;
 
 import java.net.URI;
 import java.util.LinkedList;
@@ -57,7 +59,13 @@
       return null;
     }
 
-    return rewriteHtml(content.getParseTree(), gadget.getSpec().getUrl());
+    Uri base = gadget.getSpec().getUrl();
+    View view = gadget.getCurrentView();
+    if (view != null && view.getHref() != null) {
+      base = view.getHref();
+    }
+
+    return rewriteHtml(content.getParseTree(), base.toJavaUri());
   }
 
   private RewriterResults rewriteHtml(GadgetHtmlNode root, URI baseUri) {

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/lexer/DefaultContentRewriter.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/lexer/DefaultContentRewriter.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/lexer/DefaultContentRewriter.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/lexer/DefaultContentRewriter.java Wed Oct  1 16:54:27 2008
@@ -17,6 +17,7 @@
  */
 package org.apache.shindig.gadgets.rewrite.lexer;
 
+import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.gadgets.Gadget;
 import org.apache.shindig.gadgets.GadgetException;
 import org.apache.shindig.gadgets.GadgetSpecFactory;
@@ -30,6 +31,7 @@
 import org.apache.shindig.gadgets.rewrite.ProxyingLinkRewriter;
 import org.apache.shindig.gadgets.rewrite.RewriterResults;
 import org.apache.shindig.gadgets.spec.GadgetSpec;
+import org.apache.shindig.gadgets.spec.View;
 
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
@@ -113,7 +115,13 @@
   public RewriterResults rewrite(Gadget gadget, MutableContent content) {
     StringWriter sw = new StringWriter();
     GadgetSpec spec = gadget.getSpec();
-    if (rewrite(spec, spec.getUrl(), new StringReader(content.getContent()), "text/html", sw)) {
+    StringReader reader = new StringReader(content.getContent());
+    Uri base = spec.getUrl();
+    View view = gadget.getCurrentView();
+    if (view != null && view.getHref() != null) {
+      base = view.getHref();
+    }
+    if (rewrite(spec, base.toJavaUri(), reader, "text/html", sw)) {
       content.setContent(sw.toString());
     }
     return RewriterResults.cacheableIndefinitely();
@@ -190,6 +198,6 @@
 
   protected LinkRewriter createLinkRewriter(GadgetSpec spec,
       ContentRewriterFeature rewriterFeature) {
-    return new ProxyingLinkRewriter(spec.getUrl(), rewriterFeature, getProxyUrl());
+    return new ProxyingLinkRewriter(spec.getUrl().toJavaUri(), rewriterFeature, getProxyUrl());
   }
 }

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/GadgetSpec.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/GadgetSpec.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/GadgetSpec.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/GadgetSpec.java Wed Oct  1 16:54:27 2008
@@ -17,6 +17,7 @@
  */
 package org.apache.shindig.gadgets.spec;
 
+import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.common.util.HashUtil;
 import org.apache.shindig.common.xml.XmlException;
 import org.apache.shindig.common.xml.XmlUtil;
@@ -26,7 +27,6 @@
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
-import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -44,10 +44,99 @@
   public static final Locale DEFAULT_LOCALE = new Locale("all", "ALL");
 
   /**
+   * Creates a new Module from the given xml input.
+   *
+   * @throws SpecParserException If xml can not be parsed as a valid gadget spec.
+   */
+  public GadgetSpec(Uri url, String xml) throws SpecParserException {
+    Element doc;
+    try {
+      doc = XmlUtil.parse(xml);
+    } catch (XmlException e) {
+      throw new SpecParserException("Malformed XML in file " + url.toString(), e);
+    }
+    this.url = url;
+
+    // This might not be good enough; should we take message bundle changes
+    // into account?
+    this.checksum = HashUtil.checksum(xml.getBytes());
+
+    NodeList children = doc.getChildNodes();
+
+    ModulePrefs modulePrefs = null;
+    List<UserPref> userPrefs = new LinkedList<UserPref>();
+    Map<String, List<Element>> views = new HashMap<String, List<Element>>();
+    for (int i = 0, j = children.getLength(); i < j; ++i) {
+      Node child = children.item(i);
+      if (!(child instanceof Element)) {
+        continue;
+      }
+      Element element = (Element)child;
+      String name = element.getTagName();
+      if ("ModulePrefs".equals(name)) {
+        if (modulePrefs == null) {
+          modulePrefs = new ModulePrefs(element, url);
+        } else {
+          throw new SpecParserException(
+              "Only 1 ModulePrefs is allowed.");
+        }
+      }
+      if ("UserPref".equals(name)) {
+        UserPref pref = new UserPref(element);
+        userPrefs.add(pref);
+      }
+      if ("Content".equals(name)) {
+        String viewNames = XmlUtil.getAttribute(element, "view", "default");
+        for (String view : viewNames.split(",")) {
+          view = view.trim();
+          List<Element> viewElements = views.get(view);
+          if (viewElements == null) {
+            viewElements = new LinkedList<Element>();
+            views.put(view, viewElements);
+          }
+          viewElements.add(element);
+        }
+      }
+    }
+
+    if (modulePrefs == null) {
+      throw new SpecParserException("At least 1 ModulePrefs is required.");
+    } else {
+      this.modulePrefs = modulePrefs;
+    }
+
+    if (views.isEmpty()) {
+      throw new SpecParserException("At least 1 Content is required.");
+    } else {
+      Map<String, View> tmpViews = new HashMap<String, View>();
+      for (Map.Entry<String, List<Element>> view : views.entrySet()) {
+        View v = new View(view.getKey(), view.getValue(), url);
+        tmpViews.put(v.getName(), v);
+      }
+      this.views = Collections.unmodifiableMap(tmpViews);
+    }
+
+    if (!userPrefs.isEmpty()) {
+      this.userPrefs = Collections.unmodifiableList(userPrefs);
+    } else {
+      this.userPrefs = Collections.emptyList();
+    }
+  }
+
+  /**
+   * Constructs a GadgetSpec for substitute calls.
+   * @param spec
+   */
+  private GadgetSpec(GadgetSpec spec) {
+    url = spec.url;
+    checksum = spec.checksum;
+  }
+
+  /**
    * The url for this gadget spec.
    */
-  private final URI url;
-  public URI getUrl() {
+  private final Uri url;
+  public Uri getUrl() {
     return url;
   }
 
@@ -150,96 +239,4 @@
     buf.append("</Module>");
     return buf.toString();
   }
-
-  /**
-   * Creates a new Module from the given xml input.
-   *
-   * @param url
-   * @param xml
-   * @throws SpecParserException
-   */
-  public GadgetSpec(URI url, String xml) throws SpecParserException {
-    Element doc;
-    try {
-      doc = XmlUtil.parse(xml);
-    } catch (XmlException e) {
-      throw new SpecParserException("Malformed XML in file " + url.toString(), e);
-    }
-    this.url = url;
-
-    // This might not be good enough; should we take message bundle changes
-    // into account?
-    this.checksum = HashUtil.checksum(xml.getBytes());
-
-    NodeList children = doc.getChildNodes();
-
-    ModulePrefs modulePrefs = null;
-    List<UserPref> userPrefs = new LinkedList<UserPref>();
-    Map<String, List<Element>> views = new HashMap<String, List<Element>>();
-    for (int i = 0, j = children.getLength(); i < j; ++i) {
-      Node child = children.item(i);
-      if (!(child instanceof Element)) {
-        continue;
-      }
-      Element element = (Element)child;
-      String name = element.getTagName();
-      if ("ModulePrefs".equals(name)) {
-        if (modulePrefs == null) {
-          modulePrefs = new ModulePrefs(element, url);
-        } else {
-          throw new SpecParserException(
-              "Only 1 ModulePrefs is allowed.");
-        }
-      }
-      if ("UserPref".equals(name)) {
-        UserPref pref = new UserPref(element);
-        userPrefs.add(pref);
-      }
-      if ("Content".equals(name)) {
-        String viewNames = XmlUtil.getAttribute(element, "view", "default");
-        for (String view : viewNames.split(",")) {
-          view = view.trim();
-          List<Element> viewElements = views.get(view);
-          if (viewElements == null) {
-            viewElements = new LinkedList<Element>();
-            views.put(view, viewElements);
-          }
-          viewElements.add(element);
-        }
-      }
-    }
-
-    if (modulePrefs == null) {
-      throw new SpecParserException(
-          "At least 1 ModulePrefs is required.");
-    } else {
-      this.modulePrefs = modulePrefs;
-    }
-
-    if (views.isEmpty()) {
-      throw new SpecParserException("At least 1 Content is required.");
-    } else {
-      Map<String, View> tmpViews = new HashMap<String, View>();
-      for (Map.Entry<String, List<Element>> view : views.entrySet()) {
-        View v = new View(view.getKey(), view.getValue());
-        tmpViews.put(v.getName(), v);
-      }
-      this.views = Collections.unmodifiableMap(tmpViews);
-    }
-
-    if (!userPrefs.isEmpty()) {
-      this.userPrefs = Collections.unmodifiableList(userPrefs);
-    } else {
-      this.userPrefs = Collections.emptyList();
-    }
-  }
-
-  /**
-   * Constructs a GadgetSpec for substitute calls.
-   * @param spec
-   */
-  private GadgetSpec(GadgetSpec spec) {
-    url = spec.url;
-    checksum = spec.checksum;
-  }
 }
\ No newline at end of file

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/LinkSpec.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/LinkSpec.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/LinkSpec.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/LinkSpec.java Wed Oct  1 16:54:27 2008
@@ -18,17 +18,35 @@
  */
 package org.apache.shindig.gadgets.spec;
 
+import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.common.xml.XmlUtil;
 import org.apache.shindig.gadgets.variables.Substitutions;
 
 import org.w3c.dom.Element;
 
-import java.net.URI;
-
 /**
  * Represents /ModulePrefs/Link elements.
  */
 public class LinkSpec {
+  private final Uri base;
+
+  public LinkSpec(Element element, Uri base) throws SpecParserException {
+    this.base = base;
+    rel = XmlUtil.getAttribute(element, "rel");
+    if (rel == null) {
+      throw new SpecParserException("Link/@rel is required!");
+    }
+    href = XmlUtil.getUriAttribute(element, "href");
+    if (href == null) {
+      throw new SpecParserException("Link/@href is required!");
+    }
+  }
+
+  private LinkSpec(LinkSpec rhs, Substitutions substitutions) {
+    rel = substitutions.substituteString(null, rhs.rel);
+    base = rhs.base;
+    href = base.resolve(substitutions.substituteUri(null, rhs.href));
+  }
 
   /**
    * Link/@rel
@@ -41,8 +59,8 @@
   /**
    * Link/@href
    */
-  private final URI href;
-  public URI getHref() {
+  private final Uri href;
+  public Uri getHref() {
     return href;
   }
 
@@ -57,20 +75,4 @@
   public String toString() {
     return "<Link rel='" + rel + "' href='" + href.toString() + "'/>";
   }
-
-  public LinkSpec(Element element) throws SpecParserException {
-    rel = XmlUtil.getAttribute(element, "rel");
-    if (rel == null) {
-      throw new SpecParserException("Link/@rel is required!");
-    }
-    href = XmlUtil.getUriAttribute(element, "href");
-    if (href == null) {
-      throw new SpecParserException("Link/@href is required!");
-    }
-  }
-
-  private LinkSpec(LinkSpec rhs, Substitutions substitutions) {
-    rel = substitutions.substituteString(null, rhs.rel);
-    href = substitutions.substituteUri(null, rhs.href);
-  }
 }

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/LocaleSpec.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/LocaleSpec.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/LocaleSpec.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/LocaleSpec.java Wed Oct  1 16:54:27 2008
@@ -16,14 +16,11 @@
  * specific language governing permissions and limitations under the License.
  */
 package org.apache.shindig.gadgets.spec;
+import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.common.xml.XmlUtil;
 
 import org.w3c.dom.Element;
 
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
 import java.util.Map;
 
 /**
@@ -38,6 +35,31 @@
 public class LocaleSpec {
 
   /**
+   * @param specUrl The url that the spec is loaded from. messages is assumed
+   *     to be relative to this path.
+   * @throws SpecParserException If language_direction is not valid
+   */
+  public LocaleSpec(Element element, Uri specUrl) throws SpecParserException {
+    language = XmlUtil.getAttribute(element, "lang", "all").toLowerCase();
+    country = XmlUtil.getAttribute(element, "country", "ALL").toUpperCase();
+    languageDirection = XmlUtil.getAttribute(element, "language_direction", "ltr");
+    if (!("ltr".equals(languageDirection) || "rtl".equals(languageDirection))) {
+      throw new SpecParserException("Locale/@language_direction must be ltr or rtl");
+    }
+    String messages = XmlUtil.getAttribute(element, "messages");
+    if (messages == null) {
+      this.messages = Uri.parse("");
+    } else {
+      try {
+        this.messages = specUrl.resolve(Uri.parse(messages));
+      } catch (IllegalArgumentException e) {
+        throw new SpecParserException("Locale@messages url is invalid.");
+      }
+    }
+    messageBundle = new MessageBundle(element);
+  }
+
+  /**
    * Locale@lang
    */
   private final String language;
@@ -64,8 +86,8 @@
   /**
    * Locale@messages
    */
-  private final URI messages;
-  public URI getMessages() {
+  private final Uri messages;
+  public Uri getMessages() {
     return messages;
   }
 
@@ -93,35 +115,4 @@
     buf.append("</Locale>");
     return buf.toString();
   }
-
-  /**
-   * @param element
-   * @param specUrl The url that the spec is loaded from. messages is assumed
-   *     to be relative to this path.
-   * @throws SpecParserException If language_direction is not valid
-   */
-  public LocaleSpec(Element element, URI specUrl) throws SpecParserException {
-    language = XmlUtil.getAttribute(element, "lang", "all").toLowerCase();
-    country = XmlUtil.getAttribute(element, "country", "ALL").toUpperCase();
-    languageDirection
-        = XmlUtil.getAttribute(element, "language_direction", "ltr");
-    if (!("ltr".equals(languageDirection) ||
-          "rtl".equals(languageDirection))) {
-      throw new SpecParserException(
-          "Locale@language_direction must be ltr or rtl");
-    }
-    String messages = XmlUtil.getAttribute(element, "messages");
-    if (messages == null) {
-      this.messages = URI.create("");
-    } else {
-      try {
-        this.messages = new URL(specUrl.toURL(), messages).toURI();
-      } catch (URISyntaxException e) {
-        throw new SpecParserException("Locale@messages url is invalid.");
-      } catch (MalformedURLException e) {
-        throw new SpecParserException("Locale@messages url is invalid.");
-      }
-    }
-    messageBundle = new MessageBundle(element);
-  }
 }

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/ModulePrefs.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/ModulePrefs.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/ModulePrefs.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/ModulePrefs.java Wed Oct  1 16:54:27 2008
@@ -16,20 +16,21 @@
  * specific language governing permissions and limitations under the License.
  */
 package org.apache.shindig.gadgets.spec;
+import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.gadgets.variables.Substitutions;
 
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
 import org.w3c.dom.Element;
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
-import java.net.URI;
-import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -65,10 +66,91 @@
   private static final String ATTR_HEIGHT = "height";
   private static final String ATTR_CATEGORY = "category";
   private static final String ATTR_CATEGORY2 = "category2";
-
-  private static final URI EMPTY_URI = URI.create("");
+  private static final Uri EMPTY_URI = Uri.parse("");
 
   private final Map<String, String> attributes;
+  private final Uri base;
+
+  public ModulePrefs(Element element, Uri base) throws SpecParserException {
+    this.base = base;
+    attributes = new HashMap<String, String>();
+    NamedNodeMap attributeNodes = element.getAttributes();
+    for (int i = 0; i < attributeNodes.getLength(); i++) {
+      Node node = attributeNodes.item(i);
+      attributes.put(node.getNodeName(), node.getNodeValue());
+    }
+
+    if (getTitle() == null) {
+      throw new SpecParserException("ModulePrefs@title is required.");
+    }
+
+    categories = Arrays.asList(
+        getAttribute(ATTR_CATEGORY, ""), getAttribute(ATTR_CATEGORY2, ""));
+
+    // Child elements
+    PreloadVisitor preloadVisitor = new PreloadVisitor();
+    FeatureVisitor featureVisitor = new FeatureVisitor();
+    OAuthVisitor oauthVisitor = new OAuthVisitor();
+    IconVisitor iconVisitor = new IconVisitor();
+    LocaleVisitor localeVisitor = new LocaleVisitor();
+    LinkVisitor linkVisitor = new LinkVisitor();
+
+    Map<String, ElementVisitor> visitors = Maps.newHashMapWithExpectedSize(6);
+    visitors.put("Preload", preloadVisitor);
+    visitors.put("Optional", featureVisitor);
+    visitors.put("Require", featureVisitor);
+    visitors.put("OAuth", oauthVisitor);
+    visitors.put("Icon", iconVisitor);
+    visitors.put("Locale", localeVisitor);
+    visitors.put("Link", linkVisitor);
+
+    walk(element, visitors);
+
+    preloads = Collections.unmodifiableList(preloadVisitor.preloaded);
+    features = Collections.unmodifiableMap(featureVisitor.features);
+    icons = Collections.unmodifiableList(iconVisitor.icons);
+    locales = Collections.unmodifiableMap(localeVisitor.localeMap);
+    links = Collections.unmodifiableMap(linkVisitor.linkMap);
+    oauth = oauthVisitor.oauthSpec;
+  }
+
+  /**
+   * Produces a new, substituted ModulePrefs
+   */
+  private ModulePrefs(ModulePrefs prefs, Substitutions substituter) {
+    base = prefs.base;
+    categories = prefs.getCategories();
+    features = prefs.getFeatures();
+    locales = prefs.getLocales();
+    oauth = prefs.oauth;
+
+    List<Preload> preloads = new ArrayList<Preload>(prefs.preloads.size());
+    for (Preload preload : prefs.preloads) {
+      preloads.add(preload.substitute(substituter));
+    }
+    this.preloads = Collections.unmodifiableList(preloads);
+
+    List<Icon> icons = new ArrayList<Icon>(prefs.icons.size());
+    for (Icon icon : prefs.icons) {
+      icons.add(icon.substitute(substituter));
+    }
+    this.icons = Collections.unmodifiableList(icons);
+
+    Map<String, LinkSpec> links = new HashMap<String, LinkSpec>(prefs.links.size());
+    for (LinkSpec link : prefs.links.values()) {
+      LinkSpec sub = link.substitute(substituter);
+      links.put(sub.getRel(), sub);
+    }
+    this.links = Collections.unmodifiableMap(links);
+
+    Map<String, String> attributes
+        = new HashMap<String, String>(prefs.attributes.size());
+    for (Map.Entry<String, String> attr : prefs.attributes.entrySet()) {
+      String substituted = substituter.substituteString(null, attr.getValue());
+      attributes.put(attr.getKey(), substituted);
+    }
+    this.attributes = Collections.unmodifiableMap(attributes);
+  }
 
   // Canonical spec items first.
 
@@ -86,7 +168,7 @@
    *
    * User Pref + Message Bundle + Bidi
    */
-  public URI getTitleUrl() {
+  public Uri getTitleUrl() {
     return getUriAttribute(ATTR_TITLE_URL);
   }
 
@@ -122,7 +204,7 @@
    *
    * Message Bundles
    */
-  public URI getScreenshot() {
+  public Uri getScreenshot() {
     return getUriAttribute(ATTR_SCREENSHOT);
   }
 
@@ -131,7 +213,7 @@
    *
    * Message Bundles
    */
-  public URI getThumbnail() {
+  public Uri getThumbnail() {
     return getUriAttribute(ATTR_THUMBNAIL);
   }
 
@@ -169,8 +251,8 @@
    *
    * Message Bundles
    */
-  public String getAuthorPhoto() {
-    return getAttribute(ATTR_AUTHOR_PHOTO);
+  public Uri getAuthorPhoto() {
+    return getUriAttribute(ATTR_AUTHOR_PHOTO);
   }
 
   /**
@@ -196,8 +278,8 @@
    *
    * Message Bundles
    */
-  public String getAuthorLink() {
-    return getAttribute(ATTR_AUTHOR_LINK);
+  public Uri getAuthorLink() {
+    return getUriAttribute(ATTR_AUTHOR_LINK);
   }
 
   /**
@@ -274,12 +356,13 @@
    * @return the attribute by name converted to an URI, or the empty URI if the
    *    attribute couldn't be converted
    */
-  public URI getUriAttribute(String name) {
-    String uri = getAttribute(name);
-    if (uri != null) {
+  public Uri getUriAttribute(String name) {
+    String uriAttribute = getAttribute(name);
+    if (uriAttribute != null) {
       try {
-        return new URI(uri);
-      } catch (URISyntaxException e) {
+        Uri uri = Uri.parse(uriAttribute);
+        return base.resolve(uri);
+      } catch (IllegalArgumentException e) {
         return EMPTY_URI;
       }
     }
@@ -359,7 +442,7 @@
   public Map<String, LinkSpec> getLinks() {
     return links;
   }
-  
+
   /**
    * ModuleSpec/OAuthSpec
    */
@@ -455,167 +538,85 @@
     return buf.toString();
   }
 
+  interface ElementVisitor {
+    void visit(Element element) throws SpecParserException;
+  }
+
   /**
-   * @param element
-   * @param specUrl
+   * Processes ModulePrefs/Preload into a list.
    */
-  public ModulePrefs(Element element, URI specUrl) throws SpecParserException {
-    attributes = new HashMap<String, String>();
-    NamedNodeMap attributeNodes = element.getAttributes();
-    for (int i = 0; i < attributeNodes.getLength(); i++) {
-      Node node = attributeNodes.item(i);
-      attributes.put(node.getNodeName(), node.getNodeValue());
-    }
+  private class PreloadVisitor implements ElementVisitor {
+    private final List<Preload> preloaded = Lists.newLinkedList();
 
-    if (getTitle() == null) {
-      throw new SpecParserException("ModulePrefs@title is required.");
+    public void visit(Element element) throws SpecParserException {
+      Preload preload = new Preload(element, base);
+      preloaded.add(preload);
     }
-
-    categories = Arrays.asList(
-        getAttribute(ATTR_CATEGORY, ""), getAttribute(ATTR_CATEGORY2, ""));
-
-    // Child elements
-    PreloadVisitor preloadVisitor = new PreloadVisitor();
-    FeatureVisitor featureVisitor = new FeatureVisitor();
-    OAuthVisitor oauthVisitor = new OAuthVisitor();
-    IconVisitor iconVisitor = new IconVisitor();
-    LocaleVisitor localeVisitor = new LocaleVisitor(specUrl);
-    LinkVisitor linkVisitor = new LinkVisitor();
-
-    Map<String, ElementVisitor> visitors
-        = new HashMap<String, ElementVisitor>(6, 1);
-    visitors.put("Preload", preloadVisitor);
-    visitors.put("Optional", featureVisitor);
-    visitors.put("Require", featureVisitor);
-    visitors.put("OAuth", oauthVisitor);
-    visitors.put("Icon", iconVisitor);
-    visitors.put("Locale", localeVisitor);
-    visitors.put("Link", linkVisitor);
-
-    walk(element, visitors);
-
-    preloads = Collections.unmodifiableList(preloadVisitor.preloads);
-    features = Collections.unmodifiableMap(featureVisitor.features);
-    icons = Collections.unmodifiableList(iconVisitor.icons);
-    locales = Collections.unmodifiableMap(localeVisitor.locales);
-    links = Collections.unmodifiableMap(linkVisitor.links);
-    oauth = oauthVisitor.oauth;
   }
 
   /**
-   * Produces a new, substituted ModulePrefs
+   * Process ModulePrefs/OAuth
    */
-  private ModulePrefs(ModulePrefs prefs, Substitutions substituter) {
-    categories = prefs.getCategories();
-    features = prefs.getFeatures();
-    locales = prefs.getLocales();
-    oauth = prefs.oauth;
+  private class OAuthVisitor implements ElementVisitor {
+    private OAuthSpec oauthSpec;
 
-    List<Preload> preloads = new ArrayList<Preload>(prefs.preloads.size());
-    for (Preload preload : prefs.preloads) {
-      preloads.add(preload.substitute(substituter));
+    public OAuthVisitor() {
+      this.oauthSpec = null;
     }
-    this.preloads = Collections.unmodifiableList(preloads);
 
-    List<Icon> icons = new ArrayList<Icon>(prefs.icons.size());
-    for (Icon icon : prefs.icons) {
-      icons.add(icon.substitute(substituter));
+    public void visit(Element element) throws SpecParserException {
+      if (oauthSpec != null) {
+        throw new SpecParserException("ModulePrefs/OAuth may only occur once.");
+      }
+      oauthSpec = new OAuthSpec(element, base);
     }
-    this.icons = Collections.unmodifiableList(icons);
+  }
 
-    Map<String, LinkSpec> links = new HashMap<String, LinkSpec>(prefs.links.size());
-    for (LinkSpec link : prefs.links.values()) {
-      LinkSpec sub = link.substitute(substituter);
-      links.put(sub.getRel(), sub);
-    }
-    this.links = Collections.unmodifiableMap(links);
+  /**
+   * Processes ModulePrefs/Require and ModulePrefs/Optional
+   */
+  private static class FeatureVisitor implements ElementVisitor {
+    private final Map<String, Feature> features = Maps.newHashMap();
 
-    Map<String, String> attributes
-        = new HashMap<String, String>(prefs.attributes.size());
-    for (Map.Entry<String, String> attr : prefs.attributes.entrySet()) {
-      String substituted = substituter.substituteString(null, attr.getValue());
-      attributes.put(attr.getKey(), substituted);
+    public void visit (Element element) throws SpecParserException {
+      Feature feature = new Feature(element);
+      features.put(feature.getName(), feature);
     }
-    this.attributes = Collections.unmodifiableMap(attributes);
   }
-}
-
-interface ElementVisitor {
-  public void visit(Element element) throws SpecParserException;
-}
 
-/**
- * Processes ModulePrefs/Preload into a list.
- */
-class PreloadVisitor implements ElementVisitor {
-  final List<Preload> preloads = new LinkedList<Preload>();
-  public void visit(Element element) throws SpecParserException {
-    Preload preload = new Preload(element);
-    preloads.add(preload);
-  }
-}
+  /**
+   * Processes ModulePrefs/Icon
+   */
+  private static class IconVisitor implements ElementVisitor {
+    private final List<Icon> icons = Lists.newLinkedList();
 
-/**
- * Process ModulePrefs/OAuth
- */
-class OAuthVisitor implements ElementVisitor {
-  OAuthSpec oauth;
-  public void visit(Element element) throws SpecParserException {
-    if (oauth != null) {
-      throw new SpecParserException("ModulePrefs/OAuth may only occur once.");
+    public void visit(Element element) throws SpecParserException {
+      icons.add(new Icon(element));
     }
-    oauth = new OAuthSpec(element);
   }
-  public OAuthVisitor() {
-    this.oauth = null;
-  }
-}
 
-/**
- * Processes ModulePrefs/Require and ModulePrefs/Optional
- */
-class FeatureVisitor implements ElementVisitor {
-  final Map<String, Feature> features = new HashMap<String, Feature>();
-  public void visit (Element element) throws SpecParserException {
-    Feature feature = new Feature(element);
-    features.put(feature.getName(), feature);
-  }
-}
+  /**
+   * Process ModulePrefs/Locale
+   */
+  private class LocaleVisitor implements ElementVisitor {
+    private final Map<Locale, LocaleSpec> localeMap = Maps.newHashMap();
 
-/**
- * Processes ModulePrefs/Icon
- */
-class IconVisitor implements ElementVisitor {
-  final List<Icon> icons = new LinkedList<Icon>();
-  public void visit(Element element) throws SpecParserException {
-    icons.add(new Icon(element));
-  }
-}
+    public void visit(Element element) throws SpecParserException {
+      LocaleSpec locale = new LocaleSpec(element, base);
+      localeMap.put(new Locale(locale.getLanguage(), locale.getCountry()), locale);
+    }
 
-/**
- * Process ModulePrefs/Locale
- */
-class LocaleVisitor implements ElementVisitor {
-  final URI base;
-  final Map<Locale, LocaleSpec> locales
-      = new HashMap<Locale, LocaleSpec>();
-  public void visit(Element element) throws SpecParserException {
-    LocaleSpec locale = new LocaleSpec(element, base);
-    locales.put(new Locale(locale.getLanguage(), locale.getCountry()), locale);
   }
-  public LocaleVisitor(URI base) {
-    this.base = base;
-  }
-}
 
-/**
- * Process ModulePrefs/Link
- */
-class LinkVisitor implements ElementVisitor {
-  final Map<String, LinkSpec> links = new HashMap<String, LinkSpec>();
+  /**
+   * Process ModulePrefs/Link
+   */
+  private class LinkVisitor implements ElementVisitor {
+    private final Map<String, LinkSpec> linkMap = Maps.newHashMap();
 
-  public void visit(Element element) throws SpecParserException {
-    LinkSpec link = new LinkSpec(element);
-    links.put(link.getRel(), link);
+    public void visit(Element element) throws SpecParserException {
+      LinkSpec link = new LinkSpec(element, base);
+      linkMap.put(link.getRel(), link);
+    }
   }
 }

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuthService.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuthService.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuthService.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuthService.java Wed Oct  1 16:54:27 2008
@@ -18,15 +18,16 @@
  */
 package org.apache.shindig.gadgets.spec;
 
-import java.net.URI;
-import java.util.HashMap;
-import java.util.Map;
-
+import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.common.xml.XmlUtil;
+
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Information about an OAuth service that a gadget wants to use.
  *
@@ -35,10 +36,65 @@
 public class OAuthService {
   private EndPoint requestUrl;
   private EndPoint accessUrl;
-  private URI authorizationUrl;
+  private Uri authorizationUrl;
   private String name;
 
   /**
+   * Constructor for testing only.
+   */
+  OAuthService() { }
+
+  public OAuthService(Element serviceElement, Uri base) throws SpecParserException {
+    name = serviceElement.getAttribute("name");
+    NodeList children = serviceElement.getChildNodes();
+    for (int i=0; i < children.getLength(); ++i) {
+      Node child = children.item(i);
+      if (child.getNodeType() != Element.ELEMENT_NODE) {
+        continue;
+      }
+      String childName = child.getNodeName();
+      if (childName.equals("Request")) {
+        if (requestUrl != null) {
+          throw new SpecParserException("Multiple OAuth/Service/Request elements");
+        }
+        requestUrl = parseEndPoint("OAuth/Service/Request", (Element)child, base);
+      } else if (childName.equals("Authorization")) {
+        if (authorizationUrl != null) {
+          throw new SpecParserException("Multiple OAuth/Service/Authorization elements");
+        }
+        authorizationUrl = parseAuthorizationUrl((Element)child, base);
+      } else if (childName.equals("Access")) {
+        if (accessUrl != null) {
+          throw new SpecParserException("Multiple OAuth/Service/Access elements");
+        }
+        accessUrl = parseEndPoint("OAuth/Service/Access", (Element)child, base);
+      }
+    }
+    if (requestUrl == null) {
+      throw new SpecParserException("/OAuth/Service/Request is required");
+    }
+    if (accessUrl == null) {
+      throw new SpecParserException("/OAuth/Service/Access is required");
+    }
+    if (authorizationUrl == null) {
+      throw new SpecParserException("/OAuth/Service/Authorization is required");
+    }
+    if (requestUrl.location != accessUrl.location) {
+      throw new SpecParserException(
+          "Access@location must be identical to Request@location");
+    }
+    if (requestUrl.method != accessUrl.method) {
+      throw new SpecParserException(
+          "Access@method must be identical to Request@method");
+    }
+    if (requestUrl.location == Location.BODY &&
+        requestUrl.method == Method.GET) {
+      throw new SpecParserException("Incompatible parameter location, cannot" +
+          "use post-body with GET requests");
+    }
+  }
+
+  /**
    * Represents /OAuth/Service/Request elements.
    */
   public EndPoint getRequestUrl() {
@@ -53,26 +109,26 @@
   }
   /**
    * Represents /OAuth/Service/Authorization elements.
-   */  
-  public URI getAuthorizationUrl() {
+   */
+  public Uri getAuthorizationUrl() {
     return authorizationUrl;
   }
-  
+
   /**
    * Represents /OAuth/Service@name
    */
   public String getName() {
     return name;
-  }  
-  
+  }
+
   /**
    * Method to use for requests to an OAuth request token or access token URL.
    */
   public enum Method {
     GET, POST;
-    
+
     private static Map<String, Method> METHODS;
-    
+
     static {
       METHODS = new HashMap<String, Method>();
       for (Method m : Method.values()) {
@@ -81,7 +137,7 @@
       // Default
       METHODS.put("", Method.GET);
     }
-    
+
     public static Method parse(String value) throws SpecParserException {
       value = value.trim();
       Method result = METHODS.get(value);
@@ -91,7 +147,7 @@
       return result;
     }
   }
-  
+
   /**
    * Location for OAuth parameters in requests to an OAuth request token,
    * access token, or resource URL.
@@ -100,9 +156,9 @@
     HEADER("auth-header"),
     URL("uri-query"),
     BODY("post-body");
-    
+
     private static Map<String, Location> LOCATIONS;
-    
+
     static {
       LOCATIONS = new HashMap<String, Location>();
       for (Location l : Location.values()) {
@@ -111,7 +167,7 @@
       // Default value
       LOCATIONS.put("", Location.HEADER);
     }
-    
+
     private String locationString;
     private Location(String locationString) {
       this.locationString = locationString;
@@ -121,30 +177,30 @@
     public String toString() {
       return locationString;
     }
-    
+
     public static Location parse(String value) throws SpecParserException {
       value = value.trim();
       Location result = LOCATIONS.get(value);
       if (result == null) {
-        throw new SpecParserException("Unknown OAuth param_location: " + value);        
+        throw new SpecParserException("Unknown OAuth param_location: " + value);
       }
       return result;
     }
   }
-  
+
   private static final String URL_ATTR = "url";
   private static final String PARAM_LOCATION_ATTR = "param_location";
   private static final String METHOD_ATTR = "method";
-  
+
   /**
    * Description of an OAuth request token or access token URL.
    */
   public static class EndPoint {
-    public final URI url;
+    public final Uri url;
     public final Method method;
     public final Location location;
-    
-    public EndPoint(URI url, Method method, Location location) {
+
+    public EndPoint(Uri url, Method method, Location location) {
       this.url = url;
       this.method = method;
       this.location = location;
@@ -155,81 +211,25 @@
       		"method='" + method + "' param_location='" + location + "'/>";
     }
   }
-  
-  public OAuthService(Element serviceElement) throws SpecParserException {
-    name = serviceElement.getAttribute("name");
-    NodeList children = serviceElement.getChildNodes();
-    for (int i=0; i < children.getLength(); ++i) {
-      Node child = children.item(i);
-      if (child.getNodeType() != Element.ELEMENT_NODE) {
-        continue;
-      }
-      String childName = child.getNodeName();
-      if (childName.equals("Request")) {
-        if (requestUrl != null) {
-          throw new SpecParserException("Multiple OAuth/Service/Request elements");
-        }
-        requestUrl = parseEndPoint("OAuth/Service/Request", (Element)child);
-      } else if (childName.equals("Authorization")) {
-        if (authorizationUrl != null) {
-          throw new SpecParserException("Multiple OAuth/Service/Authorization elements");
-        }
-        authorizationUrl = parseAuthorizationUrl((Element)child);
-      } else if (childName.equals("Access")) {
-        if (accessUrl != null) {
-          throw new SpecParserException("Multiple OAuth/Service/Access elements");          
-        }
-        accessUrl = parseEndPoint("OAuth/Service/Access", (Element)child);
-      }
-    }
-    if (requestUrl == null) {
-      throw new SpecParserException("/OAuth/Service/Request is required");
-    }
-    if (accessUrl == null) {
-      throw new SpecParserException("/OAuth/Service/Access is required");
-    }
-    if (authorizationUrl == null) {
-      throw new SpecParserException("/OAuth/Service/Authorization is required");
-    }
-    if (requestUrl.location != accessUrl.location) {
-      throw new SpecParserException(
-          "Access@location must be identical to Request@location");
-    }
-    if (requestUrl.method != accessUrl.method) {
-      throw new SpecParserException(
-          "Access@method must be identical to Request@method");     
-    }
-    if (requestUrl.location == Location.BODY &&
-        requestUrl.method == Method.GET) {
-      throw new SpecParserException("Incompatible parameter location, cannot" +
-          "use post-body with GET requests");
-    }
-  }
-  
-  /**
-   * Constructor for testing only.
-   */
-  OAuthService() {    
-  }
 
-  URI parseAuthorizationUrl(Element child) throws SpecParserException {
-    URI url = XmlUtil.getHttpUriAttribute(child, URL_ATTR);
+  Uri parseAuthorizationUrl(Element child, Uri base) throws SpecParserException {
+    Uri url = XmlUtil.getHttpUriAttribute(child, URL_ATTR);
     if (url == null) {
       throw new SpecParserException("OAuth/Service/Authorization @url is not valid: " +
           child.getAttribute(URL_ATTR));
     }
-    return url;
+    return base.resolve(url);
   }
 
 
-  EndPoint parseEndPoint(String where, Element child) throws SpecParserException {
-    URI url = XmlUtil.getHttpUriAttribute(child, URL_ATTR);
+  EndPoint parseEndPoint(String where, Element child, Uri base) throws SpecParserException {
+    Uri url = XmlUtil.getHttpUriAttribute(child, URL_ATTR);
     if (url == null) {
       throw new SpecParserException("Not an HTTP url: " + child.getAttribute(URL_ATTR));
     }
-    
+
     Location location = Location.parse(child.getAttribute(PARAM_LOCATION_ATTR));
     Method method = Method.parse(child.getAttribute(METHOD_ATTR));
-    return new EndPoint(url, method, location);
+    return new EndPoint(base.resolve(url), method, location);
   }
 }

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuthSpec.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuthSpec.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuthSpec.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuthSpec.java Wed Oct  1 16:54:27 2008
@@ -17,40 +17,42 @@
  */
 package org.apache.shindig.gadgets.spec;
 
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
+import org.apache.shindig.common.uri.Uri;
 
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Wraps an <OAuth> element from the gadget spec.
  *
  * Instances are immutable.
  */
 public class OAuthSpec {
-  
+
   /** Keys are service names, values are service descriptors */
   private final Map<String, OAuthService> serviceMap;
 
-  public OAuthSpec(Element element) throws SpecParserException {
+  public OAuthSpec(Element element, Uri base) throws SpecParserException {
     serviceMap = new HashMap<String, OAuthService>();
     NodeList services = element.getElementsByTagName("Service");
     for (int i=0; i < services.getLength(); ++i) {
       Node node = services.item(i);
       if (node.getNodeType() == Element.ELEMENT_NODE) {
-        parseService((Element)node);
+        parseService((Element)node, base);
       }
     }
   }
 
-  private void parseService(Element serviceElement) throws SpecParserException {
-    OAuthService service = new OAuthService(serviceElement);
+  private void parseService(Element serviceElement, Uri base) throws SpecParserException {
+    OAuthService service = new OAuthService(serviceElement, base);
     serviceMap.put(service.getName(), service);
   }
-  
+
   public Map<String, OAuthService> getServices() {
     return Collections.unmodifiableMap(serviceMap);
   }

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/Preload.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/Preload.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/Preload.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/Preload.java Wed Oct  1 16:54:27 2008
@@ -17,6 +17,7 @@
  */
 package org.apache.shindig.gadgets.spec;
 
+import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.common.xml.XmlUtil;
 import org.apache.shindig.gadgets.AuthType;
 import org.apache.shindig.gadgets.variables.Substitutions;
@@ -29,7 +30,6 @@
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 
-import java.net.URI;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Map;
@@ -43,13 +43,16 @@
   private static final Set<String> KNOWN_ATTRIBUTES
       = ImmutableSet.of("views", "href", "authz", "sign_owner", "sign_viewer");
 
+  private final Uri base;
+
   /**
    * Creates a new Preload from an xml node.
    *
    * @param preload The Preload to create
    * @throws SpecParserException When the href is not specified
    */
-  public Preload(Element preload) throws SpecParserException {
+  public Preload(Element preload, Uri base) throws SpecParserException {
+    this.base = base;
     href = XmlUtil.getUriAttribute(preload, "href");
     if (href == null) {
       throw new SpecParserException("Preload/@href is missing or invalid.");
@@ -81,11 +84,12 @@
   }
 
   private Preload(Preload preload, Substitutions substituter) {
+    base = preload.base;
     views = preload.views;
     auth = preload.auth;
     signOwner = preload.signOwner;
     signViewer = preload.signViewer;
-    href = substituter.substituteUri(null, preload.href);
+    href = base.resolve(substituter.substituteUri(null, preload.href));
     Map<String, String> attributes = Maps.newHashMap();
     for (Map.Entry<String, String> entry : preload.attributes.entrySet()) {
       attributes.put(entry.getKey(), substituter.substituteString(null, entry.getValue()));
@@ -96,8 +100,8 @@
   /**
    * Preload@href
    */
-  private final URI href;
-  public URI getHref() {
+  private final Uri href;
+  public Uri getHref() {
     return href;
   }
 

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/RequestAuthenticationInfo.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/RequestAuthenticationInfo.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/RequestAuthenticationInfo.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/RequestAuthenticationInfo.java Wed Oct  1 16:54:27 2008
@@ -18,9 +18,9 @@
  */
 package org.apache.shindig.gadgets.spec;
 
+import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.gadgets.AuthType;
 
-import java.net.URI;
 import java.util.Map;
 
 /**
@@ -35,7 +35,7 @@
   /**
    * @return The destination URI for making authenticated requests to.
    */
-  URI getHref();
+  Uri getHref();
 
   /**
    * @return True if owner signing is needed.

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/View.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/View.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/View.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/View.java Wed Oct  1 16:54:27 2008
@@ -17,6 +17,7 @@
  */
 package org.apache.shindig.gadgets.spec;
 
+import org.apache.shindig.common.uri.Uri;
 import org.apache.shindig.common.xml.XmlUtil;
 import org.apache.shindig.gadgets.AuthType;
 import org.apache.shindig.gadgets.variables.Substitutions;
@@ -30,7 +31,6 @@
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 
-import java.net.URI;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -45,17 +45,22 @@
       "sign_owner", "sign_viwer"
   );
 
+  private final Uri base;
+
   /**
+   * @param name The name of this view.
    * @param elements List of all views, in order, that make up this view.
    *     An ordered list is required per the spec, since values must
    *     overwrite one another.
+   * @param base The base url to resolve href against.
    * @throws SpecParserException
    */
-  public View(String name, List<Element> elements) throws SpecParserException {
+  public View(String name, List<Element> elements, Uri base) throws SpecParserException {
     this.name = name;
+    this.base = base;
 
     boolean quirks = true;
-    URI href = null;
+    Uri href = null;
     String contentType = null;
     ContentType type = null;
     int preferredHeight = 0;
@@ -125,7 +130,8 @@
     signViewer = view.signViewer;
 
     content = substituter.substituteString(null, view.content);
-    href = substituter.substituteUri(null, view.href);
+    base = view.base;
+    href = base.resolve(substituter.substituteUri(null, view.href));
     Map<String, String> attributes = Maps.newHashMap();
     for (Map.Entry<String, String> entry : view.attributes.entrySet()) {
       attributes.put(entry.getKey(), substituter.substituteString(null, entry.getValue()));
@@ -162,8 +168,8 @@
    *
    * All substitutions
    */
-  private URI href;
-  public URI getHref() {
+  private Uri href;
+  public Uri getHref() {
     return href;
   }
 

Modified: incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/variables/Substitutions.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/variables/Substitutions.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/variables/Substitutions.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/variables/Substitutions.java Wed Oct  1 16:54:27 2008
@@ -17,8 +17,8 @@
  */
 package org.apache.shindig.gadgets.variables;
 
-import java.net.URI;
-import java.net.URISyntaxException;
+import org.apache.shindig.common.uri.Uri;
+
 import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.Map;
@@ -177,14 +177,14 @@
    * @param uri
    * @return The substituted uri, or a dummy value if the result is invalid.
    */
-  public URI substituteUri(Type type, URI uri) {
+  public Uri substituteUri(Type type, Uri uri) {
     if (uri == null) {
       return null;
     }
     try {
-      return new URI(substituteString(type, uri.toString()));
-    } catch (URISyntaxException e) {
-      return URI.create("");
+      return Uri.parse(substituteString(type, uri.toString()));
+    } catch (IllegalArgumentException e) {
+      return Uri.parse("");
     }
   }
 }

Modified: incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/BasicGadgetSpecFactoryTest.java
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/BasicGadgetSpecFactoryTest.java?rev=700975&r1=700974&r2=700975&view=diff
==============================================================================
--- incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/BasicGadgetSpecFactoryTest.java (original)
+++ incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/BasicGadgetSpecFactoryTest.java Wed Oct  1 16:54:27 2008
@@ -190,7 +190,7 @@
 
     GadgetSpec spec = specFactory.getGadgetSpec(SPEC_URL.toJavaUri(), true);
 
-    assertEquals(REMOTE_URL.toJavaUri(), spec.getView(GadgetSpec.DEFAULT_VIEW).getHref());
+    assertEquals(REMOTE_URL, spec.getView(GadgetSpec.DEFAULT_VIEW).getHref());
     assertEquals("", spec.getView(GadgetSpec.DEFAULT_VIEW).getContent());
   }