--- /dev/null
+// 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
+}