Add API Framework Revel Source Files
[iec.git] / src / foundation / api / revel / revel.go
diff --git a/src/foundation/api/revel/revel.go b/src/foundation/api/revel/revel.go
new file mode 100644 (file)
index 0000000..27ac6ef
--- /dev/null
@@ -0,0 +1,301 @@
+// Copyright (c) 2012-2016 The Revel Framework Authors, All rights reserved.
+// Revel Framework source code and usage is governed by a MIT style
+// license that can be found in the LICENSE file.
+
+package revel
+
+import (
+       "go/build"
+       "log"
+       "path/filepath"
+       "strings"
+
+       "encoding/json"
+       "fmt"
+       "github.com/revel/config"
+       "github.com/revel/revel/logger"
+       "github.com/revel/revel/model"
+)
+
+const (
+       // RevelImportPath Revel framework import path
+       RevelImportPath = "github.com/revel/revel"
+)
+
+const (
+       TEST_MODE_FLAG   = "testModeFlag"
+       SPECIAL_USE_FLAG = "specialUseFlag"
+)
+
+// App details
+var (
+       RevelConfig *model.RevelContainer
+       AppName    string // e.g. "sample"
+       AppRoot    string // e.g. "/app1"
+       BasePath   string // e.g. "$GOPATH/src/corp/sample"
+       AppPath    string // e.g. "$GOPATH/src/corp/sample/app"
+       ViewsPath  string // e.g. "$GOPATH/src/corp/sample/app/views"
+       ImportPath string // e.g. "corp/sample"
+       SourcePath string // e.g. "$GOPATH/src"
+
+       Config  *config.Context
+       RunMode string // Application-defined (by default, "dev" or "prod")
+       DevMode bool   // if true, RunMode is a development mode.
+
+       // Revel installation details
+       RevelPath string // e.g. "$GOPATH/src/github.com/revel/revel"
+
+       // Where to look for templates
+       // Ordered by priority. (Earlier paths take precedence over later paths.)
+       CodePaths     []string // Code base directories, for modules and app
+       TemplatePaths []string // Template path directories manually added
+
+       // ConfPaths where to look for configurations
+       // Config load order
+       // 1. framework (revel/conf/*)
+       // 2. application (conf/*)
+       // 3. user supplied configs (...) - User configs can override/add any from above
+       ConfPaths []string
+
+       // Server config.
+       //
+       // Alert: This is how the app is configured, which may be different from
+       // the current process reality.  For example, if the app is configured for
+       // port 9000, HTTPPort will always be 9000, even though in dev mode it is
+       // run on a random port and proxied.
+       HTTPPort    int    // e.g. 9000
+       HTTPAddr    string // e.g. "", "127.0.0.1"
+       HTTPSsl     bool   // e.g. true if using ssl
+       HTTPSslCert string // e.g. "/path/to/cert.pem"
+       HTTPSslKey  string // e.g. "/path/to/key.pem"
+
+       // All cookies dropped by the framework begin with this prefix.
+       CookiePrefix string
+       // Cookie domain
+       CookieDomain string
+       // Cookie flags
+       CookieSecure bool
+
+       // Revel request access log, not exposed from package.
+       // However output settings can be controlled from app.conf
+
+       // True when revel engine has been initialized (Init has returned)
+       Initialized bool
+
+       // Private
+       secretKey     []byte             // Key used to sign cookies. An empty key disables signing.
+       packaged      bool               // If true, this is running from a pre-built package.
+       initEventList = []EventHandler{} // Event handler list for receiving events
+)
+
+// Init initializes Revel -- it provides paths for getting around the app.
+//
+// Params:
+//   mode - the run mode, which determines which app.conf settings are used.
+//   importPath - the Go import path of the application.
+//   srcPath - the path to the source directory, containing Revel and the app.
+//     If not specified (""), then a functioning Go installation is required.
+func Init(inputmode, importPath, srcPath string) {
+       RevelConfig = &model.RevelContainer{}
+       // Ignore trailing slashes.
+       ImportPath = strings.TrimRight(importPath, "/")
+       SourcePath = srcPath
+
+       RunMode = updateLog(inputmode)
+
+       // If the SourcePath is not specified, find it using build.Import.
+       var revelSourcePath string // may be different from the app source path
+       if SourcePath == "" {
+               revelSourcePath, SourcePath = findSrcPaths(importPath)
+       } else {
+               // If the SourcePath was specified, assume both Revel and the app are within it.
+               SourcePath = filepath.Clean(SourcePath)
+               revelSourcePath = SourcePath
+               packaged = true
+       }
+
+       RevelPath = filepath.Join(revelSourcePath, filepath.FromSlash(RevelImportPath))
+       BasePath = filepath.Join(SourcePath, filepath.FromSlash(importPath))
+       AppPath = filepath.Join(BasePath, "app")
+       ViewsPath = filepath.Join(AppPath, "views")
+
+       CodePaths = []string{AppPath}
+
+       if ConfPaths == nil {
+               ConfPaths = []string{}
+       }
+
+       // Config load order
+       // 1. framework (revel/conf/*)
+       // 2. application (conf/*)
+       // 3. user supplied configs (...) - User configs can override/add any from above
+       ConfPaths = append(
+               []string{
+                       filepath.Join(RevelPath, "conf"),
+                       filepath.Join(BasePath, "conf"),
+               },
+               ConfPaths...)
+
+       TemplatePaths = []string{
+               ViewsPath,
+               filepath.Join(RevelPath, "templates"),
+       }
+
+       // Load app.conf
+       var err error
+       Config, err = config.LoadContext("app.conf", ConfPaths)
+       if err != nil || Config == nil {
+               RevelLog.Fatal("Failed to load app.conf:", "error", err)
+       }
+
+       // After application config is loaded update the logger
+       updateLog(inputmode)
+
+       // Configure properties from app.conf
+       DevMode = Config.BoolDefault("mode.dev", false)
+       HTTPPort = Config.IntDefault("http.port", 9000)
+       HTTPAddr = Config.StringDefault("http.addr", "")
+       HTTPSsl = Config.BoolDefault("http.ssl", false)
+       HTTPSslCert = Config.StringDefault("http.sslcert", "")
+       HTTPSslKey = Config.StringDefault("http.sslkey", "")
+       if HTTPSsl {
+               if HTTPSslCert == "" {
+                       RevelLog.Fatal("No http.sslcert provided.")
+               }
+               if HTTPSslKey == "" {
+                       RevelLog.Fatal("No http.sslkey provided.")
+               }
+       }
+
+       AppName = Config.StringDefault("app.name", "(not set)")
+       AppRoot = Config.StringDefault("app.root", "")
+       CookiePrefix = Config.StringDefault("cookie.prefix", "REVEL")
+       CookieDomain = Config.StringDefault("cookie.domain", "")
+       CookieSecure = Config.BoolDefault("cookie.secure", HTTPSsl)
+       if secretStr := Config.StringDefault("app.secret", ""); secretStr != "" {
+               SetSecretKey([]byte(secretStr))
+       }
+
+       RaiseEvent(REVEL_BEFORE_MODULES_LOADED, nil)
+       loadModules()
+       RaiseEvent(REVEL_AFTER_MODULES_LOADED, nil)
+
+       Initialized = true
+       RevelLog.Info("Initialized Revel", "Version", Version, "BuildDate", BuildDate, "MinimumGoVersion", MinimumGoVersion)
+}
+
+// The input mode can be as simple as "prod" or it can be a JSON string like
+// {"mode":"%s","testModeFlag":true}
+// When this function is called it returns the true "inputmode" extracted from the parameter
+// and it sets the log context appropriately
+func updateLog(inputmode string) (returnMode string) {
+       if inputmode == "" {
+               returnMode = config.DefaultSection
+               return
+       } else {
+               returnMode = inputmode
+       }
+
+       // Check to see if the mode is a json object
+       modemap := map[string]interface{}{}
+
+       var testModeFlag, specialUseFlag bool
+       if err := json.Unmarshal([]byte(inputmode), &modemap); err == nil {
+               returnMode = modemap["mode"].(string)
+               if testmode, found := modemap[TEST_MODE_FLAG]; found {
+                       testModeFlag, _ = testmode.(bool)
+               }
+               if specialUse, found := modemap[SPECIAL_USE_FLAG]; found {
+                       specialUseFlag, _ = specialUse.(bool)
+               }
+       }
+
+       var newContext *config.Context
+       // If the Config is nil, set the logger to minimal log messages by adding the option
+       if Config == nil {
+               newContext = config.NewContext()
+               newContext.SetOption(TEST_MODE_FLAG, fmt.Sprint(true))
+       } else {
+               // Ensure that the selected runmode appears in app.conf.
+               // If empty string is passed as the mode, treat it as "DEFAULT"
+               if !Config.HasSection(returnMode) {
+                       log.Fatalln("app.conf: No mode found:", returnMode)
+               }
+               Config.SetSection(returnMode)
+               newContext = Config
+       }
+
+       // Only set the testmode flag if it doesnt exist
+       if _, found := newContext.Bool(TEST_MODE_FLAG); !found {
+               newContext.SetOption(TEST_MODE_FLAG, fmt.Sprint(testModeFlag))
+       }
+       if _, found := newContext.Bool(SPECIAL_USE_FLAG); !found {
+               newContext.SetOption(SPECIAL_USE_FLAG, fmt.Sprint(specialUseFlag))
+       }
+
+       appHandle := logger.InitializeFromConfig(BasePath, newContext)
+
+       // Set all the log handlers
+       setAppLog(AppLog, appHandle)
+
+       return
+}
+
+// Set the secret key
+func SetSecretKey(newKey []byte) error {
+       secretKey = newKey
+       return nil
+}
+
+// ResolveImportPath returns the filesystem path for the given import path.
+// Returns an error if the import path could not be found.
+func ResolveImportPath(importPath string) (string, error) {
+       if packaged {
+               return filepath.Join(SourcePath, importPath), nil
+       }
+
+       modPkg, err := build.Import(importPath, RevelPath, build.FindOnly)
+       if err != nil {
+               return "", err
+       }
+       return modPkg.Dir, nil
+}
+
+// CheckInit method checks `revel.Initialized` if not initialized it panics
+func CheckInit() {
+       if !Initialized {
+               RevelLog.Panic("CheckInit: Revel has not been initialized!")
+       }
+}
+
+// findSrcPaths uses the "go/build" package to find the source root for Revel
+// and the app.
+func findSrcPaths(importPath string) (revelSourcePath, appSourcePath string) {
+       var (
+               gopaths = filepath.SplitList(build.Default.GOPATH)
+               goroot  = build.Default.GOROOT
+       )
+
+       if len(gopaths) == 0 {
+               RevelLog.Fatal("GOPATH environment variable is not set. " +
+                       "Please refer to http://golang.org/doc/code.html to configure your Go environment.")
+       }
+
+       if ContainsString(gopaths, goroot) {
+               RevelLog.Fatalf("GOPATH (%s) must not include your GOROOT (%s). "+
+                       "Please refer to http://golang.org/doc/code.html to configure your Go environment.",
+                       gopaths, goroot)
+       }
+
+       appPkg, err := build.Import(importPath, "", build.FindOnly)
+       if err != nil {
+               RevelLog.Panic("Failed to import "+importPath+" with error:", "error", err)
+       }
+
+       revelPkg, err := build.Import(RevelImportPath, appPkg.Dir, build.FindOnly)
+       if err != nil {
+               RevelLog.Fatal("Failed to find Revel with error:", "error", err)
+       }
+
+       return revelPkg.Dir[:len(revelPkg.Dir)-len(RevelImportPath)], appPkg.SrcRoot
+}