Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / google.golang.org / appengine / internal / api_classic.go
1 // Copyright 2015 Google Inc. All rights reserved.
2 // Use of this source code is governed by the Apache 2.0
3 // license that can be found in the LICENSE file.
4
5 // +build appengine
6
7 package internal
8
9 import (
10         "errors"
11         "fmt"
12         "net/http"
13         "time"
14
15         "appengine"
16         "appengine_internal"
17         basepb "appengine_internal/base"
18
19         "github.com/golang/protobuf/proto"
20         netcontext "golang.org/x/net/context"
21 )
22
23 var contextKey = "holds an appengine.Context"
24
25 // fromContext returns the App Engine context or nil if ctx is not
26 // derived from an App Engine context.
27 func fromContext(ctx netcontext.Context) appengine.Context {
28         c, _ := ctx.Value(&contextKey).(appengine.Context)
29         return c
30 }
31
32 // This is only for classic App Engine adapters.
33 func ClassicContextFromContext(ctx netcontext.Context) (appengine.Context, error) {
34         c := fromContext(ctx)
35         if c == nil {
36                 return nil, errNotAppEngineContext
37         }
38         return c, nil
39 }
40
41 func withContext(parent netcontext.Context, c appengine.Context) netcontext.Context {
42         ctx := netcontext.WithValue(parent, &contextKey, c)
43
44         s := &basepb.StringProto{}
45         c.Call("__go__", "GetNamespace", &basepb.VoidProto{}, s, nil)
46         if ns := s.GetValue(); ns != "" {
47                 ctx = NamespacedContext(ctx, ns)
48         }
49
50         return ctx
51 }
52
53 func IncomingHeaders(ctx netcontext.Context) http.Header {
54         if c := fromContext(ctx); c != nil {
55                 if req, ok := c.Request().(*http.Request); ok {
56                         return req.Header
57                 }
58         }
59         return nil
60 }
61
62 func ReqContext(req *http.Request) netcontext.Context {
63         return WithContext(netcontext.Background(), req)
64 }
65
66 func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context {
67         c := appengine.NewContext(req)
68         return withContext(parent, c)
69 }
70
71 type testingContext struct {
72         appengine.Context
73
74         req *http.Request
75 }
76
77 func (t *testingContext) FullyQualifiedAppID() string { return "dev~testcontext" }
78 func (t *testingContext) Call(service, method string, _, _ appengine_internal.ProtoMessage, _ *appengine_internal.CallOptions) error {
79         if service == "__go__" && method == "GetNamespace" {
80                 return nil
81         }
82         return fmt.Errorf("testingContext: unsupported Call")
83 }
84 func (t *testingContext) Request() interface{} { return t.req }
85
86 func ContextForTesting(req *http.Request) netcontext.Context {
87         return withContext(netcontext.Background(), &testingContext{req: req})
88 }
89
90 func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error {
91         if ns := NamespaceFromContext(ctx); ns != "" {
92                 if fn, ok := NamespaceMods[service]; ok {
93                         fn(in, ns)
94                 }
95         }
96
97         if f, ctx, ok := callOverrideFromContext(ctx); ok {
98                 return f(ctx, service, method, in, out)
99         }
100
101         // Handle already-done contexts quickly.
102         select {
103         case <-ctx.Done():
104                 return ctx.Err()
105         default:
106         }
107
108         c := fromContext(ctx)
109         if c == nil {
110                 // Give a good error message rather than a panic lower down.
111                 return errNotAppEngineContext
112         }
113
114         // Apply transaction modifications if we're in a transaction.
115         if t := transactionFromContext(ctx); t != nil {
116                 if t.finished {
117                         return errors.New("transaction context has expired")
118                 }
119                 applyTransaction(in, &t.transaction)
120         }
121
122         var opts *appengine_internal.CallOptions
123         if d, ok := ctx.Deadline(); ok {
124                 opts = &appengine_internal.CallOptions{
125                         Timeout: d.Sub(time.Now()),
126                 }
127         }
128
129         err := c.Call(service, method, in, out, opts)
130         switch v := err.(type) {
131         case *appengine_internal.APIError:
132                 return &APIError{
133                         Service: v.Service,
134                         Detail:  v.Detail,
135                         Code:    v.Code,
136                 }
137         case *appengine_internal.CallError:
138                 return &CallError{
139                         Detail:  v.Detail,
140                         Code:    v.Code,
141                         Timeout: v.Timeout,
142                 }
143         }
144         return err
145 }
146
147 func handleHTTP(w http.ResponseWriter, r *http.Request) {
148         panic("handleHTTP called; this should be impossible")
149 }
150
151 func logf(c appengine.Context, level int64, format string, args ...interface{}) {
152         var fn func(format string, args ...interface{})
153         switch level {
154         case 0:
155                 fn = c.Debugf
156         case 1:
157                 fn = c.Infof
158         case 2:
159                 fn = c.Warningf
160         case 3:
161                 fn = c.Errorf
162         case 4:
163                 fn = c.Criticalf
164         default:
165                 // This shouldn't happen.
166                 fn = c.Criticalf
167         }
168         fn(format, args...)
169 }