class MessageConverters

URL短縮・展開のためのクラス。これを継承したクラスを作れば短縮URL機能として利用されるようになる

Constants

ExpandExpire

Public Class Methods

cache(shrinked, expanded) click to toggle source

shrinked を展開したら expanded になるということをキャッシュに登録する。 shrinked を返す。

# File core/messageconverters.rb, line 16
def cache(shrinked, expanded)
  expand_by_cache[shrinked] = expanded.freeze
  shrink_by_cache[expanded] = shrinked.freeze end
expand_url(urls) click to toggle source

URL url を展開する。urlは配列で渡す。 { 渡されたURL => 展開後URL }の配列を返す

# File core/messageconverters.rb, line 93
def expand_url(urls)
  result = Hash.new
  urls.each{ |url|
    result[url] = expand_url_one(url) }
  result.freeze end
expand_url_all(text) click to toggle source

textからURLを抜き出してすべて展開したテキストを返す

# File core/messageconverters.rb, line 69
def expand_url_all(text)
  urls = text.matches(shrinkable_url_regexp)
  return text if(urls.empty?)
  table = self.expand_url(urls)
  text.gsub(shrinkable_url_regexp){ |k| table[k] } if table end
expand_url_one(url, recur=0) click to toggle source

urlを一つだけ受け取り、再帰的に展開する。 ただし再帰的展開は4段までしか行わず、展開系が渡されたURLと同じになるか それ以上展開できなくなれば直ちにそれを返す。

# File core/messageconverters.rb, line 102
def expand_url_one(url, recur=0)
  return expand_by_cache[url] if expand_by_cache[url]
  lock(url) do
    if recur < 4 and shrinked_url?(url)
      expanded = timeout(5, ExpandExpire){ Plugin.filtering(:expand_url, url).first.freeze }
      if(expanded == url)
        url
      else
        result = expand_url_one(expanded, recur + 1)
        cache(url, result)
        result end
    else
      url end end
rescue ExpandExpire => e
  notice "url expand failed: timeout #{url}"
  cache(url, url)
  url end
lock(url) { |end end| ... } click to toggle source

url に対するMutexを作成・ロックして、ブロックを実行する。 ただし、urlが既にキャッシュにある場合は、Mutexは作成・ロックされず、単にブロックが実行される。

# File core/messageconverters.rb, line 53
    def lock(url, &proc)
      mutex = mutexes{ |mutexes|
        mutexes[url] ||= Mutex.new if !(expand_by_cache.has_key?(url) || shrink_by_cache.has_key?(url)) }
      if mutex
        mutex.synchronize(&proc)
      else
        yield end end

    # textからURLを抜き出してすべて短縮したテキストを返す
    def shrink_url_all(text)
      urls = text.matches(shrinkable_url_regexp)
      return text if(urls.empty?)
      table = self.shrink_url(urls)
      text.gsub(shrinkable_url_regexp){ |k| table[k] } if table end

    # textからURLを抜き出してすべて展開したテキストを返す
    def expand_url_all(text)
      urls = text.matches(shrinkable_url_regexp)
      return text if(urls.empty?)
      table = self.expand_url(urls)
      text.gsub(shrinkable_url_regexp){ |k| table[k] } if table end

    # URL _url_ を短縮する。urlは配列で渡す。
    # { 渡されたURL => 短縮後URL }の配列を返す
    def shrink_url(urls)
      result = Hash.new
      urls.each{ |url|
        url.freeze
        if shrinked_url?(url)
          result[url] = url
        else
          if(shrink_by_cache[url])
            result[url] = shrink_by_cache[url]
          else
            result[url] = Plugin.filtering(:shrink_url, url).first
            cache(result[url], url) if result[url] end end }
      result.freeze end

    # URL _url_ を展開する。urlは配列で渡す。
    # { 渡されたURL => 展開後URL }の配列を返す
    def expand_url(urls)
      result = Hash.new
      urls.each{ |url|
        result[url] = expand_url_one(url) }
      result.freeze end

    # urlを一つだけ受け取り、再帰的に展開する。
    # ただし再帰的展開は4段までしか行わず、展開系が渡されたURLと同じになるか
    # それ以上展開できなくなれば直ちにそれを返す。
    def expand_url_one(url, recur=0)
      return expand_by_cache[url] if expand_by_cache[url]
      lock(url) do
        if recur < 4 and shrinked_url?(url)
          expanded = timeout(5, ExpandExpire){ Plugin.filtering(:expand_url, url).first.freeze }
          if(expanded == url)
            url
          else
            result = expand_url_one(expanded, recur + 1)
            cache(url, result)
            result end
        else
          url end end
    rescue ExpandExpire => e
      notice "url expand failed: timeout #{url}"
      cache(url, url)
      url end

    def shrinkable_url_regexp
      URI.regexp(['http','https']) end

    def shrinked_url?(url)
      not Plugin.filtering(:is_expanded, url).first
    end

  end

  def shrink_url(url)
    nil end

  def expand_url(url)
    nil end

  def shrinked_url?(url)
    raise end

  def plugin_name
    raise end

  # no override follow

  def shrink_url_ifnecessary(url)
    if shrinked_url?(url)
      url
    else
      shrink_url(url)
    end
  end
end
mutexes() { |mutexes ||= time_limited_storage(String, Mutex, 60)| ... } click to toggle source

URLごとのロックを管理しているHashを取得し、ブロックの引数に渡して実行する。 ブロック内では、他のプロセスがそのHashを変更しないようにロックされている。

# File core/messageconverters.rb, line 47
def mutexes
  (@global_mutex ||= Mutex.new).synchronize {
    yield(@mutexes ||= TimeLimitedStorage.new(String, Mutex, 60)) } end
plugin_name() click to toggle source
# File core/messageconverters.rb, line 138
def plugin_name
  raise end
regist() click to toggle source

サブクラスから呼び出す。そのクラスをURLの短縮/展開のためのクラスとして登録する。

# File core/messageconverters.rb, line 21
def regist
  converter = self.new
  plugin = Plugin.create(converter.plugin_name)
  [:shrink, :expand].each{ |convert|
    plugin.add_event_filter("#{convert}_url"){ |url, &cont|
      lock(url) do
        cached = if convert == :shrink then shrink_by_cache[url] else expand_by_cache[url] end
        cont.call([cached]) if cached
        converted = converter.__send__("#{convert}_url", url)
        if(converted)
          if convert == :shrink
            cache(converted, url)
          else
            cache(url, converted) end
          cont.call([converted])
        else
          [url] end end } }
  plugin.add_event_filter(:is_expanded){ |url, &cont|
    if(converter.shrinked_url?(url))
      cont.call([false])
    else
      [url] end }
end
shrink_url(urls) click to toggle source

URL url を短縮する。urlは配列で渡す。 { 渡されたURL => 短縮後URL }の配列を返す

# File core/messageconverters.rb, line 77
def shrink_url(urls)
  result = Hash.new
  urls.each{ |url|
    url.freeze
    if shrinked_url?(url)
      result[url] = url
    else
      if(shrink_by_cache[url])
        result[url] = shrink_by_cache[url]
      else
        result[url] = Plugin.filtering(:shrink_url, url).first
        cache(result[url], url) if result[url] end end }
  result.freeze end
shrink_url_all(text) click to toggle source

textからURLを抜き出してすべて短縮したテキストを返す

# File core/messageconverters.rb, line 62
def shrink_url_all(text)
  urls = text.matches(shrinkable_url_regexp)
  return text if(urls.empty?)
  table = self.shrink_url(urls)
  text.gsub(shrinkable_url_regexp){ |k| table[k] } if table end
shrink_url_ifnecessary(url) click to toggle source

no override follow

# File core/messageconverters.rb, line 143
def shrink_url_ifnecessary(url)
  if shrinked_url?(url)
    url
  else
    shrink_url(url)
  end
end
shrinkable_url_regexp() click to toggle source
# File core/messageconverters.rb, line 120
def shrinkable_url_regexp
  URI.regexp(['http','https']) end
shrinked_url?(url) click to toggle source
# File core/messageconverters.rb, line 123
def shrinked_url?(url)
  not Plugin.filtering(:is_expanded, url).first
end