001    /**
002     * Copyright (c) 2000-2013 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.InetAddressUtil;
023    import com.liferay.portal.kernel.util.SocketUtil;
024    import com.liferay.portal.kernel.util.Validator;
025    import com.liferay.portal.util.PropsValues;
026    
027    import java.net.InetAddress;
028    import java.net.NetworkInterface;
029    
030    import java.util.ArrayList;
031    import java.util.Collections;
032    import java.util.List;
033    
034    import org.jgroups.JChannel;
035    import org.jgroups.Receiver;
036    import org.jgroups.View;
037    
038    /**
039     * @author Shuyang Zhou
040     */
041    public abstract class ClusterBase {
042    
043            public void afterPropertiesSet() {
044                    if (!isEnabled()) {
045                            return;
046                    }
047    
048                    if (!_initialized) {
049                            initSystemProperties();
050    
051                            try {
052                                    initBindAddress();
053                            }
054                            catch (Exception e) {
055                                    if (_log.isWarnEnabled()) {
056                                            _log.warn("Failed to initialize outgoing IP address", e);
057                                    }
058                            }
059    
060                            _initialized = true;
061                    }
062    
063                    try {
064                            initChannels();
065                    }
066                    catch (Exception e) {
067                            if (_log.isErrorEnabled()) {
068                                    _log.error("Unable to initialize channels", e);
069                            }
070    
071                            throw new IllegalStateException(e);
072                    }
073            }
074    
075            public abstract void destroy();
076    
077            public boolean isEnabled() {
078                    return PropsValues.CLUSTER_LINK_ENABLED;
079            }
080    
081            protected JChannel createJChannel(
082                            String properties, Receiver receiver, String clusterName)
083                    throws Exception {
084    
085                    JChannel jChannel = new JChannel(properties);
086    
087                    jChannel.setReceiver(receiver);
088    
089                    jChannel.connect(clusterName);
090    
091                    if (_log.isInfoEnabled()) {
092                            _log.info(
093                                    "Create a new channel with properties " +
094                                            jChannel.getProperties());
095                    }
096    
097                    return jChannel;
098            }
099    
100            protected List<Address> getAddresses(JChannel channel) {
101                    BaseReceiver baseReceiver = (BaseReceiver)channel.getReceiver();
102    
103                    View view = baseReceiver.getView();
104    
105                    List<org.jgroups.Address> jGroupsAddresses = view.getMembers();
106    
107                    if (jGroupsAddresses == null) {
108                            return Collections.emptyList();
109                    }
110    
111                    List<Address> addresses = new ArrayList<Address>(
112                            jGroupsAddresses.size());
113    
114                    for (org.jgroups.Address jgroupsAddress : jGroupsAddresses) {
115                            addresses.add(new AddressImpl(jgroupsAddress));
116                    }
117    
118                    return addresses;
119            }
120    
121            protected void initBindAddress() throws Exception {
122                    String autodetectAddress = PropsValues.CLUSTER_LINK_AUTODETECT_ADDRESS;
123    
124                    if (Validator.isNull(autodetectAddress)) {
125                            bindInetAddress = InetAddressUtil.getLocalInetAddress();
126    
127                            return;
128                    }
129    
130                    String host = autodetectAddress;
131                    int port = 80;
132    
133                    int index = autodetectAddress.indexOf(CharPool.COLON);
134    
135                    if (index != -1) {
136                            host = autodetectAddress.substring(0, index);
137                            port = GetterUtil.getInteger(
138                                    autodetectAddress.substring(index + 1), port);
139                    }
140    
141                    if (_log.isInfoEnabled()) {
142                            _log.info(
143                                    "Autodetecting JGroups outgoing IP address and interface for " +
144                                            host + ":" + port);
145                    }
146    
147                    SocketUtil.BindInfo bindInfo = SocketUtil.getBindInfo(host, port);
148    
149                    bindInetAddress = bindInfo.getInetAddress();
150                    NetworkInterface networkInterface = bindInfo.getNetworkInterface();
151    
152                    System.setProperty(
153                            "jgroups.bind_addr", bindInetAddress.getHostAddress());
154                    System.setProperty(
155                            "jgroups.bind_interface", networkInterface.getName());
156    
157                    if (_log.isInfoEnabled()) {
158                            _log.info(
159                                    "Setting JGroups outgoing IP address to " +
160                                            bindInetAddress.getHostAddress() + " and interface to " +
161                                                    networkInterface.getName());
162                    }
163            }
164    
165            protected abstract void initChannels() throws Exception;
166    
167            protected void initSystemProperties() {
168                    for (String systemProperty :
169                                    PropsValues.CLUSTER_LINK_CHANNEL_SYSTEM_PROPERTIES) {
170    
171                            int index = systemProperty.indexOf(CharPool.COLON);
172    
173                            if (index == -1) {
174                                    continue;
175                            }
176    
177                            String key = systemProperty.substring(0, index);
178                            String value = systemProperty.substring(index + 1);
179    
180                            System.setProperty(key, value);
181    
182                            if (_log.isDebugEnabled()) {
183                                    _log.debug(
184                                            "Setting system property {key=" + key + ", value=" + value +
185                                                    "}");
186                            }
187                    }
188            }
189    
190            protected static InetAddress bindInetAddress;
191    
192            private static Log _log = LogFactoryUtil.getLog(ClusterBase.class);
193    
194            private static boolean _initialized;
195    
196    }