001: /*
002: * Copyright 2005-2007 Noelios Consulting.
003: *
004: * The contents of this file are subject to the terms of the Common Development
005: * and Distribution License (the "License"). You may not use this file except in
006: * compliance with the License.
007: *
008: * You can obtain a copy of the license at
009: * http://www.opensource.org/licenses/cddl1.txt See the License for the specific
010: * language governing permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL HEADER in each file and
013: * include the License file at http://www.opensource.org/licenses/cddl1.txt If
014: * applicable, add the following below this CDDL HEADER, with the fields
015: * enclosed by brackets "[]" replaced with your own identifying information:
016: * Portions Copyright [yyyy] [name of copyright owner]
017: */
018:
019: package com.noelios.restlet.component;
020:
021: import java.util.Iterator;
022: import java.util.logging.Level;
023: import java.util.logging.Logger;
024:
025: import org.restlet.Application;
026: import org.restlet.Client;
027: import org.restlet.Component;
028: import org.restlet.Context;
029: import org.restlet.Filter;
030: import org.restlet.Restlet;
031: import org.restlet.Route;
032: import org.restlet.Server;
033: import org.restlet.VirtualHost;
034: import org.restlet.data.Protocol;
035: import org.restlet.data.Request;
036: import org.restlet.data.Response;
037: import org.restlet.data.Status;
038:
039: import com.noelios.restlet.ChainHelper;
040: import com.noelios.restlet.StatusFilter;
041:
042: /**
043: * Component helper.
044: *
045: * @author Jerome Louvel (contact@noelios.com)
046: */
047: public class ComponentHelper extends ChainHelper {
048: /** The helped component. */
049: private Component component;
050:
051: /** The internal client router. */
052: private ClientRouter clientRouter;
053:
054: /** The internal server router. */
055: private ServerRouter serverRouter;
056:
057: /**
058: * Constructor.
059: *
060: * @param component
061: * The helper component.
062: */
063: public ComponentHelper(Component component) {
064: super (null);
065: this .component = component;
066: this .clientRouter = new ClientRouter(getComponent());
067: this .serverRouter = new ServerRouter(getComponent());
068: }
069:
070: /**
071: * Creates a new context.
072: *
073: * @param loggerName
074: * The JDK's logger name to use for contextual logging.
075: * @return The new context.
076: */
077: public Context createContext(String loggerName) {
078: return new ComponentContext(this , Logger.getLogger(loggerName));
079: }
080:
081: /**
082: * Returns the internal client router.
083: *
084: * @return the internal client router.
085: */
086: public ClientRouter getClientRouter() {
087: return this .clientRouter;
088: }
089:
090: /**
091: * Returns the helped component.
092: *
093: * @return The helped component.
094: */
095: protected Component getComponent() {
096: return this .component;
097: }
098:
099: /**
100: * Returns the internal host router.
101: *
102: * @return the internal host router.
103: */
104: public ServerRouter getServerRouter() {
105: return this .serverRouter;
106: }
107:
108: /**
109: * Handles a call.
110: *
111: * @param request
112: * The request to handle.
113: * @param response
114: * The response to update.
115: */
116: public void handle(Request request, Response response) {
117: if (getFirst() != null) {
118: getFirst().handle(request, response);
119: } else {
120: response.setStatus(Status.SERVER_ERROR_INTERNAL);
121: getComponent()
122: .getLogger()
123: .log(Level.SEVERE,
124: "The component wasn't properly started, it can't handle calls.");
125: }
126: }
127:
128: /** Start callback. */
129: public void start() throws Exception {
130: // Initialization of services
131: Filter lastFilter = null;
132:
133: // Checking if all applications have proper connectors
134: boolean success = checkVirtualHost(getComponent()
135: .getDefaultHost());
136: if (success) {
137: for (VirtualHost host : getComponent().getHosts()) {
138: success = success && checkVirtualHost(host);
139: }
140: }
141:
142: // Let's actually start the component
143: if (!success) {
144: getComponent().stop();
145: } else {
146: // Logging of calls
147: if (getComponent().getLogService().isEnabled()) {
148: lastFilter = createLogFilter(getComponent()
149: .getContext(), getComponent().getLogService());
150: setFirst(lastFilter);
151: }
152:
153: // Addition of status pages
154: if (getComponent().getStatusService().isEnabled()) {
155: Filter statusFilter = createStatusFilter(getComponent());
156: if (lastFilter != null)
157: lastFilter.setNext(statusFilter);
158: if (getFirst() == null)
159: setFirst(statusFilter);
160: lastFilter = statusFilter;
161: }
162:
163: // Reattach the original filter's attached Restlet
164: if (getFirst() == null) {
165: setFirst(getServerRouter());
166: } else {
167: lastFilter.setNext(getServerRouter());
168: }
169: }
170: }
171:
172: /**
173: * Check the applications attached to a virtual host.
174: *
175: * @param host
176: * The parent virtual host.
177: * @return True if the check succeeded.
178: * @throws Exception
179: */
180: private boolean checkVirtualHost(VirtualHost host) throws Exception {
181: boolean result = true;
182:
183: if (host != null) {
184: for (Route route : host.getRoutes()) {
185: Restlet next = route.getNext();
186:
187: if (next instanceof Application) {
188: Application application = (Application) next;
189:
190: for (Protocol clientProtocol : application
191: .getConnectorService().getClientProtocols()) {
192: boolean clientFound = false;
193:
194: // Try to find a client connector matching the client
195: // protocol
196: Client client;
197: for (Iterator<Client> iter = getComponent()
198: .getClients().iterator(); !clientFound
199: && iter.hasNext();) {
200: client = iter.next();
201: clientFound = client.getProtocols()
202: .contains(clientProtocol);
203: }
204:
205: if (!clientFound) {
206: getComponent()
207: .getLogger()
208: .severe(
209: "Unable to start the application \""
210: + application
211: .getName()
212: + "\". Client connector for protocol "
213: + clientProtocol
214: .getName()
215: + " is missing.");
216: result = false;
217: }
218: }
219:
220: for (Protocol serverProtocol : application
221: .getConnectorService().getServerProtocols()) {
222: boolean serverFound = false;
223:
224: // Try to find a server connector matching the server
225: // protocol
226: Server server;
227: for (Iterator<Server> iter = getComponent()
228: .getServers().iterator(); !serverFound
229: && iter.hasNext();) {
230: server = iter.next();
231: serverFound = server.getProtocols()
232: .contains(serverProtocol);
233: }
234:
235: if (!serverFound) {
236: getComponent()
237: .getLogger()
238: .severe(
239: "Unable to start the application \""
240: + application
241: .getName()
242: + "\". Server connector for protocol "
243: + serverProtocol
244: .getName()
245: + " is missing.");
246: result = false;
247: }
248: }
249:
250: if (result && application.isStopped()) {
251: application.start();
252: }
253: }
254: }
255: }
256:
257: return result;
258: }
259:
260: /**
261: * Creates a new status filter. Allows overriding.
262: *
263: * @param component
264: * The parent component.
265: * @return The new status filter.
266: */
267: protected StatusFilter createStatusFilter(Component component) {
268: return new ComponentStatusFilter(component);
269: }
270:
271: /** Stop callback. */
272: public void stop() throws Exception {
273: // Stop the server's router
274: getServerRouter().stop();
275:
276: // Stop all applications
277: stopVirtualHostApplications(getComponent().getDefaultHost());
278: for (VirtualHost host : getComponent().getHosts()) {
279: stopVirtualHostApplications(host);
280: }
281: }
282:
283: /**
284: * Stop all applications attached to a virtual host
285: *
286: * @param host
287: * @throws Exception
288: */
289: private void stopVirtualHostApplications(VirtualHost host)
290: throws Exception {
291: for (Route route : host.getRoutes()) {
292: Restlet next = route.getNext();
293:
294: if (next instanceof Application) {
295: Application application = (Application) next;
296:
297: if (application.isStarted()) {
298: application.stop();
299: }
300: }
301: }
302: }
303:
304: }
|