summaryrefslogtreecommitdiffstats
path: root/base/common/src/com/netscape/cmscore/connector/LocalConnector.java
blob: ba2db83a137010f49531cc9c314cf030b2a244e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
// --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package com.netscape.cmscore.connector;

import java.util.Hashtable;

import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.authority.IAuthority;
import com.netscape.certsrv.authority.ICertAuthority;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.IConfigStore;
import com.netscape.certsrv.base.ISubsystem;
import com.netscape.certsrv.base.SessionContext;
import com.netscape.certsrv.connector.IConnector;
import com.netscape.certsrv.logging.ILogger;
import com.netscape.certsrv.request.IRequest;
import com.netscape.certsrv.request.IRequestListener;
import com.netscape.certsrv.request.IRequestQueue;
import com.netscape.certsrv.request.RequestId;
import com.netscape.certsrv.request.RequestStatus;
import com.netscape.cmscore.util.Debug;

public class LocalConnector implements IConnector {
    ICertAuthority mSource = null;
    IAuthority mDest = null;
    Hashtable<String, IRequest> mSourceReqs = new Hashtable<String, IRequest>();

    public LocalConnector(ICertAuthority source, IAuthority dest) {
        mSource = source;
        // mSource.log(ILogger.LL_DEBUG, "Local connector setup for source " +
        //    mSource.getId());
        mDest = dest;
        CMS.debug("Local connector setup for dest " +
                mDest.getId());
        // register for events.
        mDest.registerRequestListener(new LocalConnListener());
        CMS.debug("Connector inited");
    }

    /**
     * send request to local authority.
     * returns resulting request
     */
    public boolean send(IRequest r) throws EBaseException {
        if (Debug.ON) {
            Debug.print("send request type "
                    + r.getRequestType() + " status=" + r.getRequestStatus() + " to " + mDest.getId() + " id="
                    + r.getRequestId() + "\n");
        }
        CMS.debug("send request type " + r.getRequestType() +
                " to " + mDest.getId());

        IRequestQueue destQ = mDest.getRequestQueue();
        IRequest destreq = destQ.newRequest(r.getRequestType());

        CMS.debug("local connector dest req " +
                destreq.getRequestId() + " created for source rId " + r.getRequestId());
        //  mSource.log(ILogger.LL_DEBUG,
        //     "setting connector dest " + mDest.getId() +
        //    " source id to " + r.getRequestId());

        // XXX set context to the real identity later.
        destreq.setSourceId(
                mSource.getX500Name().toString() + ":" + r.getRequestId().toString());
        //destreq.copyContents(r);  // copy meta attributes in request.
        transferRequest(r, destreq);
        // XXX requestor type is not transferred on return.
        destreq.setExtData(IRequest.REQUESTOR_TYPE,
                IRequest.REQUESTOR_RA);
        CMS.debug("connector dest " + mDest.getId() +
                " processing " + destreq.getRequestId());

        // set context before calling process request so
        // that request subsystem can record the creator
        // of the request
        SessionContext s = SessionContext.getContext();

        if (s.get(SessionContext.USER_ID) == null) {
            // use $local$ to represent it is not a user who
            // submit the request, but it is a local subsystem
            s.put(SessionContext.USER_ID, "$local$" + mSource.getId());
        }

        // Locally cache the source request so that we
        // can update it when the dest request is
        // processed (when LocalConnListener is being called).
        mSourceReqs.put(r.getRequestId().toString(), r);
        try {
            destQ.processRequest(destreq);
        } catch (EBaseException ex) {
            throw ex;
        } finally {
            // release the source id either success or failure
            mSourceReqs.remove(r.getRequestId().toString());
        }

        CMS.debug("connector dest " + mDest.getId() +
                " processed " + destreq.getRequestId() +
                " status " + destreq.getRequestStatus());

        if (destreq.getRequestStatus() == RequestStatus.COMPLETE) {
            // no need to transfer contents if request wasn't complete.
            transferRequest(destreq, r);
            return true;
        } else {
            return false;
        }
    }

    public class LocalConnListener implements IRequestListener {

        public void init(ISubsystem sys, IConfigStore config)
                throws EBaseException {
        }

        public void set(String name, String val) {
        }

        public void accept(IRequest destreq) {
            if (Debug.ON) {
                Debug.print("dest " + mDest.getId() + " done with " + destreq.getRequestId());
            }
            CMS.debug(
                    "dest " + mDest.getId() + " done with " + destreq.getRequestId());

            IRequestQueue sourceQ = mSource.getRequestQueue();
            // accept requests that only belong to us.
            // XXX review death scenarios here. - If system dies anywhere
            // here need to check all requests at next server startup.
            String sourceNameAndId = destreq.getSourceId();
            String sourceName = mSource.getX500Name().toString();

            if (sourceNameAndId == null ||
                    !sourceNameAndId.toString().regionMatches(0,
                            sourceName, 0, sourceName.length())) {
                CMS.debug("request " + destreq.getRequestId() +
                        " from " + sourceNameAndId + " not ours.");
                return;
            }
            int index = sourceNameAndId.lastIndexOf(':');

            if (index == -1) {
                mSource.log(ILogger.LL_FAILURE,
                        "request " + destreq.getRequestId() +
                                " for " + sourceNameAndId + " malformed.");
                return;
            }
            String sourceId = sourceNameAndId.substring(index + 1);
            RequestId rId = new RequestId(sourceId);

            //    mSource.log(ILogger.LL_DEBUG, mDest.getId() + " " +
            //       destreq.getRequestId() + " mapped to " + mSource.getId() + " " + rId);

            IRequest r = null;

            // 391439: Previously, we try to access the request
            // via request queue here. Due to the recent
            // performance enhancement, approved request will
            // not be immediately available in the database. So
            // retrieving the request from the queue within
            // the serviceRequest() function will have
            // diffculities.
            // You may wonder what happen if the system crashes
            // during the request servicing. Yes, the request
            // will be lost. This is ok because the users will
            // resubmit their requests again.
            // Note that the pending requests, on the other hand,
            // are persistent before the servicing.
            // Please see stateEngine() function in
            // ARequestQueue.java for details.
            r = mSourceReqs.get(rId.toString());
            if (r != null) {
                if (r.getRequestStatus() != RequestStatus.SVC_PENDING) {
                    mSource.log(ILogger.LL_FAILURE,
                            "request state of " + rId + "not pending " +
                                    " from dest authority " + mDest.getId());
                    sourceQ.releaseRequest(r);
                    return;
                }
                transferRequest(destreq, r);
                sourceQ.markAsServiced(r);
                sourceQ.releaseRequest(r);

                CMS.debug("released request " + r.getRequestId());
            }
        }
    }

    public void start() {
    }

    public void stop() {
    }

    protected void transferRequest(IRequest src, IRequest dest) {
        RequestTransfer.transfer(src, dest);
    }
}