001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.cluster;
016    
017    import com.liferay.portal.kernel.cluster.Address;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.util.CharPool;
021    import com.liferay.portal.kernel.util.GetterUtil;
022    import com.liferay.portal.kernel.util.SocketUtil;
023    import com.liferay.portal.kernel.util.Validator;
024    import com.liferay.portal.util.PropsValues;
025    
026    import java.net.InetAddress;
027    import java.net.NetworkInterface;
028    
029    import java.util.ArrayList;
030    import java.util.Collections;
031    import java.util.List;
032    
033    import org.jgroups.JChannel;
034    import org.jgroups.Receiver;
035    import org.jgroups.View;
036    import org.jgroups.stack.Protocol;
037    import org.jgroups.stack.ProtocolStack;
038    
039    /**
040     * @author Shuyang Zhou
041     */
042    public abstract class ClusterBase {
043    
044            public void afterPropertiesSet() {
045                    if (!isEnabled()) {
046                            return;
047                    }
048    
049                    if (!_initJGroupsProperties) {
050                            initSystemProperties();
051    
052                            try {
053                                    initBindAddress();
054                            }
055                            catch (Exception e) {
056                                    if (_log.isWarnEnabled()) {
057                                            _log.warn("Failed to initialize outgoing IP address", e);
058                                    }
059                            }
060    
061                            _initJGroupsProperties = true;
062                    }
063            }
064    
065            public abstract void destroy();
066    
067            public boolean isEnabled() {
068                    return PropsValues.CLUSTER_LINK_ENABLED;
069            }
070    
071            protected JChannel createJChannel(
072                            String properties, Receiver receiver, String clusterName)
073                    throws Exception {
074    
075                    JChannel jChannel = new JChannel(properties);
076    
077                    jChannel.setReceiver(receiver);
078    
079                    jChannel.connect(clusterName);
080    
081                    if (_log.isInfoEnabled()) {
082                            _log.info(
083                                    "Create a new channel with properties " +
084                                            jChannel.getProperties());
085                    }
086    
087                    return jChannel;
088            }
089    
090            protected List<Address> getAddresses(JChannel channel) {
091                    BaseReceiver baseReceiver = (BaseReceiver)channel.getReceiver();
092    
093                    View view = baseReceiver.getView();
094    
095                    List<org.jgroups.Address> jGroupsAddresses = view.getMembers();
096    
097                    if (jGroupsAddresses == null) {
098                            return Collections.emptyList();
099                    }
100    
101                    List<Address> addresses = new ArrayList<Address>(
102                            jGroupsAddresses.size());
103    
104                    for (org.jgroups.Address jgroupsAddress : jGroupsAddresses) {
105                            addresses.add(new AddressImpl(jgroupsAddress));
106                    }
107    
108                    return addresses;
109            }
110    
111            protected InetAddress getBindInetAddress(JChannel jChannel) {
112                    ProtocolStack protocolStack = jChannel.getProtocolStack();
113    
114                    Protocol protocol = protocolStack.getBottomProtocol();
115    
116                    return (InetAddress)protocol.getValue("bind_addr");
117            }
118    
119            protected void initBindAddress() throws Exception {
120                    String autodetectAddress = PropsValues.CLUSTER_LINK_AUTODETECT_ADDRESS;
121    
122                    if (Validator.isNull(autodetectAddress)) {
123                            return;
124                    }
125    
126                    String host = autodetectAddress;
127                    int port = 80;
128    
129                    int index = autodetectAddress.indexOf(CharPool.COLON);
130    
131                    if (index != -1) {
132                            host = autodetectAddress.substring(0, index);
133                            port = GetterUtil.getInteger(
134                                    autodetectAddress.substring(index + 1), port);
135                    }
136    
137                    if (_log.isInfoEnabled()) {
138                            _log.info(
139                                    "Autodetecting JGroups outgoing IP address and interface for " +
140                                            host + ":" + port);
141                    }
142    
143                    SocketUtil.BindInfo bindInfo = SocketUtil.getBindInfo(host, port);
144    
145                    InetAddress inetAddress = bindInfo.getInetAddress();
146    
147                    NetworkInterface networkInterface = bindInfo.getNetworkInterface();
148    
149                    System.setProperty("jgroups.bind_addr", inetAddress.getHostAddress());
150                    System.setProperty(
151                            "jgroups.bind_interface", networkInterface.getName());
152    
153                    if (_log.isInfoEnabled()) {
154                            _log.info(
155                                    "Setting JGroups outgoing IP address to " +
156                                            inetAddress.getHostAddress() + " and interface to " +
157                                                    networkInterface.getName());
158                    }
159            }
160    
161            protected void initSystemProperties() {
162                    for (String systemProperty :
163                                    PropsValues.CLUSTER_LINK_CHANNEL_SYSTEM_PROPERTIES) {
164    
165                            int index = systemProperty.indexOf(CharPool.COLON);
166    
167                            if (index == -1) {
168                                    continue;
169                            }
170    
171                            String key = systemProperty.substring(0, index);
172                            String value = systemProperty.substring(index + 1);
173    
174                            System.setProperty(key, value);
175    
176                            if (_log.isDebugEnabled()) {
177                                    _log.debug(
178                                            "Setting system property {key=" + key + ", value=" + value +
179                                                    "}");
180                            }
181                    }
182            }
183    
184            private static final Log _log = LogFactoryUtil.getLog(ClusterBase.class);
185    
186            private static boolean _initJGroupsProperties;
187    
188    }