001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036: package com.sun.xml.ws.transport.http.server;
037:
038: import com.sun.net.httpserver.HttpContext;
039: import com.sun.net.httpserver.HttpServer;
040: import com.sun.xml.ws.server.ServerRtException;
041:
042: import java.net.InetSocketAddress;
043: import java.net.URL;
044: import java.util.HashMap;
045: import java.util.Map;
046: import java.util.concurrent.ExecutorService;
047: import java.util.concurrent.Executors;
048: import java.util.logging.Logger;
049:
050: /**
051: * Manages all the WebService HTTP servers created by JAXWS runtime.
052: *
053: * @author Jitendra Kotamraju
054: */
055: final class ServerMgr {
056:
057: private static final ServerMgr serverMgr = new ServerMgr();
058: private static final Logger logger = Logger
059: .getLogger(com.sun.xml.ws.util.Constants.LoggingDomain
060: + ".server.http");
061: private final Map<InetSocketAddress, ServerState> servers = new HashMap<InetSocketAddress, ServerState>();
062:
063: private ServerMgr() {
064: }
065:
066: /**
067: * Gets the singleton instance.
068: * @return manager instance
069: */
070: static ServerMgr getInstance() {
071: return serverMgr;
072: }
073:
074: /*
075: * Creates a HttpContext at the given address. If there is already a server
076: * it uses that server to create a context. Otherwise, it creates a new
077: * HTTP server. This sever is added to servers Map.
078: */
079: /*package*/HttpContext createContext(String address) {
080: try {
081: HttpServer server;
082: ServerState state;
083: URL url = new URL(address);
084: int port = url.getPort();
085: if (port == -1) {
086: port = url.getDefaultPort();
087: }
088: InetSocketAddress inetAddress = new InetSocketAddress(url
089: .getHost(), port);
090: synchronized (servers) {
091: state = servers.get(inetAddress);
092: if (state == null) {
093: logger.fine("Creating new HTTP Server at "
094: + inetAddress);
095: server = HttpServer.create(inetAddress, 5);
096: server.setExecutor(Executors.newCachedThreadPool());
097: String path = url.toURI().getPath();
098: logger.fine("Creating HTTP Context at = " + path);
099: HttpContext context = server.createContext(path);
100: server.start();
101: logger.fine("HTTP server started = " + inetAddress);
102: state = new ServerState(server);
103: servers.put(inetAddress, state);
104: return context;
105: }
106: }
107: server = state.getServer();
108: logger.fine("Creating HTTP Context at = " + url.getPath());
109: HttpContext context = server.createContext(url.getPath());
110: state.oneMoreContext();
111: return context;
112: } catch (Exception e) {
113: throw new ServerRtException("server.rt.err", e);
114: }
115: }
116:
117: /*
118: * Removes a context. If the server doesn't have anymore contexts, it
119: * would stop the server and server is removed from servers Map.
120: */
121: /*package*/void removeContext(HttpContext context) {
122: InetSocketAddress inetAddress = context.getServer()
123: .getAddress();
124: synchronized (servers) {
125: ServerState state = servers.get(inetAddress);
126: int instances = state.noOfContexts();
127: if (instances < 2) {
128: ((ExecutorService) state.getServer().getExecutor())
129: .shutdown();
130: state.getServer().stop(0);
131: servers.remove(inetAddress);
132: } else {
133: state.getServer().removeContext(context);
134: state.oneLessContext();
135: }
136: }
137: }
138:
139: private static final class ServerState {
140: private final HttpServer server;
141: private int instances;
142:
143: ServerState(HttpServer server) {
144: this .server = server;
145: this .instances = 1;
146: }
147:
148: public HttpServer getServer() {
149: return server;
150: }
151:
152: public void oneMoreContext() {
153: ++instances;
154: }
155:
156: public void oneLessContext() {
157: --instances;
158: }
159:
160: public int noOfContexts() {
161: return instances;
162: }
163: }
164: }
|