protected virtual IDekiScriptInvocationTarget FindTarget(XUri uri) { string last_segment = uri.LastSegment ?? string.Empty; if(last_segment.EndsWithInvariant(".rpc")) { string methodName = last_segment.Substring(0, last_segment.Length - 4); return new DekiScriptXmlRpcInvocationTarget(uri.WithoutLastSegment(), methodName); } if(last_segment.EndsWithInvariant(".jsp")) { return new DekiScriptHttpGetInvocationTarget(uri); } return new DekiScriptRemoteInvocationTarget(uri); }
private void LoadScript() { _manifestPath = null; _resourcesPath = null; _manifestUri = null; _resourcesUri = null; _manifest = null; // read manifest _manifestPath = Config["manifest"].AsText; if(string.IsNullOrEmpty(_manifestPath)) { throw new ArgumentNullException("manifest"); } _manifestUri = XUri.TryParse(_manifestPath); if(_manifestUri != null) { _manifestPath = null; _manifest = Plug.New(_manifestUri).Get().ToDocument(); _resourcesUri = Config["resources"].AsUri ?? _manifestUri.WithoutLastSegment(); } else { _manifest = XDocFactory.LoadFrom(_manifestPath, MimeType.XML); _resourcesPath = Config["resources"].AsText ?? Path.GetDirectoryName(_manifestPath); } if(!_manifest.HasName("extension")) { throw new ArgumentException("invalid extension manifest"); } // initilize runtime _runtime = new DekiScriptRuntime(); // read manifest settings _title = _manifest["title"].AsText; _label = _manifest["label"].AsText; _copyright = _manifest["copyright"].AsText; _description = _manifest["description"].AsText; _help = _manifest["uri.help"].AsText; _logo = _manifest["uri.logo"].AsText; _namespace = _manifest["namespace"].AsText; // initialize evaluation environment _commonEnv = _runtime.CreateEnv(); // read functions _functions = new Dictionary<XUri, DekiScriptInvocationTargetDescriptor>(); foreach(var function in _manifest["function"]) { var descriptor = ConvertFunction(function); if(descriptor != null) { var uri = Self.At(descriptor.SystemName); DekiScriptInvocationTargetDescriptor old; if(_functions.TryGetValue(uri, out old)) { _log.WarnFormat("duplicate function name {0} in script {1}", descriptor.Name, _manifestUri); } _functions[uri] = descriptor; } } _runtime.RegisterExtensionFunctions(_functions); // add extension functions to env foreach(var function in _functions) { _commonEnv.Vars.AddNativeValueAt(function.Value.Name.ToLowerInvariant(), function.Key); } // add configuration settings DreamContext context = DreamContext.Current; DekiScriptMap scriptConfig = new DekiScriptMap(); foreach(KeyValuePair<string, string> entry in Config.ToKeyValuePairs()) { XUri local; if(XUri.TryParse(entry.Value, out local)) { local = context.AsPublicUri(local); scriptConfig.AddAt(entry.Key.Split('/'), DekiScriptExpression.Constant(local.ToString())); } else { scriptConfig.AddAt(entry.Key.Split('/'), DekiScriptExpression.Constant(entry.Value)); } } _commonEnv.Vars.Add("config", scriptConfig); }
//--- Constructor --- public DekiInstance(DekiWikiService deki, string id, XDoc instanceConfig) { if(deki == null) { throw new ArgumentNullException("deki"); } if(string.IsNullOrEmpty(id)) { throw new ArgumentNullException("id"); } this.Id = id; this.TimerFactory = TaskTimerFactory.Create(this); this.Cache = new DreamCache(TimerFactory); var cacheFactory = new InMemoryKeyValueCacheFactory(TimerFactory); var searchSerializer = new SearchSerializer(); cacheFactory.SetSerializer<SearchResult>(searchSerializer); cacheFactory.SetSerializer<SearchResultDetail>(searchSerializer); this.SearchCache = cacheFactory.Create(); this.Config = instanceConfig; this.Log = LogManager.GetLogger(deki.GetType().Name + "_" + id); _deki = deki; _status = DekiInstanceStatus.CREATED; foreach(XDoc hostDoc in Config["host"]) { string host = hostDoc.Contents; if(!StringUtil.EqualsInvariantIgnoreCase(host, "*")) { string port = hostDoc["@port"].AsText; string scheme = hostDoc["@https"].AsBool.GetValueOrDefault() ? "https://" : "http://"; string uri = scheme + host + (string.IsNullOrEmpty(port) ? "" : ":" + port); _canonicalUri = new XUri(uri); _log.DebugFormat("divined canonical use from hosts as {0}", _canonicalUri); break; } } if(_canonicalUri == null) { // Note (arnec): this is a best guess fallback. It will only work in these scenarios: // a) The host was set up with a uri.public that has ends in @api and with the @api points to the site uri, or // b) The api lives on the same machine as the site, so that deriving uri.public for the host from the machine // IP happens to point to the same machine // Either way it relies on the hard-coded assumption that the api is accessible via {site}/@api _canonicalUri = DreamContext.Current.ServerUri; if(_canonicalUri.LastSegment.EqualsInvariantIgnoreCase("@api")) { _canonicalUri = _canonicalUri.WithoutLastSegment(); } _log.DebugFormat("using server uri as canonical uri: {0}", _canonicalUri); } else { // Note (arnec): Propagating a much hard-coded assumption, i.e. that the Api for any Deki instance can be accessed // at the instances' canonical uri plus @api // register the api uri with the dream host so that requests originating from within Dream are guaranteed to be locally routed _deki.Env.At("status", "aliases").Post(new XDoc("aliases").Elem("uri.alias", _canonicalUri.At("@api")), new Result<DreamMessage>()); } }