github.com/keysonZZZ/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgView/kmgViewResource/Generated.go (about) 1 package kmgViewResource 2 3 import ( 4 "github.com/bronze1man/kmg/encoding/kmgJson" 5 "github.com/bronze1man/kmg/kmgCache" 6 "github.com/bronze1man/kmg/kmgConfig" 7 "github.com/bronze1man/kmg/kmgFile" 8 "github.com/bronze1man/kmg/kmgNet/kmgHttp" 9 "github.com/bronze1man/kmg/kmgXss" 10 "reflect" 11 "strings" 12 "sync" 13 ) 14 15 type Generated struct { 16 Name string //拿去做缓存控制的. 17 GeneratedJsFileUrl string 18 GeneratedCssFileUrl string 19 GeneratedJsFileName string 20 GeneratedCssFileName string 21 GeneratedUrlPrefix string // 末尾不包含 / 22 RequestImportList []string 23 24 locker sync.Mutex 25 cachedInfo resourceBuildToDirResponse 26 initOnce sync.Once 27 } 28 29 type htmlTplData struct { 30 urlPrefix string 31 jsFileUrl string 32 cssFileUrl string 33 } 34 35 func (g *Generated) HtmlRender() string { 36 data := g.GetHtmlTplData() 37 return `<script> 38 function getResourceUrlPrefix(){ 39 return ` + kmgXss.Jsonv(data.urlPrefix) + ` 40 } 41 </script> 42 <link rel="stylesheet" href="` + kmgXss.H(data.cssFileUrl) + `"> 43 <script src="` + kmgXss.H(data.jsFileUrl) + `"></script>` 44 } 45 46 func (g *Generated) HeaderHtml() string { 47 data := g.GetHtmlTplData() 48 return `<script> 49 function getResourceUrlPrefix(){ 50 return ` + kmgXss.Jsonv(data.urlPrefix) + ` 51 } 52 </script> 53 <link rel="stylesheet" href="` + kmgXss.H(data.cssFileUrl) + `">` 54 } 55 56 func (g *Generated) FooterHtml() string { 57 data := g.GetHtmlTplData() 58 return `<script src="` + kmgXss.H(data.jsFileUrl) + `"></script>` 59 } 60 61 func (g *Generated) GetHtmlTplData() htmlTplData { 62 if kmgConfig.HasDefaultEnv() { 63 g.recheckAndReloadCache() 64 g.locker.Lock() 65 cachedInfo := g.cachedInfo 66 g.locker.Unlock() 67 urlPrefix := "/kmgViewResource." + g.Name 68 return htmlTplData{ 69 urlPrefix: urlPrefix, 70 jsFileUrl: urlPrefix + "/" + cachedInfo.JsFileName, 71 cssFileUrl: urlPrefix + "/" + cachedInfo.CssFileName, 72 } 73 } else { 74 urlPrefix := "/kmgViewResource." + g.Name 75 return htmlTplData{ 76 urlPrefix: urlPrefix, 77 jsFileUrl: urlPrefix + "/" + g.GeneratedJsFileName, 78 cssFileUrl: urlPrefix + "/" + g.GeneratedCssFileName, 79 } 80 } 81 } 82 83 // 返回url前缀,末尾不包含 '/' 84 func (g *Generated) GetUrlPrefix() string { 85 if kmgConfig.HasDefaultEnv() { 86 g.recheckAndReloadCache() 87 return "/kmgViewResource." + g.Name 88 } else { 89 return "/kmgViewResource." + g.Name 90 } 91 } 92 93 func (g *Generated) GetJsUrl() string { 94 if kmgConfig.HasDefaultEnv() { 95 g.recheckAndReloadCache() 96 g.locker.Lock() 97 cachedInfo := g.cachedInfo 98 g.locker.Unlock() 99 return "/kmgViewResource." + g.Name + "/" + cachedInfo.JsFileName 100 } else { 101 return "/kmgViewResource." + g.Name + "/" + g.GeneratedJsFileName 102 } 103 } 104 func (g *Generated) GetCssUrl() string { 105 if kmgConfig.HasDefaultEnv() { 106 g.recheckAndReloadCache() 107 g.locker.Lock() 108 cachedInfo := g.cachedInfo 109 g.locker.Unlock() 110 return "/kmgViewResource." + g.Name + "/" + cachedInfo.CssFileName 111 } else { 112 return "/kmgViewResource." + g.Name + "/" + g.GeneratedCssFileName 113 } 114 } 115 116 // 这个初始化会在第一次使用的时候,自动进行,如果嫌自动初始化太慢,可以手动初始化. 117 func (g *Generated) Init() { 118 g.initOnce.Do(func() { 119 if kmgConfig.HasDefaultEnv() { 120 g.recheckAndReloadCache() 121 kmgHttp.MustAddFileToHttpPathToDefaultServer("/kmgViewResource."+g.Name+"/", 122 kmgConfig.DefaultEnv().PathInProject("tmp/kmgViewResource_debug/"+g.Name)) 123 } else { 124 // 默认使用反向代理方式提供数据. 125 kmgHttp.MustAddUriProxyRefToUriToDefaultServer("/kmgViewResource."+g.Name+"/", g.GeneratedUrlPrefix) 126 } 127 }) 128 } 129 130 // 获取某个资源文件的内容 131 func (g *Generated) GetContentByName(name string) (b []byte, err error) { 132 name = strings.TrimPrefix(name, "/") 133 if kmgConfig.HasDefaultEnv() { 134 g.recheckAndReloadCache() 135 path := kmgConfig.DefaultEnv().PathInProject("tmp/kmgViewResource_debug/" + g.Name + "/" + name) 136 return kmgFile.ReadFile(path) 137 } else { 138 // 默认使用反向代理方式提供数据. 139 return kmgHttp.UrlGetContent(g.GeneratedUrlPrefix + "/" + name) 140 } 141 142 } 143 144 func (g *Generated) recheckAndReloadCache() { 145 // 加载缓存文件,确定有哪些文件需要检查. 146 cachedInfo := &resourceBuildToDirResponse{} 147 err := kmgJson.ReadFile(kmgConfig.DefaultEnv().PathInProject("tmp/kmgViewResource_meta/"+g.Name), &cachedInfo) 148 if err != nil || cachedInfo.JsFileName == "" { 149 g.reloadCache() 150 return 151 } 152 // 第一次内存,没有数据时,需要从硬盘读入数据. 153 g.locker.Lock() 154 g.cachedInfo = *cachedInfo 155 g.locker.Unlock() 156 if !reflect.DeepEqual(cachedInfo.ImportPackageList, g.RequestImportList) { 157 g.reloadCache() 158 return 159 } 160 kmgCache.MustMd5FileChangeCache("kmgViewResource_"+g.Name, cachedInfo.NeedCachePathList, func() { 161 g.reloadCache() 162 }) 163 } 164 165 func (g *Generated) reloadCache() { 166 debugBuildPath := kmgConfig.DefaultEnv().PathInProject("tmp/kmgViewResource_debug/" + g.Name) 167 kmgFile.MustDelete(debugBuildPath) 168 response := resourceBuildToDir(g.RequestImportList, debugBuildPath) 169 response.NeedCachePathList = append(response.NeedCachePathList, debugBuildPath) 170 kmgJson.MustWriteFileIndent(kmgConfig.DefaultEnv().PathInProject("tmp/kmgViewResource_meta/"+g.Name), response) 171 g.locker.Lock() 172 g.cachedInfo = response 173 g.locker.Unlock() 174 // 重新加载 NeedCachePathList 缓存.避免同一次变化多次更新缓存. TODO data race? 175 kmgCache.MustMd5FileChangeCache("kmgViewResource_"+g.Name, response.NeedCachePathList, func() {}) 176 177 } 178 179 /* 180 TODO 修复缓存无效原因1: 181 * 用户修改了资源文件的配置,现在资源文件需要访问的package和上一次缓存时需要访问的package不一致. 182 */