001: /*
002: * Routes all request from GW to Rewriter Proxy. Just a copy of NetletProxyRouter
003: * Need to consolidated in the future, All information required for consolidation
004: * is available as comments in the source code (NetletProxyRouter, RewriterProxyRouter,
005: * HostChooser, ServersList, and the Mediator classes).
006: *
007: * Reads the following properties from the Gateway profile - stored in DSAME
008: *
009: * 1. sunPortalRewriterProxyHost
010: * List of rewriter proxy instances that this gateway is configured to service
011: *
012: * 2. sunPortalGatewayServerRetryInterval
013: * Time interval - frequency at which the gateway should ping the rewriter
014: * proxy to find whether the rewriter proxy is available
015: *
016: * Maintains two list, list of available and unavailable rewriter proxies and pings
017: * at the frequency as defined by the server retry interval. Creates a worker thread
018: * to continously carry out this activity
019: *
020: * @ author Rajesh T
021: * @ Created on May 20, 2003, 12:41 PM
022: */
023:
024: package com.sun.portal.rproxy.connectionhandler;
025:
026: /**
027: * TBD: 1. Need to change protocol with respect to external hardware support for
028: * RWP 2. Thirdparty proxy is a single point of failure (SPF). Use PAC file
029: * proxies as backup proxy If need load balance between proxies returned by a
030: * PAC 3. Extend Domain's and Subdomains to return multiple thirdparty proxy for
031: * load balancing 4. Need a custom HTTP/HTTPS handler to overcome the issue
032: * associated with java.net.URL since the proxies specified as the part of JVM
033: * parameters tend to be a SPF
034: */
035:
036: import java.net.MalformedURLException;
037: import java.net.URL;
038: import java.util.HashMap;
039: import java.util.HashSet;
040: import java.util.Iterator;
041: import java.util.List;
042: import java.util.Map;
043: import java.util.Set;
044: import java.util.logging.Level;
045: import java.util.logging.Logger;
046:
047: import com.sun.portal.log.common.PortalLogger;
048: import com.sun.portal.rproxy.configservlet.client.GatewayProfile;
049: import com.sun.portal.rproxy.rewriterproxy.HTTPProxy;
050: import com.sun.portal.util.HostAvailabilityEvent;
051: import com.sun.portal.util.HostAvailabilityListener;
052: import com.sun.portal.util.HostChecker;
053:
054: public class RewriterProxyRouter extends HostAvailabilityListener {
055:
056: static Set rewriter_proxies = new HashSet();
057:
058: public static Map _unavailable_rewriter_proxies = new HashMap();
059:
060: private static int _retry;
061:
062: private static Iterator iterator;
063:
064: private static int noOfRewriterProxies = 0;
065:
066: private static String onlyOneRewriterProxy = null;
067:
068: private static final int PROXY_HTTP_PORT = 8080;
069:
070: // private static Logger logger =
071: // Logger.getLogger("com.sun.portal.sra.rproxy");
072: private static Logger logger = PortalLogger
073: .getLogger(RewriterProxyRouter.class);
074:
075: private static RewriterProxyRouter instance = new RewriterProxyRouter();
076:
077: static {
078: _retry = GatewayProfile.getInt("ServerRetryInterval", 5);
079: List allrewriter_proxies = GatewayProfile
080: .getStringList("RewriterProxyHost");
081: // List allrewriter_proxies =
082: // GatewayProfile.getStringList("NetletProxyHost");
083: Iterator it = allrewriter_proxies.iterator();
084: noOfRewriterProxies = allrewriter_proxies.size();
085:
086: /*
087: * Spoofing the third party proxy as Rewriter Proxy for a HTTPS request
088: * so that the proxy just tunnels all request thinks its https.
089: */
090:
091: if (noOfRewriterProxies == 1) {
092: onlyOneRewriterProxy = constructRWPUrl(it.next().toString());
093: } else {
094: while (it.hasNext())
095: rewriter_proxies.add(constructRWPUrl(it.next()
096: .toString().toLowerCase()));
097: iterator = rewriter_proxies.iterator();
098: }
099: }
100:
101: private static String constructRWPUrl(String userEntry) {
102: String constructedUrl = userEntry;
103:
104: try {
105: URL url = new URL(userEntry);
106: } catch (MalformedURLException e) {
107: constructedUrl = HTTPProxy.DEFAULT_RWPROXY_PROTOCOL + "://"
108: + userEntry;
109: }
110: return constructedUrl;
111: }
112:
113: private RewriterProxyRouter() {
114: addHostAvailabilityListener(this );
115: }
116:
117: public static RewriterProxyRouter getInstance() {
118: return instance;
119: }
120:
121: /*
122: * @ returns true if the specified rewriter proxy is present in the rewriter
123: * proxy host list
124: */
125:
126: private static boolean contains(String rwp) {
127: if (rwp == null || rwp.trim().length() == 0) {
128: return false;
129: }
130: if (noOfRewriterProxies == 1) {
131: return onlyOneRewriterProxy.equalsIgnoreCase(rwp);
132: } else {
133: return (rewriter_proxies.contains(rwp.toLowerCase()));
134: }
135: }
136:
137: /*
138: * @returns the next available rewriter proxy . A simple round-robin load
139: * balancing algorithm implementation with iterators.
140: */
141:
142: // DO NOT USE THIS !!
143: // This does not check whether the rwp is up and running
144: // Used only in case all rwp's are down - so that we return some valid
145: // value.
146: static synchronized String getServer() {
147:
148: /*
149: * There is no need for load balancing as there is only one rewriter
150: * proxy so return the only available rewriter proxy
151: */
152:
153: if (noOfRewriterProxies < 2) {
154: return onlyOneRewriterProxy;
155: }
156:
157: if (iterator.hasNext()) {
158: return iterator.next().toString();
159: } else {
160: iterator = rewriter_proxies.iterator();
161: return iterator.next().toString();
162: }
163: }
164:
165: /*
166: * @ returns true if the specified rewriter proxy is alive Do not create
167: * socket directly to the rewriter proxy coz there may be a external proxy
168: * server between the DMZ and intranet, typically specified as java vm
169: * parameters -Djava.proxySet, -Djava.proxyHost, -Djava.proxyPort
170: *
171: * URL factory implementation respects these parameter hence no extra
172: * tunneling code.
173: *
174: */
175:
176: private static boolean isAlive(String rwp) {
177:
178: synchronized (_unavailable_rewriter_proxies) {
179: if (!_unavailable_rewriter_proxies.isEmpty()
180: && _unavailable_rewriter_proxies.get(rwp) != null) {
181: return false; // do not use it!
182: }
183: }
184: try {
185:
186: URL url = new URL(rwp);
187: return HostChecker.isHostAvailable(url,
188: HostAvailabilityEvent.RP_HOST);
189: } catch (MalformedURLException mae) {
190: // logger.log(Level.SEVERE, "Malformed URL", mae);
191: logger.log(Level.SEVERE, "PSSRRPROXY_CSPRCONHNDLR115", mae);
192: }
193: return false;
194: }
195:
196: /*
197: * get a alive Rewriter proxy and return
198: */
199:
200: public static String getRewriterProxyAlive() {
201:
202: String rwp = null;
203: boolean alive = false;
204: if (noOfRewriterProxies == 1) {
205: if (isAlive(onlyOneRewriterProxy)) {
206: return onlyOneRewriterProxy;
207:
208: } else {
209: return null;
210: }
211: }
212:
213: int alive_servers = rewriter_proxies.size();
214:
215: while (!alive && alive_servers > 0) {
216: rwp = getServer();
217: alive = isAlive(rwp);
218: alive_servers--;
219: }
220:
221: if (alive == false)
222: return null;
223:
224: return rwp;
225: }
226:
227: static boolean isRewriterProxyAlive(String rwp) {
228: return isAlive(rwp);
229: }
230:
231: /*
232: * If the requested rewriter proxy is alive return it else return any other
233: * live rewriter proxy
234: */
235:
236: private static String getRewriterProxyAlive(String rwp) {
237: if (isAlive(rwp)) {
238: return rwp;
239: }
240:
241: return (getRewriterProxyAlive());
242: }
243:
244: public void hostAvailabilityChanged(HostAvailabilityEvent hae) {
245: if (hae.getHostType() == hae.RP_HOST) {
246: synchronized (_unavailable_rewriter_proxies) {
247: if (hae.getHostStatus() == hae.HOST_AVAILABLE) {
248: _unavailable_rewriter_proxies.remove(hae.getHost());
249: } else if (hae.getHostStatus() == hae.HOST_UNAVAILABLE) {
250: long time = System.currentTimeMillis();
251: _unavailable_rewriter_proxies.put(hae.getHost(),
252: (new Long(time)));
253: }
254: }
255: }
256: }
257: }
|