blob: 8f3e9a1af5bce68708007b5e51746bee1bb457a3 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.uuididentity;
import java.util.UUID;
import javax.inject.Inject;
import org.apache.cloudstack.api.Identity;
import org.apache.cloudstack.context.CallContext;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.utils.db.EntityManager;
import com.cloud.utils.db.UUIDManager;
import com.cloud.utils.exception.CloudRuntimeException;
public class UUIDManagerImpl implements UUIDManager {
@Inject
EntityManager _entityMgr;
@Inject
AccountManager _accountMgr;
//TODO - Make this configurable.
private static final int UUID_RETRY = 3;
@Override
public <T> void checkUuid(String uuid, Class<T> entityType) {
if (uuid == null) {
return;
}
Account caller = CallContext.current().getCallingAccount();
// Only admin and system allowed to do this
if (!(caller.getId() == Account.ACCOUNT_ID_SYSTEM || _accountMgr.isRootAdmin(caller.getId()))) {
throw new PermissionDeniedException("Please check your permissions, you are not allowed to create/update custom id");
}
checkUuidSimple(uuid, entityType);
}
@Override
public <T> void checkUuidSimple(String uuid, Class<T> entityType) {
if (uuid == null) {
return;
}
// check format
if (!IsUuidFormat(uuid)) {
throw new InvalidParameterValueException("UUID: " + uuid + " doesn't follow the UUID format");
}
// check unique
if (!IsUuidUnique(entityType, uuid)) {
throw new InvalidParameterValueException("UUID: " + uuid + " already exists so can't create/update with custom id");
}
}
public boolean IsUuidFormat(String uuid) {
// Match against UUID regex to check if input is uuid string
boolean isUuid = uuid.matches("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$");
return isUuid;
}
public <T> boolean IsUuidUnique(Class<T> entityType, String uuid) {
T obj = _entityMgr.findByUuid(entityType, uuid);
if (obj != null) {
return false;
} else {
return true;
}
}
@Override
public <T> String generateUuid(Class<T> entityType, String customId) {
if (customId == null) { // if no customid is passed then generate it.
int retry = UUID_RETRY;
while (retry-- != 0) { // there might be collision so retry
String uuid = UUID.randomUUID().toString();
if (IsUuidUnique(entityType, uuid)) {
return uuid;
}
}
throw new CloudRuntimeException("Unable to generate a unique uuid, please try again");
} else {
checkUuid(customId, entityType);
return customId;
}
}
@Override
public <T> String getUuid(Class<T> entityType, Long customId) {
if (customId == null) {
return null;
}
Identity identity = (Identity) this._entityMgr.findById(entityType, customId);
if (identity == null) {
throw new InvalidParameterValueException("Unable to find UUID for id " + customId);
}
return identity.getUuid();
}
}