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.kernel.model;
016    
017    import com.liferay.portal.kernel.util.CharPool;
018    import com.liferay.portal.kernel.util.GetterUtil;
019    import com.liferay.portal.kernel.util.StringBundler;
020    import com.liferay.portal.kernel.util.StringPool;
021    import com.liferay.portal.kernel.util.StringUtil;
022    import com.liferay.portal.kernel.util.Validator;
023    
024    import java.security.InvalidParameterException;
025    
026    /**
027     * @author Brian Wing Shun Chan
028     * @author Jorge Ferrer
029     */
030    public class PortletInstance {
031    
032            public static final int PORTLET_INSTANCE_KEY_MAX_LENGTH =
033                    255 - PortletInstance._INSTANCE_SEPARATOR.length() +
034                            PortletInstance._USER_SEPARATOR.length() + 39;
035    
036            public static PortletInstance fromPortletInstanceKey(
037                    String portletInstanceKey) {
038    
039                    return new PortletInstance(
040                            _getPortletName(portletInstanceKey), _getUserId(portletInstanceKey),
041                            _getInstanceId(portletInstanceKey));
042            }
043    
044            public static PortletInstance fromPortletNameAndUserIdAndInstanceId(
045                    String portletName, String userIdAndInstanceId) {
046    
047                    UserIdAndInstanceIdEncoder userIdAndInstanceIdEncoder =
048                            _buildUserIdAndInstanceIdEncoder(userIdAndInstanceId);
049    
050                    return new PortletInstance(
051                            portletName, userIdAndInstanceIdEncoder.getUserId(),
052                            userIdAndInstanceIdEncoder.getInstanceId());
053            }
054    
055            public PortletInstance(String portletName) {
056                    this(portletName, StringUtil.randomString(12));
057            }
058    
059            public PortletInstance(String portletName, long userId) {
060                    this(portletName, userId, null);
061            }
062    
063            public PortletInstance(String portletName, long userId, String instanceId) {
064                    validatePortletName(portletName);
065    
066                    _portletName = portletName;
067                    _userId = userId;
068                    _instanceId = instanceId;
069            }
070    
071            public PortletInstance(String portletName, String instanceId) {
072                    this(portletName, 0, instanceId);
073            }
074    
075            public String getInstanceId() {
076                    return _instanceId;
077            }
078    
079            public String getPortletInstanceKey() {
080                    StringBundler sb = new StringBundler(5);
081    
082                    sb.append(_portletName);
083    
084                    if (_userId > 0) {
085                            sb.append(_USER_SEPARATOR);
086                            sb.append(_userId);
087                    }
088    
089                    if (Validator.isNotNull(_instanceId)) {
090                            sb.append(_INSTANCE_SEPARATOR);
091                            sb.append(_instanceId);
092                    }
093    
094                    return sb.toString();
095            }
096    
097            public String getPortletName() {
098                    return _portletName;
099            }
100    
101            public long getUserId() {
102                    return _userId;
103            }
104    
105            public String getUserIdAndInstanceId() {
106                    UserIdAndInstanceIdEncoder userIdAndInstanceIdEncoder =
107                            new UserIdAndInstanceIdEncoder(_userId, _instanceId);
108    
109                    return userIdAndInstanceIdEncoder.encode();
110            }
111    
112            public boolean hasIdenticalPortletName(PortletInstance portletInstance) {
113                    return hasIdenticalPortletName(portletInstance.getPortletName());
114            }
115    
116            public boolean hasIdenticalPortletName(String portletName) {
117                    return _portletName.equals(portletName);
118            }
119    
120            public boolean hasInstanceId() {
121                    return Validator.isNotNull(_instanceId);
122            }
123    
124            public boolean hasUserId() {
125                    if (_userId > 0) {
126                            return true;
127                    }
128    
129                    return false;
130            }
131    
132            @Override
133            public String toString() {
134                    return getPortletInstanceKey();
135            }
136    
137            private static UserIdAndInstanceIdEncoder _buildUserIdAndInstanceIdEncoder(
138                    String userIdAndInstanceId) {
139    
140                    if (userIdAndInstanceId == null) {
141                            throw new InvalidParameterException(
142                                    "User ID and instance ID are null");
143                    }
144    
145                    if (userIdAndInstanceId.isEmpty()) {
146                            return new UserIdAndInstanceIdEncoder(0, null);
147                    }
148    
149                    int slashCount = StringUtil.count(
150                            userIdAndInstanceId, StringPool.SLASH);
151    
152                    if (slashCount > 0) {
153                            throw new InvalidParameterException(
154                                    "User ID and instance ID contain slashes");
155                    }
156    
157                    int underlineCount = StringUtil.count(
158                            userIdAndInstanceId, StringPool.UNDERLINE);
159    
160                    if (underlineCount > 1) {
161                            throw new InvalidParameterException(
162                                    "User ID and instance ID has more than one underscore");
163                    }
164    
165                    if (underlineCount == 1) {
166                            int index = userIdAndInstanceId.indexOf(CharPool.UNDERLINE);
167    
168                            long userId = GetterUtil.getLong(
169                                    userIdAndInstanceId.substring(0, index), -1);
170    
171                            if (userId == -1) {
172                                    throw new InvalidParameterException("User ID is not a number");
173                            }
174    
175                            String instanceId = null;
176    
177                            if (index < (userIdAndInstanceId.length() - 1)) {
178                                    instanceId = userIdAndInstanceId.substring(index + 1);
179                            }
180    
181                            return new UserIdAndInstanceIdEncoder(userId, instanceId);
182                    }
183    
184                    return new UserIdAndInstanceIdEncoder(0, userIdAndInstanceId);
185            }
186    
187            private static String _getInstanceId(String portletInstanceKey) {
188                    int index = portletInstanceKey.indexOf(_INSTANCE_SEPARATOR);
189    
190                    if (index == -1) {
191                            return null;
192                    }
193    
194                    return portletInstanceKey.substring(
195                            index + _INSTANCE_SEPARATOR.length());
196            }
197    
198            private static String _getPortletName(String portletInstanceKey) {
199                    int x = portletInstanceKey.indexOf(_USER_SEPARATOR);
200                    int y = portletInstanceKey.indexOf(_INSTANCE_SEPARATOR);
201    
202                    if ((x == -1) && (y == -1)) {
203                            return portletInstanceKey;
204                    }
205                    else if (x != -1) {
206                            return portletInstanceKey.substring(0, x);
207                    }
208    
209                    return portletInstanceKey.substring(0, y);
210            }
211    
212            private static long _getUserId(String portletInstanceKey) {
213                    int x = portletInstanceKey.indexOf(_USER_SEPARATOR);
214                    int y = portletInstanceKey.indexOf(_INSTANCE_SEPARATOR);
215    
216                    if (x == -1) {
217                            return 0;
218                    }
219    
220                    if (y != -1) {
221                            return GetterUtil.getLong(
222                                    portletInstanceKey.substring(x + _USER_SEPARATOR.length(), y));
223                    }
224    
225                    return GetterUtil.getLong(
226                            portletInstanceKey.substring(x + _USER_SEPARATOR.length()));
227            }
228    
229            private void validatePortletName(String portletName) {
230                    for (String keyword : _PORTLET_NAME_KEYWORDS) {
231                            if (!portletName.contains(keyword)) {
232                                    continue;
233                            }
234    
235                            throw new InvalidParameterException(
236                                    "The portletName '" + portletName +
237                                            "' must not contain the keyword " + keyword);
238                    }
239            }
240    
241            private static final String _INSTANCE_SEPARATOR = "_INSTANCE_";
242    
243            private static final String _USER_SEPARATOR = "_USER_";
244    
245            private final String[] _PORTLET_NAME_KEYWORDS =
246                    {_INSTANCE_SEPARATOR, _USER_SEPARATOR};
247    
248            private final String _instanceId;
249            private final String _portletName;
250            private final long _userId;
251    
252            private static final class UserIdAndInstanceIdEncoder {
253    
254                    public UserIdAndInstanceIdEncoder(long userId, String instanceId) {
255                            _userId = userId;
256                            _instanceId = instanceId;
257                    }
258    
259                    public String encode() {
260                            if ((_userId <= 0) && Validator.isBlank(_instanceId)) {
261                                    return null;
262                            }
263    
264                            StringBundler sb = new StringBundler(3);
265    
266                            if (_userId > 0) {
267                                    sb.append(_userId);
268                                    sb.append(StringPool.UNDERLINE);
269                            }
270    
271                            if (_instanceId != null) {
272                                    sb.append(_instanceId);
273                            }
274    
275                            return sb.toString();
276                    }
277    
278                    public String getInstanceId() {
279                            return _instanceId;
280                    }
281    
282                    public long getUserId() {
283                            return _userId;
284                    }
285    
286                    @Override
287                    public String toString() {
288                            return encode();
289                    }
290    
291                    private String _instanceId;
292                    private long _userId;
293    
294            }
295    
296    }