/*
* Copyright 2001-2006 The Apache Software Foundation.
*
* Licensed 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.
*/
/*
* Copyright 2008-2009 MOPAS(Ministry of Public Administration and Security).
*
* Licensed 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 egovframework.rte.fdl.idgnr.impl;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.StringTokenizer;
import egovframework.rte.fdl.cmmn.exception.FdlException;
import egovframework.rte.fdl.idgnr.EgovIdGnrService;
import egovframework.rte.fdl.idgnr.EgovIdGnrStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.MessageSource;
/**
* ID Generation 서비스를 위한 UUID 구현 클래스
*
* <p><b>NOTE</b>: UUID(Universally Unique Identifier)
* 알고리즘 기반의 유일키를 제공 받을 수 있다.</p>
*
* @author 실행환경 개발팀 김태호
* @since 2009.02.01
* @version 1.0
* @deprecated Use the EgovUUIdGnrServiceImpl class.
* @see <pre>
* == 개정이력(Modification Information) ==
*
* 수정일 수정자 수정내용
* ------- -------- ---------------------------
* 2009.02.01 김태호 최초 생성
*
* </pre>
*/
@Deprecated
public class EgovUUIdGnrService implements EgovIdGnrService, ApplicationContextAware {
/**
* Message Source
*/
private MessageSource messageSource;
/**
* Message Source Injection
*/
public void setApplicationContext(ApplicationContext applicationContext) {
this.messageSource =
(MessageSource) applicationContext.getBean("messageSource");
}
/**
* Class 사용 로거 지정
*/
private static final Logger LOGGER = LoggerFactory.getLogger(EgovUUIdGnrService.class);
private static final String ERROR_STRING = "address in the configuration should be a valid IP or MAC Address";
/**
* Address Id
*/
private String mAddressId;
/**
* UUID 생성에 필요한 Time Factor에 의한 ID
*/
private String mTimeId;
// 사용자 지정 Address
// - PMD error report: Avoid unused private fields
// such as 'address'
// private String address;
/**
* Loop Counter
*/
private short mLoopCounter = 0;
/**
* BigDecimal 타입을 아이디 제공
*
* @return BigDecimal 타입 ID
* @throws FdlException 아이디 생성에 실패한 경우
*/
public BigDecimal getNextBigDecimalId() throws FdlException {
String newId = getNextStringId();
byte[] bytes = newId.getBytes(); // get 16 bytes
BigDecimal bd = new BigDecimal(0);
// CHECKSTYLE:OFF
for (int i = 0; i < bytes.length; i++) {
bd = bd.multiply(new BigDecimal(256));
bd = bd.add(new BigDecimal(((int) bytes[i]) & 0xFF));
}
// CHECKSTYLE:ON
return bd;
}
/**
* byte 타입을 아이디 제공
*
* @return byte 타입 ID
* @throws FdlException 아이디 생성에 실패한 경우
*/
public byte getNextByteId() throws FdlException {
throw new FdlException(messageSource, "error.idgnr.not.supported",
new String[] {"Byte" }, null);
}
/**
* int 타입을 아이디 제공을 요청하면 불가능한 요청이라는 Exception 발생
*
* @return int 타입 ID
* @throws FdlException 아이디 생성에 실패한 경우
*/
public int getNextIntegerId() throws FdlException {
throw new FdlException(messageSource, "error.idgnr.not.supported",
new String[] {"Integer" }, null);
}
/**
* long 타입을 아이디 제공을 요청하면 불가능한 요청이라는 Exception 발생
*
* @return long 타입 ID
* @throws FdlException 아이디 생성에 실패한 경우
*/
public long getNextLongId() throws FdlException {
throw new FdlException(messageSource, "error.idgnr.not.supported",
new String[] {"Long" }, null);
}
/**
* short 타입을 아이디 제공을 요청하면 불가능한 요청이라는 Exception 발생
*
* @return short 타입 ID
* @throws FdlException 아이디 생성에 실패한 경우
*/
public short getNextShortId() throws FdlException {
throw new FdlException(messageSource, "error.idgnr.not.supported",
new String[] {"Short" }, null);
}
/**
* String 타입을 아이디 제공
*
* @return String 타입 ID
* @throws FdlException 아이디 생성에 실패한 경우
*/
public String getNextStringId() throws FdlException {
return getUUId();
}
/**
* 정책정보를 입력받아 String 타입을 아이디 제공을 요청하면 불가능한 요청이라는 에러 발생
*
* @param strategy 정책정보 오브젝트
* @return String 타입 ID
* @throws FdlException 아이디 생성에 실패한 경우
*/
public String getNextStringId(EgovIdGnrStrategy strategy) throws FdlException {
throw new FdlException(messageSource, "error.idgnr.not.supported",
new String[] {"String" }, null);
}
/**
* 정책정보를 입력받아 String 타입을 아이디 제공을 요청하면 불가능한 요청이라는 에러 발생
*
* @param strategy 정책 String
* @return String 타입 ID
* @throws FdlException 아이디 생성에 실패한 경우
*/
public String getNextStringId(String strategyId) throws FdlException {
throw new FdlException(messageSource, "error.idgnr.not.supported",
new String[] {"String" }, null);
}
/**
* Config 정보에 지정된 Address 세팅
*
* @param address Config 에 지정된 address 정보
* @throws FdlException IP 정보가 이상한 경우
*/
public void setAddress(String address) throws FdlException {
// CHECKSTYLE:OFF
// this.address = address;
byte[] addressBytes = new byte[6];
if (null == address) {
LOGGER.warn("IDGeneration Service : Using a random number as the "
+ "base for id's. This is not the best method for many "
+ "purposes, but may be adequate in some circumstances."
+ " Consider using an IP or ethernet (MAC) address if "
+ "available. ");
for (int i = 0; i < 6; i++) {
addressBytes[i] = (byte) (255 * Math.random());
}
} else {
if (address.indexOf(".") > 0) {
// we should have an IP
StringTokenizer stok = new StringTokenizer(address, ".");
if (stok.countTokens() != 4) {
throw new FdlException(ERROR_STRING);
}
addressBytes[0] = (byte) 255;
addressBytes[1] = (byte) 255;
int i = 2;
try {
while (stok.hasMoreTokens()) {
addressBytes[i++] =
Integer.valueOf(stok.nextToken(), 16).byteValue();
}
} catch (Exception e) {
throw new FdlException(ERROR_STRING);
}
} else if (address.indexOf(":") > 0) {
// we should have a MAC
StringTokenizer stok = new StringTokenizer(address, ":");
if (stok.countTokens() != 6) {
throw new FdlException(ERROR_STRING);
}
int i = 0;
try {
while (stok.hasMoreTokens()) {
addressBytes[i++] =
Integer.valueOf(stok.nextToken(), 16).byteValue();
}
} catch (Exception e) {
throw new FdlException(ERROR_STRING);
}
} else {
throw new FdlException(ERROR_STRING);
}
}
mAddressId = Base64.encode(addressBytes);
// CHECKSTYLE:ON
}
/**
* UUID 얻기
* @return String unique id
*/
private String getUUId() {
// CHECKSTYLE:OFF
byte[] bytes6 = new byte[6];
long timeNow = System.currentTimeMillis();
timeNow = (int) timeNow & 0xFFFFFFFF;
byte[] bytes4 = new byte[4];
toFixSizeByteArray(new BigInteger(String.valueOf(timeNow)), bytes4);
bytes6[0] = bytes4[0];
bytes6[1] = bytes4[1];
bytes6[2] = bytes4[2];
bytes6[3] = bytes4[3];
short counter;
synchronized (this) {
counter = getLoopCounter();
}
byte[] bytes2 = new byte[2];
toFixSizeByteArray(new BigInteger(String.valueOf(counter)), bytes2);
bytes6[4] = bytes2[0];
bytes6[5] = bytes2[1];
mTimeId = Base64.encode(bytes6);
// CHECKSTYLE:ON
return (mAddressId + mTimeId).replace('+', '_').replace('/', '@');
}
/**
* Get the counter value as a signed short
*
* @original Get the counter value as a signed short
* @return short loop count
*/
private short getLoopCounter() {
return mLoopCounter++;
}
// CHECKSTYLE:OFF
/**
* To fix size byte array.
*
* @original This method transforms Java BigInteger type into a fix size byte array
* containing the two's-complement representation of the integer.
* The byte array will be in big-endian byte-order: the most significant byte is in the zeroth element.
* If the destination array is shorter then the BigInteger.toByteArray(),
* the the less significant bytes will be copy only.
* If the destination array is longer then the BigInteger.toByteArray(), destination will be left padded with zeros.
*
* @param bigInt Java BigInteger type
* @param destination destination array
*/
// CHECKSTYLE:ON
private void toFixSizeByteArray(BigInteger bigInt, byte[] destination) {
// Prepare the destination
for (int i = 0; i < destination.length; i++) {
destination[i] = 0x00;
}
// Convert the BigInt to a byte array
byte[] source = bigInt.toByteArray();
// Copy only the fix size length
if (source.length <= destination.length) {
for (int i = 0; i < source.length; i++) {
destination[destination.length - source.length + i] = source[i];
}
} else {
for (int i = 0; i < destination.length; i++) {
destination[i] = source[source.length - destination.length + i];
}
}
}
}