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.license.util;
016    
017    import com.liferay.portal.kernel.cluster.ClusterExecutorUtil;
018    import com.liferay.portal.kernel.cluster.ClusterNode;
019    import com.liferay.portal.kernel.cluster.ClusterNodeResponse;
020    import com.liferay.portal.kernel.cluster.ClusterNodeResponses;
021    import com.liferay.portal.kernel.cluster.ClusterRequest;
022    import com.liferay.portal.kernel.cluster.FutureClusterResponses;
023    import com.liferay.portal.kernel.json.JSONFactoryUtil;
024    import com.liferay.portal.kernel.json.JSONObject;
025    import com.liferay.portal.kernel.log.Log;
026    import com.liferay.portal.kernel.log.LogFactoryUtil;
027    import com.liferay.portal.kernel.util.Base64;
028    import com.liferay.portal.kernel.util.CharPool;
029    import com.liferay.portal.kernel.util.FileUtil;
030    import com.liferay.portal.kernel.util.GetterUtil;
031    import com.liferay.portal.kernel.util.Http;
032    import com.liferay.portal.kernel.util.MethodHandler;
033    import com.liferay.portal.kernel.util.MethodKey;
034    import com.liferay.portal.kernel.util.ParamUtil;
035    import com.liferay.portal.kernel.util.ReleaseInfo;
036    import com.liferay.portal.kernel.util.StringPool;
037    import com.liferay.portal.kernel.util.StringUtil;
038    import com.liferay.portal.kernel.util.Validator;
039    import com.liferay.portal.util.ClassLoaderUtil;
040    import com.liferay.portal.util.PropsUtil;
041    import com.liferay.portal.util.PropsValues;
042    import com.liferay.util.Encryptor;
043    
044    import java.io.BufferedReader;
045    import java.io.File;
046    import java.io.InputStream;
047    import java.io.InputStreamReader;
048    import java.io.OutputStream;
049    
050    import java.net.Inet4Address;
051    import java.net.InetAddress;
052    import java.net.InetSocketAddress;
053    import java.net.NetworkInterface;
054    import java.net.Proxy;
055    import java.net.URL;
056    import java.net.URLConnection;
057    
058    import java.security.Key;
059    import java.security.KeyFactory;
060    import java.security.PublicKey;
061    import java.security.SecureRandom;
062    import java.security.spec.X509EncodedKeySpec;
063    
064    import java.util.Arrays;
065    import java.util.Collections;
066    import java.util.HashMap;
067    import java.util.HashSet;
068    import java.util.Iterator;
069    import java.util.List;
070    import java.util.Map;
071    import java.util.Set;
072    import java.util.TreeMap;
073    import java.util.concurrent.TimeUnit;
074    import java.util.regex.Matcher;
075    import java.util.regex.Pattern;
076    
077    import javax.crypto.KeyGenerator;
078    
079    import javax.servlet.http.HttpServletRequest;
080    
081    import org.apache.commons.io.IOUtils;
082    
083    /**
084     * @author Amos Fong
085     */
086    public class LicenseUtil {
087    
088            public static final String LICENSE_REPOSITORY_DIR =
089                    PropsValues.LIFERAY_HOME.concat("/data/license");
090    
091            public static final String LICENSE_SERVER_URL = GetterUtil.get(
092                    PropsUtil.get("license.server.url"), "https://www.liferay.com");
093    
094            public static Map<String, String> getClusterServerInfo(String clusterNodeId)
095                    throws Exception {
096    
097                    List<ClusterNode> clusterNodes = ClusterExecutorUtil.getClusterNodes();
098    
099                    ClusterNode clusterNode = null;
100    
101                    for (ClusterNode curClusterNode : clusterNodes) {
102                            String curClusterNodeId = curClusterNode.getClusterNodeId();
103    
104                            if (curClusterNodeId.equals(clusterNodeId)) {
105                                    clusterNode = curClusterNode;
106    
107                                    break;
108                            }
109                    }
110    
111                    if (clusterNode == null) {
112                            return null;
113                    }
114    
115                    try {
116                            if (clusterNode.equals(ClusterExecutorUtil.getLocalClusterNode())) {
117                                    return getServerInfo();
118                            }
119    
120                            ClusterRequest clusterRequest = ClusterRequest.createUnicastRequest(
121                                    _getServerInfoMethodHandler, clusterNodeId);
122    
123                            FutureClusterResponses futureClusterResponses =
124                                    ClusterExecutorUtil.execute(clusterRequest);
125    
126                            ClusterNodeResponses clusterNodeResponses =
127                                    futureClusterResponses.get(20000, TimeUnit.MILLISECONDS);
128    
129                            ClusterNodeResponse clusterNodeResponse =
130                                    clusterNodeResponses.getClusterResponse(clusterNode);
131    
132                            return (Map<String, String>)clusterNodeResponse.getResult();
133                    }
134                    catch (Exception e) {
135                            _log.error(e, e);
136    
137                            throw e;
138                    }
139            }
140    
141            public static String getHostName() {
142                    if (_hostName != null) {
143                            return _hostName;
144                    }
145    
146                    _hostName = StringPool.BLANK;
147    
148                    try {
149                            Runtime runtime = Runtime.getRuntime();
150    
151                            Process process = runtime.exec("hostname");
152    
153                            BufferedReader bufferedReader = new BufferedReader(
154                                    new InputStreamReader(process.getInputStream()), 128);
155    
156                            _hostName = bufferedReader.readLine();
157    
158                            bufferedReader.close();
159                    }
160                    catch (Exception e) {
161                            _log.error("Unable to read local server's host name");
162    
163                            _log.error(e, e);
164                    }
165    
166                    return _hostName;
167            }
168    
169            public static Set<String> getIpAddresses() {
170                    if (_ipAddresses != null) {
171                            return new HashSet<String>(_ipAddresses);
172                    }
173    
174                    _ipAddresses = new HashSet<String>();
175    
176                    try {
177                            List<NetworkInterface> networkInterfaces = Collections.list(
178                                    NetworkInterface.getNetworkInterfaces());
179    
180                            for (NetworkInterface networkInterface : networkInterfaces) {
181                                    List<InetAddress> inetAddresses = Collections.list(
182                                            networkInterface.getInetAddresses());
183    
184                                    for (InetAddress inetAddress : inetAddresses) {
185                                            if (inetAddress.isLinkLocalAddress() ||
186                                                    inetAddress.isLoopbackAddress() ||
187                                                    !(inetAddress instanceof Inet4Address)) {
188    
189                                                    continue;
190                                            }
191    
192                                            _ipAddresses.add(inetAddress.getHostAddress());
193                                    }
194                            }
195                    }
196                    catch (Exception e) {
197                            _log.error("Unable to read local server's IP addresses");
198    
199                            _log.error(e, e);
200                    }
201    
202                    return new HashSet<String>(_ipAddresses);
203            }
204    
205            public static Set<String> getMacAddresses() {
206                    if (_macAddresses != null) {
207                            return new HashSet<String>(_macAddresses);
208                    }
209    
210                    Set<String> macAddresses = new HashSet<String>();
211    
212                    String osName = System.getProperty("os.name");
213    
214                    String executable = null;
215                    String arguments = null;
216    
217                    if (StringUtil.startsWith(osName, "win")) {
218                            executable = "ipconfig";
219                            arguments = "/all";
220                    }
221                    else {
222                            if (StringUtil.startsWith(osName, "aix")) {
223                                    executable = "netstat";
224                                    arguments = "-ina";
225                            }
226                            else {
227                                    executable = "ifconfig";
228                                    arguments = "-a";
229                            }
230    
231                            File sbinDir = new File("/sbin", executable);
232    
233                            if (sbinDir.exists()) {
234                                    executable = "/sbin/".concat(executable);
235                            }
236                    }
237    
238                    try {
239                            Runtime runtime = Runtime.getRuntime();
240    
241                            Process process = runtime.exec(
242                                    new String[] {executable, arguments});
243    
244                            macAddresses = getMacAddresses(osName, process.getInputStream());
245                    }
246                    catch (Exception e) {
247                            _log.error(e, e);
248                    }
249    
250                    _macAddresses = macAddresses;
251    
252                    return new HashSet<String>(macAddresses);
253            }
254    
255            public static Set<String> getMacAddresses(
256                            String osName, InputStream processInputStream)
257                    throws Exception {
258    
259                    Set<String> macAddresses = new HashSet<String>();
260    
261                    Pattern macAddressPattern = _macAddressPattern1;
262    
263                    if (StringUtil.startsWith(osName, "aix")) {
264                            macAddressPattern = _macAddressPattern2;
265                    }
266    
267                    String processOutput = StringUtil.read(processInputStream);
268    
269                    String[] lines = StringUtil.split(processOutput, CharPool.NEW_LINE);
270    
271                    for (String line : lines) {
272                            Matcher matcher = macAddressPattern.matcher(line);
273    
274                            if (!matcher.find()) {
275                                    continue;
276                            }
277    
278                            String macAddress = matcher.group(1);
279    
280                            macAddress = macAddress.toLowerCase();
281                            macAddress = macAddress.replace(CharPool.DASH, CharPool.COLON);
282                            macAddress = macAddress.replace(CharPool.PERIOD, CharPool.COLON);
283    
284                            StringBuilder sb = new StringBuilder(17);
285    
286                            sb.append(macAddress);
287    
288                            for (int i = 1; i < 5; ++i) {
289                                    int pos = (i * 3) - 1;
290    
291                                    if (sb.charAt(pos) != CharPool.COLON) {
292                                            sb.insert((i - 1) * 3, CharPool.NUMBER_0);
293                                    }
294                            }
295    
296                            if (sb.length() < 17) {
297                                    sb.insert(15, CharPool.NUMBER_0);
298                            }
299    
300                            macAddress = sb.toString();
301    
302                            macAddresses.add(macAddress);
303                    }
304    
305                    return macAddresses;
306            }
307    
308            public static byte[] getServerIdBytes() throws Exception {
309                    if (_serverIdBytes != null) {
310                            return _serverIdBytes;
311                    }
312    
313                    File serverIdFile = new File(
314                            LICENSE_REPOSITORY_DIR + "/server/serverId");
315    
316                    if (!serverIdFile.exists()) {
317                            return new byte[0];
318                    }
319    
320                    _serverIdBytes = FileUtil.getBytes(serverIdFile);
321    
322                    return _serverIdBytes;
323            }
324    
325            public static Map<String, String> getServerInfo() {
326                    Map<String, String> serverInfo = new HashMap<String, String>();
327    
328                    serverInfo.put("hostName", getHostName());
329                    serverInfo.put("ipAddresses", StringUtil.merge(getIpAddresses()));
330                    serverInfo.put("macAddresses", StringUtil.merge(getMacAddresses()));
331    
332                    return serverInfo;
333            }
334    
335            public static void registerOrder(HttpServletRequest request) {
336                    String orderUuid = ParamUtil.getString(request, "orderUuid");
337                    String productEntryName = ParamUtil.getString(
338                            request, "productEntryName");
339                    int maxServers = ParamUtil.getInteger(request, "maxServers");
340    
341                    List<ClusterNode> clusterNodes = ClusterExecutorUtil.getClusterNodes();
342    
343                    if ((clusterNodes.size() <= 1) || Validator.isNull(productEntryName) ||
344                            Validator.isNull(orderUuid)) {
345    
346                            Map<String, Object> attributes = registerOrder(
347                                    orderUuid, productEntryName, maxServers);
348    
349                            for (Map.Entry<String, Object> entry : attributes.entrySet()) {
350                                    request.setAttribute(entry.getKey(), entry.getValue());
351                            }
352                    }
353                    else {
354                            for (ClusterNode clusterNode : clusterNodes) {
355                                    boolean register = ParamUtil.getBoolean(
356                                            request, clusterNode.getClusterNodeId() + "_register");
357    
358                                    if (!register) {
359                                            continue;
360                                    }
361    
362                                    try {
363                                            _registerClusterOrder(
364                                                    request, clusterNode, orderUuid, productEntryName,
365                                                    maxServers);
366                                    }
367                                    catch (Exception e) {
368                                            _log.error(e, e);
369    
370                                            InetAddress inetAddress = clusterNode.getInetAddress();
371    
372                                            String message =
373                                                    "Error contacting " + inetAddress.getHostName();
374    
375                                            if (clusterNode.getPort() != -1) {
376                                                    message += StringPool.COLON + clusterNode.getPort();
377                                            }
378    
379                                            request.setAttribute(
380                                                    clusterNode.getClusterNodeId() + "_ERROR_MESSAGE",
381                                                    message);
382                                    }
383                            }
384                    }
385            }
386    
387            public static Map<String, Object> registerOrder(
388                    String orderUuid, String productEntryName, int maxServers) {
389    
390                    Map<String, Object> attributes = new HashMap<String, Object>();
391    
392                    if (Validator.isNull(orderUuid)) {
393                            return attributes;
394                    }
395    
396                    try {
397                            JSONObject jsonObject = _createRequest(
398                                    orderUuid, productEntryName, maxServers);
399    
400                            String response = sendRequest(jsonObject.toString());
401    
402                            JSONObject responseJSONObject = JSONFactoryUtil.createJSONObject(
403                                    response);
404    
405                            attributes.put(
406                                    "ORDER_PRODUCT_ID", responseJSONObject.getString("productId"));
407                            attributes.put(
408                                    "ORDER_PRODUCTS", _getOrderProducts(responseJSONObject));
409    
410                            String errorMessage = responseJSONObject.getString("errorMessage");
411    
412                            if (Validator.isNotNull(errorMessage)) {
413                                    attributes.put("ERROR_MESSAGE", errorMessage);
414    
415                                    return attributes;
416                            }
417    
418                            String licenseXML = responseJSONObject.getString("licenseXML");
419    
420                            if (Validator.isNotNull(licenseXML)) {
421                                    LicenseManagerUtil.registerLicense(responseJSONObject);
422    
423                                    attributes.clear();
424                                    attributes.put(
425                                            "SUCCESS_MESSAGE",
426                                            "Your license has been successfully registered.");
427                            }
428                    }
429                    catch (Exception e) {
430                            _log.error(e, e);
431    
432                            attributes.put(
433                                    "ERROR_MESSAGE",
434                                    "There was an error contacting " + LICENSE_SERVER_URL);
435                    }
436    
437                    return attributes;
438            }
439    
440            public static String sendRequest(String request) throws Exception {
441                    InputStream inputStream = null;
442                    OutputStream outputStream = null;
443    
444                    try {
445                            String serverURL = LICENSE_SERVER_URL;
446    
447                            if (!serverURL.endsWith(StringPool.SLASH)) {
448                                    serverURL += StringPool.SLASH;
449                            }
450    
451                            serverURL += "osb-portlet/license";
452    
453                            URL url = new URL(serverURL);
454    
455                            URLConnection connection = null;
456    
457                            if (Validator.isNotNull(_PROXY_URL)) {
458                                    if (_log.isInfoEnabled()) {
459                                            _log.info(
460                                                    "Using proxy " + _PROXY_URL + StringPool.COLON +
461                                                            _PROXY_PORT);
462                                    }
463    
464                                    Proxy proxy = new Proxy(
465                                            Proxy.Type.HTTP,
466                                            new InetSocketAddress(_PROXY_URL, _PROXY_PORT));
467    
468                                    connection = url.openConnection(proxy);
469    
470                                    if (Validator.isNotNull(_PROXY_USER_NAME)) {
471                                            String login =
472                                                    _PROXY_USER_NAME + StringPool.COLON + _PROXY_PASSWORD;
473    
474                                            String encodedLogin = Base64.encode(login.getBytes());
475    
476                                            connection.setRequestProperty(
477                                                    "Proxy-Authorization", "Basic " + encodedLogin);
478                                    }
479                            }
480                            else {
481                                    connection = url.openConnection();
482                            }
483    
484                            connection.setDoOutput(true);
485    
486                            outputStream = connection.getOutputStream();
487    
488                            outputStream.write(_encryptRequest(serverURL, request));
489    
490                            String response = _decryptResponse(
491                                    serverURL, connection.getInputStream());
492    
493                            if (_log.isDebugEnabled()) {
494                                    _log.debug("Server response: " + response);
495                            }
496    
497                            if (Validator.isNull(response)) {
498                                    throw new Exception("Server response is null");
499                            }
500    
501                            return response;
502                    }
503                    finally {
504                            try {
505                                    if (inputStream != null) {
506                                            inputStream.close();
507                                    }
508                            }
509                            catch (Exception e) {
510                            }
511    
512                            try {
513                                    if (outputStream != null) {
514                                            outputStream.close();
515                                    }
516                            }
517                            catch (Exception e) {
518                            }
519                    }
520            }
521    
522            public static void writeServerProperties(byte[] serverIdBytes)
523                    throws Exception {
524    
525                    File serverIdFile = new File(
526                            LICENSE_REPOSITORY_DIR + "/server/serverId");
527    
528                    FileUtil.write(serverIdFile, serverIdBytes);
529            }
530    
531            private static JSONObject _createRequest(
532                            String orderUuid, String productEntryName, int maxServers)
533                    throws Exception {
534    
535                    JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
536    
537                    jsonObject.put("version", 2);
538                    jsonObject.put("orderUuid", orderUuid);
539                    jsonObject.put("liferayVersion", ReleaseInfo.getBuildNumber());
540    
541                    if (Validator.isNull(productEntryName)) {
542                            jsonObject.put("cmd", "QUERY");
543                    }
544                    else {
545                            jsonObject.put("cmd", "REGISTER");
546    
547                            if (productEntryName.startsWith("basic")) {
548                                    jsonObject.put("productEntryName", "basic");
549    
550                                    if (productEntryName.equals("basic-cluster")) {
551                                            jsonObject.put("cluster", true);
552                                            jsonObject.put("maxServers", maxServers);
553                                    }
554                                    else if (productEntryName.startsWith("basic-")) {
555                                            String[] productNameArray = StringUtil.split(
556                                                    productEntryName, StringPool.DASH);
557    
558                                            if (productNameArray.length >= 3) {
559                                                    jsonObject.put("offeringEntryId", productNameArray[1]);
560                                                    jsonObject.put("clusterId", productNameArray[2]);
561                                            }
562                                    }
563                            }
564                            else {
565                                    jsonObject.put("productEntryName", productEntryName);
566                            }
567    
568                            jsonObject.put("hostName", getHostName());
569                            jsonObject.put("ipAddresses", StringUtil.merge(getIpAddresses()));
570                            jsonObject.put("macAddresses", StringUtil.merge(getMacAddresses()));
571                            jsonObject.put("serverId", Arrays.toString(getServerIdBytes()));
572                    }
573    
574                    return jsonObject;
575            }
576    
577            private static String _decryptResponse(
578                            String serverURL, InputStream inputStream)
579                    throws Exception {
580    
581                    if (serverURL.startsWith(Http.HTTPS)) {
582                            return StringUtil.read(inputStream);
583                    }
584                    else {
585                            byte[] bytes = IOUtils.toByteArray(inputStream);
586    
587                            if ((bytes == null) || (bytes.length <= 0)) {
588                                    return null;
589                            }
590    
591                            bytes = Encryptor.decryptUnencodedAsBytes(_symmetricKey, bytes);
592    
593                            return new String(bytes, StringPool.UTF8);
594                    }
595            }
596    
597            private static byte[] _encryptRequest(String serverURL, String request)
598                    throws Exception {
599    
600                    byte[] bytes = request.getBytes(StringPool.UTF8);
601    
602                    if (serverURL.startsWith(Http.HTTPS)) {
603                            return bytes;
604                    }
605                    else {
606                            JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
607    
608                            bytes = Encryptor.encryptUnencoded(_symmetricKey, bytes);
609    
610                            jsonObject.put("content", Base64.objectToString(bytes));
611                            jsonObject.put("key", _encryptedSymmetricKey);
612    
613                            return jsonObject.toString().getBytes(StringPool.UTF8);
614                    }
615            }
616    
617            private static Map<String, String> _getOrderProducts(
618                    JSONObject jsonObject) {
619    
620                    JSONObject productsJSONObject = jsonObject.getJSONObject(
621                            "productsJSONObject");
622    
623                    if (productsJSONObject == null) {
624                            return null;
625                    }
626    
627                    Map<String, String> sortedMap = new TreeMap<String, String>(
628                            String.CASE_INSENSITIVE_ORDER);
629    
630                    Iterator<String> itr = productsJSONObject.keys();
631    
632                    while (itr.hasNext()) {
633                            String key = itr.next();
634    
635                            sortedMap.put(key, productsJSONObject.getString(key));
636                    }
637    
638                    return sortedMap;
639            }
640    
641            private static void _initKeys() {
642                    ClassLoader classLoader = ClassLoaderUtil.getPortalClassLoader();
643    
644                    if ((classLoader == null) || (_encryptedSymmetricKey != null)) {
645                            return;
646                    }
647    
648                    try {
649                            URL url = classLoader.getResource(
650                                    "com/liferay/portal/license/public.key");
651    
652                            byte[] bytes = IOUtils.toByteArray(url.openStream());
653    
654                            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(
655                                    bytes);
656    
657                            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
658    
659                            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
660    
661                            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
662    
663                            keyGenerator.init(128, new SecureRandom());
664    
665                            _symmetricKey = keyGenerator.generateKey();
666    
667                            byte[] encryptedSymmetricKey = Encryptor.encryptUnencoded(
668                                    publicKey, _symmetricKey.getEncoded());
669    
670                            _encryptedSymmetricKey = Base64.objectToString(
671                                    encryptedSymmetricKey);
672                    }
673                    catch (Exception e) {
674                            _log.error(e, e);
675                    }
676            }
677    
678            private static void _registerClusterOrder(
679                            HttpServletRequest request, ClusterNode clusterNode,
680                            String orderUuid, String productEntryName, int maxServers)
681                    throws Exception {
682    
683                    MethodHandler methodHandler = new MethodHandler(
684                            _registerOrderMethodKey, orderUuid, productEntryName, maxServers);
685    
686                    ClusterRequest clusterRequest = ClusterRequest.createUnicastRequest(
687                            methodHandler, clusterNode.getClusterNodeId());
688    
689                    FutureClusterResponses futureClusterResponses =
690                            ClusterExecutorUtil.execute(clusterRequest);
691    
692                    ClusterNodeResponses clusterNodeResponses = futureClusterResponses.get(
693                            20000, TimeUnit.MILLISECONDS);
694    
695                    ClusterNodeResponse clusterNodeResponse =
696                            clusterNodeResponses.getClusterResponse(clusterNode);
697    
698                    Map<String, Object> attributes =
699                            (Map<String, Object>)clusterNodeResponse.getResult();
700    
701                    for (Map.Entry<String, Object> entry : attributes.entrySet()) {
702                            request.setAttribute(
703                                    clusterNode.getClusterNodeId() + StringPool.UNDERLINE +
704                                            entry.getKey(),
705                                    entry.getValue());
706                    }
707            }
708    
709            private static final String _PROXY_PASSWORD = GetterUtil.getString(
710                    PropsUtil.get("license.proxy.password"));
711    
712            private static final int _PROXY_PORT = GetterUtil.getInteger(
713                    PropsUtil.get("license.proxy.port"), 80);
714    
715            private static final String _PROXY_URL = PropsUtil.get("license.proxy.url");
716    
717            private static final String _PROXY_USER_NAME = GetterUtil.getString(
718                    PropsUtil.get("license.proxy.username"));
719    
720            private static Log _log = LogFactoryUtil.getLog(LicenseUtil.class);
721    
722            private static String _encryptedSymmetricKey;
723            private static MethodHandler _getServerInfoMethodHandler =
724                    new MethodHandler(
725                            new MethodKey(LicenseUtil.class.getName(), "getServerInfo"));
726            private static String _hostName;
727            private static Set<String> _ipAddresses;
728            private static Set<String> _macAddresses;
729            private static Pattern _macAddressPattern1 = Pattern.compile(
730                    "\\s((\\p{XDigit}{2}(-|:)){5}(\\p{XDigit}{2}))(?:\\s|$)");
731            private static Pattern _macAddressPattern2 = Pattern.compile(
732                    "\\s((\\p{XDigit}{1,2}(\\.)){5}(\\p{XDigit}{1,2}))(?:\\s|$)");
733            private static MethodKey _registerOrderMethodKey = new MethodKey(
734                    LicenseUtil.class.getName(), "registerOrder", String.class,
735                    String.class, int.class);
736            private static byte[] _serverIdBytes;
737            private static Key _symmetricKey;
738    
739            static {
740                    _initKeys();
741            }
742    
743    }