001: package org.jacorb.orb.giop;
002:
003: /*
004: * JacORB - a free Java ORB
005: *
006: * Copyright (C) 1997-2004 Gerald Brose.
007: *
008: * This library is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU Library General Public
010: * License as published by the Free Software Foundation; either
011: * version 2 of the License, or (at your option) any later version.
012: *
013: * This library is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016: * Library General Public License for more details.
017: *
018: * You should have received a copy of the GNU Library General Public
019: * License along with this library; if not, write to the Free
020: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
021: */
022:
023: import java.io.IOException;
024: import java.util.List;
025:
026: import org.apache.avalon.framework.configuration.Configurable;
027: import org.apache.avalon.framework.configuration.Configuration;
028: import org.apache.avalon.framework.configuration.ConfigurationException;
029: import org.apache.avalon.framework.logger.Logger;
030: import org.jacorb.orb.ORB;
031: import org.jacorb.orb.SystemExceptionHelper;
032: import org.jacorb.orb.dsi.ServerRequest;
033: import org.jacorb.poa.POA;
034: import org.omg.CONV_FRAME.CodeSetContext;
035: import org.omg.CORBA.CompletionStatus;
036: import org.omg.CORBA.NO_PERMISSION;
037: import org.omg.CORBA.OBJECT_NOT_EXIST;
038: import org.omg.GIOP.LocateStatusType_1_2;
039: import org.omg.GIOP.ReplyStatusType_1_2;
040:
041: /**
042: * @author Nicolas Noffke
043: * @version $Id: ServerRequestListener.java,v 1.25 2006/07/10 08:56:00 alphonse.bendt Exp $
044: */
045: public class ServerRequestListener implements RequestListener,
046: Configurable {
047: private final ORB orb;
048: private final POA rootPOA;
049:
050: /** the configuration object */
051: private Logger logger = null;
052: private boolean require_ssl = false;
053:
054: public ServerRequestListener(ORB orb, POA rootPOA) {
055: this .orb = orb;
056: this .rootPOA = rootPOA;
057: }
058:
059: public void configure(Configuration myConfiguration)
060: throws ConfigurationException {
061: org.jacorb.config.Configuration configuration = (org.jacorb.config.Configuration) myConfiguration;
062: logger = configuration
063: .getNamedLogger("jacorb.giop.server.listener");
064:
065: boolean supportSSL = configuration.getAttribute(
066: "jacorb.security.support_ssl", "off").equals("on");
067:
068: if (supportSSL) {
069: int required = configuration.getAttributeAsInteger(
070: "jacorb.security.ssl.server.required_options", 16);
071:
072: //if we require EstablishTrustInTarget or
073: //EstablishTrustInClient, SSL must be used.
074: require_ssl = supportSSL && (required & 0x60) != 0;
075: }
076: }
077:
078: public void requestReceived(byte[] request,
079: GIOPConnection connection) {
080: RequestInputStream inputStream = new RequestInputStream(orb,
081: request);
082:
083: if (require_ssl && !connection.isSSL()) {
084: ReplyOutputStream out = new ReplyOutputStream(
085: inputStream.req_hdr.request_id,
086: ReplyStatusType_1_2.SYSTEM_EXCEPTION, inputStream
087: .getGIOPMinor(), false, logger); //no locate reply
088:
089: logger
090: .debug("About to reject request because connection is not SSL.");
091:
092: SystemExceptionHelper.write(out, new NO_PERMISSION(3,
093: CompletionStatus.COMPLETED_NO));
094:
095: try {
096: connection.sendReply(out);
097: } catch (IOException e) {
098: logger.warn("IOException", e);
099: }
100:
101: return;
102: }
103:
104: //only block timeouts, if a reply needs to be sent
105: if (Messages
106: .responseExpected(inputStream.req_hdr.response_flags)) {
107: connection.incPendingMessages();
108: }
109:
110: if (!connection.isTCSNegotiated()) {
111: //If GIOP 1.0 is used don't check for a codeset context
112: if (inputStream.getGIOPMinor() == 0) {
113: connection.markTCSNegotiated();
114: } else {
115: CodeSetContext ctx = CodeSet
116: .getCodeSetContext(inputStream.req_hdr.service_context);
117:
118: if (ctx != null) {
119: connection.setCodeSets(ctx.char_data,
120: ctx.wchar_data);
121: connection.markTCSNegotiated();
122: if (logger.isDebugEnabled()) {
123: logger.debug("Received CodeSetContext. Using "
124: + CodeSet.csName(ctx.char_data)
125: + " as TCS and "
126: + CodeSet.csName(ctx.wchar_data)
127: + " as TCSW");
128: }
129: }
130: }
131: }
132:
133: inputStream.setCodeSet(connection.getTCS(), connection
134: .getTCSW());
135:
136: inputStream.updateMutatorConnection(connection);
137:
138: ServerRequest server_request = null;
139:
140: try {
141: server_request = new ServerRequest(orb, inputStream,
142: connection);
143: } catch (org.jacorb.poa.except.POAInternalError pie) {
144: logger
145: .warn("Received a request with a non-jacorb object key");
146:
147: if (inputStream.isLocateRequest()) {
148: LocateReplyOutputStream lr_out = new LocateReplyOutputStream(
149: inputStream.req_hdr.request_id,
150: LocateStatusType_1_2._UNKNOWN_OBJECT,
151: inputStream.getGIOPMinor());
152:
153: try {
154: connection.sendReply(lr_out);
155: } catch (IOException e) {
156: logger.warn("IOException", e);
157: }
158: } else {
159: ReplyOutputStream out = new ReplyOutputStream(
160: inputStream.req_hdr.request_id,
161: ReplyStatusType_1_2.SYSTEM_EXCEPTION,
162: inputStream.getGIOPMinor(), false, logger);//no locate reply
163:
164: SystemExceptionHelper.write(out, new OBJECT_NOT_EXIST(
165: 0, CompletionStatus.COMPLETED_NO));
166:
167: try {
168: connection.sendReply(out);
169: } catch (IOException e) {
170: logger.warn("IOException", e);
171: }
172: }
173:
174: return;
175: }
176:
177: deliverRequest(server_request);
178: }
179:
180: public void locateRequestReceived(byte[] request,
181: GIOPConnection connection) {
182: //for the time being, map to normal request
183: requestReceived(request, connection);
184: }
185:
186: public void cancelRequestReceived(byte[] request,
187: GIOPConnection connection) {
188: // nothing to do
189: }
190:
191: private void deliverRequest(ServerRequest request) {
192: POA tmp_poa = rootPOA;
193: String res;
194: List scopes;
195:
196: try {
197: // This is similar to code within ORB::findPOA but
198: // sufficiently different that it is reproduced here.
199: String refImplName = "";
200: final String orbImplName = orb.getImplName();
201: final String orbServerId = orb.getServerIdString();
202:
203: try {
204: refImplName = org.jacorb.poa.util.POAUtil
205: .extractImplName(request.objectKey());
206: } catch (org.jacorb.poa.except.POAInternalError pie) {
207: logger
208: .debug("serverRequestListener: reference generated by foreign POA");
209: }
210: if (!(orbImplName.equals(refImplName))
211: && !(orbServerId.equals(refImplName))) {
212: if (logger.isDebugEnabled()) {
213: logger
214: .debug("serverRequestListener: impl_name mismatch (refImplName: "
215: + refImplName
216: + " and orbServerId "
217: + orbServerId
218: + " and orbImplName "
219: + orbImplName);
220: }
221: throw new org.omg.PortableServer.POAPackage.WrongAdapter();
222: }
223:
224: // Get cached scopes from ServerRequest
225: scopes = request.getScopes();
226:
227: for (int i = 0; i < scopes.size(); i++) {
228: res = ((String) scopes.get(i));
229:
230: if (res.equals("")) {
231: break;
232: }
233:
234: /* the following is a call to a method in the private
235: interface between the ORB and the POA. It does the
236: necessary synchronization between incoming,
237: potentially concurrent requests to activate a POA
238: using its adapter activator. This call will block
239: until the correct POA is activated and ready to
240: service requests. Thus, concurrent calls
241: originating from a single, multi-threaded client
242: will be serialized because the thread that accepts
243: incoming requests from the client process is
244: blocked. Concurrent calls from other destinations
245: are not serialized unless they involve activating
246: the same adapter.
247: */
248:
249: try {
250: tmp_poa = tmp_poa._getChildPOA(res);
251: } catch (org.jacorb.poa.except.ParentIsHolding p) {
252: /* if one of the POAs is in holding state, we
253: simply deliver deliver the request to this
254: POA. It will forward the request to its
255: child POAs if necessary when changing back
256: to active For the POA to be able to forward
257: this request to its child POAa, we need to
258: supply the remaining part of the child's
259: POA name */
260:
261: String[] rest_of_name = new String[scopes.size()
262: - i];
263: for (int j = 0; j < i; j++) {
264: rest_of_name[j] = (String) scopes.get(j + i);
265: }
266:
267: request.setRemainingPOAName(rest_of_name);
268:
269: break;
270: }
271: }
272:
273: if (tmp_poa == null) {
274: throw new org.omg.CORBA.INTERNAL("Request POA null!");
275: }
276: /* hand over to the POA */
277: tmp_poa._invoke(request);
278: } catch (org.omg.PortableServer.POAPackage.WrongAdapter e) {
279: // unknown oid (not previously generated)
280: request
281: .setSystemException(new org.omg.CORBA.OBJECT_NOT_EXIST(
282: "unknown oid"));
283: request.reply();
284: } catch (org.omg.CORBA.SystemException e) {
285: request.setSystemException(e);
286: request.reply();
287: } catch (RuntimeException e) {
288: request.setSystemException(new org.omg.CORBA.UNKNOWN(e
289: .toString()));
290: request.reply();
291: logger.warn("unexpected exception", e);
292: }
293: }
294: }
|