public MessageBundle getBundle(GadgetSpec spec, Locale locale, bool ignoreCache) { if (ignoreCache) { return getNestedBundle(spec, locale, true); } String key = spec.getUrl().ToString() + '.' + locale.ToString(); MessageBundle cached = HttpRuntime.Cache[key] as MessageBundle; MessageBundle bundle; if (cached == null) { try { bundle = getNestedBundle(spec, locale, ignoreCache); } catch (GadgetException) { // Enforce negative caching. bundle = cached ?? MessageBundle.EMPTY; } HttpRuntime.Cache.Insert(key, bundle, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromSeconds(refresh)); } else { bundle = cached; } return bundle; }
/** * Performs substitutions on the spec. See individual elements for * details on what gets substituted. * * @param substituter * @return The substituted spec. */ public GadgetSpec substitute(Substitutions substituter) { GadgetSpec spec = new GadgetSpec(this); spec.modulePrefs = modulePrefs.substitute(substituter); if (userPrefs.Count == 0) { spec.userPrefs = new List <UserPref>(); } else { List <UserPref> prefs = new List <UserPref>(); foreach (UserPref pref in userPrefs) { prefs.Add(pref.substitute(substituter)); } spec.userPrefs = prefs; } Dictionary <String, View> viewMap = new Dictionary <String, View>(views.Count); foreach (View view in views.Values) { viewMap.Add(view.getName(), view.substitute(substituter)); } spec.views = viewMap; return(spec); }
/** * Substitutes all hangman variables into the gadget spec. * * @return A new GadgetSpec, with all fields substituted as needed. */ public GadgetSpec substitute(GadgetContext context, GadgetSpec spec) { MessageBundle bundle = messageBundleFactory.getBundle(spec, context.getLocale(), context.getIgnoreCache()); String dir = bundle.getLanguageDirection(); Substitutions substituter = new Substitutions(); substituter.addSubstitutions(Substitutions.Type.MESSAGE, bundle.getMessages()); BidiSubstituter.addSubstitutions(substituter, dir); substituter.addSubstitution(Substitutions.Type.MODULE, "ID", context.getModuleId()); UserPrefSubstituter.addSubstitutions(substituter, spec, context.getUserPrefs()); return spec.substitute(substituter); }
private MessageBundle getParentBundle(GadgetSpec spec, Locale locale, bool ignoreCache) { if (locale.getLanguage().Equals("all")) { // Top most locale already. return null; } if (locale.getCountry().Equals("ALL")) { return getBundle(spec, new Locale("all", "ALL"), ignoreCache); } return getBundle(spec, new Locale(locale.getLanguage(), "ALL"), ignoreCache); }
/** * @param concatBase Base url of the Concat servlet. Expected to be of the * form www.host.com/concat? * @param relativeUrlBase to resolve relative urls */ public JavascriptTagMerger(GadgetSpec spec, ContentRewriterFeature rewriterFeature, String concatBase, Uri relativeUrlBase) { // Force the mime-type to mimic browser expectation so rewriters // can function properly this.concatBase = concatBase + ProxyBase.REWRITE_MIME_TYPE_PARAM + "=text/javascript&" + "gadget=" + HttpUtility.UrlEncode(spec.getUrl().ToString()) + "&fp=" + rewriterFeature.getFingerprint() + '&'; this.relativeUrlBase = relativeUrlBase; }
public override List<preloadProcessor> createPreloadTasks(GadgetContext context, GadgetSpec gadget, PreloaderService.PreloadPhase phase) { List<preloadProcessor> preloads = new List<preloadProcessor>(); if (phase == PreloaderService.PreloadPhase.HTML_RENDER) { foreach(Preload preload in gadget.getModulePrefs().getPreloads()) { HashSet<String> preloadViews = preload.getViews(); if (preloadViews.Count == 0 || preloadViews.Contains(context.getView())) { PreloadTask task = new PreloadTask(context, preload, preload.getHref().ToString()); preloads.Add(new preloadProcessor(task.call)); } } } return preloads; }
public static void addSubstitutions(Substitutions substituter, GadgetSpec spec, UserPrefs values) { foreach (UserPref pref in spec.getUserPrefs()) { String name = pref.getName(); String value = values.getPref(name); if (value == null) { value = pref.getDefaultValue(); if (value == null) { value = ""; } } substituter.addSubstitution(Substitutions.Type.USER_PREF, name, HttpUtility.HtmlEncode(value)); } }
public MessageBundle getBundle(GadgetSpec spec, Locale locale, bool ignoreCache) { MessageBundle parent = getParentBundle(spec, locale, ignoreCache); MessageBundle child = null; LocaleSpec localeSpec = spec.getModulePrefs().getLocale(locale); if (localeSpec == null) { return parent ?? MessageBundle.EMPTY; } Uri messages = localeSpec.getMessages(); if (messages == null || messages.ToString().Length == 0) { child = localeSpec.getMessageBundle(); } else { child = fetchBundle(localeSpec, ignoreCache); } return new MessageBundle(parent, child); }
public override IPreloads preload(GadgetContext context, GadgetSpec gadget, PreloadPhase phase) { if (preloaders.Count == 0) { return null; } var tasks = new List<Preloader.preloadProcessor>(); foreach(Preloader preloader in preloaders) { ICollection<Preloader.preloadProcessor> taskCollection = preloader.createPreloadTasks(context, gadget, phase); tasks.AddRange(taskCollection); } ConcurrentPreloads preloads = new ConcurrentPreloads(); foreach (var task in tasks) { preloads.add(task.BeginInvoke(null, null)); } return preloads; }
public GadgetSpec getGadgetSpec(URI gadgetUri, bool ignoreCache) { Uri uri = Uri.fromJavaUri(gadgetUri); if (ignoreCache) { return FetchObjectAndCache(uri, ignoreCache); } GadgetSpec cached = HttpRuntime.Cache[gadgetUri.ToString()] as GadgetSpec; GadgetSpec spec; if (cached == null) { try { spec = FetchObjectAndCache(uri, ignoreCache); } catch (GadgetException e) { // We create this dummy spec to avoid the cost of re-parsing when a remote site is out. spec = new GadgetSpec(uri, ERROR_SPEC); spec.setAttribute(ERROR_KEY, e); HttpRuntime.Cache.Insert(uri.ToString(), spec, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromSeconds(ERROR_DELAY)); } } else { spec = cached; } GadgetException exception = (GadgetException)spec.getAttribute(ERROR_KEY); if (exception != null) { throw exception; } return spec; }
private GadgetSpec FetchObjectAndCache(Uri url, bool ignoreCache) { sRequest request = new sRequest(url) .setIgnoreCache(ignoreCache) .setGadget(url); // Since we don't allow any variance in cache time, we should just force the cache time // globally. This ensures propagation to shared caches when this is set. request.setCacheTtl((int)(refresh / 1000)); sResponse response = fetcher.fetch(request); if (response.getHttpStatusCode() != (int)HttpStatusCode.OK) { throw new GadgetException(GadgetException.Code.FAILED_TO_RETRIEVE_CONTENT, "Unable to retrieve gadget xml. HTTP error " + response.getHttpStatusCode()); } GadgetSpec spec = new GadgetSpec(url, response.responseString); HttpRuntime.Cache.Insert(url.ToString(), spec, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromSeconds(refresh)); return spec; }
/** * Create new preload tasks for the provided gadget. * * @param context The request that needs preloading. * @param gadget The gadget that the operations will be performed for. * @return Preloading tasks that will be executed by * {@link PreloaderService#preload(GadgetContext, GadgetSpec)}. */ public abstract List<preloadProcessor> createPreloadTasks(GadgetContext context, GadgetSpec gadget, PreloaderService.PreloadPhase phase);
/// <summary> /// Attempts to extract the "current" view for the given gadget. /// </summary> /// <param name="context"></param> /// <param name="spec"></param> /// <returns></returns> private View GetView(GadgetContext context, GadgetSpec spec) { String viewName = context.getView(); View view = spec.getView(viewName); if (view == null) { JsonObject views = containerConfig.GetJsonObject(context.getContainer(), "gadgets.features/views"); foreach (DictionaryEntry v in views) { JsonArray aliases = ((JsonObject)v.Value)["aliases"] as JsonArray; if (aliases != null && view == null) { for (int i = 0, j = aliases.Length; i < j; ++i) { if (viewName == aliases.GetString(i)) { view = spec.getView(v.Key.ToString()); if (view != null) { break; } } } } } } if (view == null) { view = spec.getView(GadgetSpec.DEFAULT_VIEW); } return view; }
/** * Constructs a GadgetSpec for substitute calls. * @param spec */ private GadgetSpec(GadgetSpec spec) { url = spec.url; checksum = spec.checksum; }
private static bool GadgetWantsLockedDomain(GadgetSpec gadget) { return gadget.getModulePrefs().getFeatures().ContainsKey("locked-domain"); }
private bool rewrite(GadgetSpec spec, Uri source, MutableContent mc, String mimeType, java.io.Writer writer) { // Dont rewrite content if the spec is unavailable if (spec == null) { return false; } // Store the feature in the spec so we dont keep parsing it ContentRewriterFeature rewriterFeature = new ContentRewriterFeature(spec, includeUrls, excludeUrls, expires, includeTags); if (!rewriterFeature.isRewriteEnabled()) { return false; } if (isHTML(mimeType)) { Dictionary<String, IHtmlTagTransformer> transformerMap = new Dictionary<string, IHtmlTagTransformer>(); if (ProxyUrl != null) { ILinkRewriter linkRewriter = CreateLinkRewriter(spec, rewriterFeature); LinkingTagRewriter rewriter = new LinkingTagRewriter(linkRewriter, source); HashSet<String> toProcess = new HashSet<string>(); foreach (var item in rewriter.getSupportedTags()) { toProcess.Add(item); } toProcess.IntersectWith(rewriterFeature.getIncludedTags()); foreach (string tag in toProcess) { transformerMap[tag] = rewriter; } if (rewriterFeature.getIncludedTags().Contains("style")) { transformerMap["style"] = new StyleTagRewriter(source, linkRewriter); } } if (ConcatUrl != null && rewriterFeature.getIncludedTags().Contains("script")) { transformerMap["script"] = new JavascriptTagMerger(spec, rewriterFeature, ConcatUrl, source); } HtmlRewriter.rewrite(new StringReader(mc.getContent()), source, transformerMap, writer); return true; } if (isCSS(mimeType)) { if (ProxyUrl != null) { CssRewriter.rewrite(new StringReader(mc.getContent()), source, CreateLinkRewriter(spec, rewriterFeature), writer, false); return true; } return false; } return false; }
/** * Begin all preload operations. * * @param context The request that needs preloading. * @param gadget The gadget that the operations will be performed for. * @return The preloads for the gadget. * * TODO: This should probably have a read only input. If we can */ public abstract IPreloads preload(GadgetContext context, GadgetSpec gadget, PreloadPhase phase);
/// <summary> /// Get all features needed to satisfy this rendering request. /// </summary> /// <param name="spec"></param> /// <param name="forced">Forced libraries; added in addition to those found in the spec. Defaults to "core"</param> /// <returns></returns> private ICollection<GadgetFeature> GetFeatures(GadgetSpec spec, ICollection<String> forced) { Dictionary<String, Feature> features = spec.getModulePrefs().getFeatures(); HashKey<String> libs = new HashKey<string>(); foreach (var item in features.Keys) { libs.Add(item); } if (forced.Count != 0) { foreach (var item in forced) { libs.Add(item); } } HashSet<String> unsupported = new HashSet<String>(); ICollection<GadgetFeature> feats = featureRegistry.GetFeatures(libs, unsupported); foreach (var item in forced) { unsupported.Remove(item); } if (unsupported.Count != 0) { // Remove non-required libs unsupported.RemoveWhere(x => !features[x].getRequired()); // Throw error with full list of unsupported libraries if (unsupported.Count != 0) { throw new UnsupportedFeatureException(String.Join(",", unsupported.ToArray())); } } return feats; }
/** * Constructor which takes a gadget spec and the default container settings * * @param spec * @param defaultInclude As a regex * @param defaultExclude As a regex * @param defaultExpires Either "HTTP" or a ttl in seconds * @param defaultTags Set of default tags that can be rewritten */ public ContentRewriterFeature(GadgetSpec spec, String defaultInclude, String defaultExclude, String defaultExpires, HashSet<String> defaultTags) { Feature f = null; if (spec != null) { spec.getModulePrefs().getFeatures().TryGetValue("content-rewrite", out f); } String includeRegex = normalizeParam(defaultInclude, null); String excludeRegex = normalizeParam(defaultExclude, null); this.includeTags = new HashSet<String>(defaultTags); List<String> expiresOptions = new List<string>(3); if (f != null) { if (f.getParams().ContainsKey(INCLUDE_URLS)) { includeRegex = normalizeParam(f.getParams()[INCLUDE_URLS], includeRegex); } // Note use of default for exclude as null here to allow clearing value in the // presence of a container default. if (f.getParams().ContainsKey(EXCLUDE_URLS)) { excludeRegex = normalizeParam(f.getParams()[EXCLUDE_URLS], null); } String includeTagList; if (f.getParams().TryGetValue(INCLUDE_TAGS, out includeTagList)) { HashSet<String> tags = new HashSet<String>(); foreach (String tag in includeTagList.Split(',')) { if (tag != null) { tags.Add(tag.Trim().ToLower()); } } includeTags = tags; } if (f.getParams().ContainsKey(EXPIRES)) { expiresOptions.Add(normalizeParam(f.getParams()[EXPIRES], null)); } } expiresOptions.Add(defaultExpires); expiresOptions.Add(EXPIRES_DEFAULT); foreach (String expiryOption in expiresOptions) { try { expires = int.Parse(expiryOption); break; } catch { // Not an integer if (EXPIRES_DEFAULT.ToLower().Equals(expiryOption)) { break; } } } if (".*".Equals(includeRegex) && excludeRegex == null) { includeAll = true; } if (".*".Equals(excludeRegex) || includeRegex == null) { includeNone = true; } if (includeRegex != null) { include = new Regex(includeRegex); } if (excludeRegex != null) { exclude = new Regex(excludeRegex); } }
private MutableContent GetMutableContent(GadgetSpec spec, View v) { // TODO - Consider using caching here to avoid parse costs MutableContent mc = new MutableContent(htmlParser, v.getContent()); return mc; }
public String getLockedDomainForGadget(GadgetSpec gadget, String container) { container = NormalizeContainer(container); if (enabled) { if (GadgetWantsLockedDomain(gadget) || ContainerRequiresLockedDomain(container)) { return GetLockedDomain(gadget, container); } } return null; }
public ContentRewriterFeature get(GadgetSpec spec) { ContentRewriterFeature rewriterFeature = (ContentRewriterFeature)spec.getAttribute("content-rewriter"); if (rewriterFeature != null) return rewriterFeature; rewriterFeature = new ContentRewriterFeature(spec, includeUrls, excludeUrls, expires, includeTags); spec.setAttribute("content-rewriter", rewriterFeature); return rewriterFeature; }
private String GetLockedDomain(GadgetSpec gadget, String container) { String suffix; if (!lockedSuffixes.TryGetValue(container, out suffix)) { return null; } String hash = SHA1.Create().ComputeHash(Encoding.Default.GetBytes(gadget.getUrl().ToString())).ToString(); return hash + suffix; }
/** * @param spec The spec for the gadget that is being processed. */ public Gadget setSpec(GadgetSpec spec) { this.spec = spec; return this; }
public bool gadgetCanRender(String host, GadgetSpec gadget, String container) { container = NormalizeContainer(container); if (enabled) { if (GadgetWantsLockedDomain(gadget) || HostRequiresLockedDomain(host) || ContainerRequiresLockedDomain(container)) { String neededHost = GetLockedDomain(gadget, container); return host.Equals(neededHost); } } return true; }
protected internal ILinkRewriter CreateLinkRewriter(GadgetSpec spec, ContentRewriterFeature rewriterFeature) { return new ProxyingLinkRewriter(spec.getUrl(), rewriterFeature, ProxyUrl); }
/** * Performs substitutions on the spec. See individual elements for * details on what gets substituted. * * @param substituter * @return The substituted spec. */ public GadgetSpec substitute(Substitutions substituter) { GadgetSpec spec = new GadgetSpec(this); spec.modulePrefs = modulePrefs.substitute(substituter); if (userPrefs.Count == 0) { spec.userPrefs = new List<UserPref>(); } else { List<UserPref> prefs = new List<UserPref>(); foreach (UserPref pref in userPrefs) { prefs.Add(pref.substitute(substituter)); } spec.userPrefs = prefs; } Dictionary<String, View> viewMap = new Dictionary<String, View>(views.Count); foreach (View view in views.Values) { viewMap.Add(view.getName(), view.substitute(substituter)); } spec.views = viewMap; return spec; }