This project has retired. For details please refer to its
Attic page.
001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package org.apache.oozie.service;
019
020 import java.text.SimpleDateFormat;
021 import java.util.Date;
022 import java.util.UUID;
023 import java.util.concurrent.atomic.AtomicLong;
024
025 import org.apache.oozie.ErrorCode;
026 import org.apache.oozie.util.ParamChecker;
027 import org.apache.oozie.util.XLog;
028
029 /**
030 * The UUID service generates unique IDs.
031 * <p/>
032 * The configuration property {@link #CONF_GENERATOR} specifies the ID generation type, 'random' or 'counter'.
033 * <p/>
034 * For 'random' uses the JDK UUID.randomUUID() method.
035 * <p/>
036 * For 'counter' uses a counter postfixed wit the system start up time.
037 */
038 public class UUIDService implements Service {
039
040 public static final String CONF_PREFIX = Service.CONF_PREFIX + "UUIDService.";
041
042 public static final String CONF_GENERATOR = CONF_PREFIX + "generator";
043
044 private String startTime;
045 private AtomicLong counter;
046 private String systemId;
047
048 /**
049 * Initialize the UUID service.
050 *
051 * @param services services instance.
052 * @throws ServiceException thrown if the UUID service could not be initialized.
053 */
054 @Override
055 public void init(Services services) throws ServiceException {
056 String genType = services.getConf().get(CONF_GENERATOR, "counter").trim();
057 if (genType.equals("counter")) {
058 counter = new AtomicLong();
059 startTime = new SimpleDateFormat("yyMMddHHmmssSSS").format(new Date());
060 }
061 else {
062 if (!genType.equals("random")) {
063 throw new ServiceException(ErrorCode.E0120, genType);
064 }
065 }
066 systemId = services.getSystemId();
067 }
068
069 /**
070 * Destroy the UUID service.
071 */
072 @Override
073 public void destroy() {
074 counter = null;
075 startTime = null;
076 }
077
078 /**
079 * Return the public interface for UUID service.
080 *
081 * @return {@link UUIDService}.
082 */
083 @Override
084 public Class<? extends Service> getInterface() {
085 return UUIDService.class;
086 }
087
088 private String longPadding(long number) {
089 StringBuilder sb = new StringBuilder();
090 sb.append(number);
091 if (sb.length() <= 7) {
092 sb.insert(0, "0000000".substring(sb.length()));
093 }
094 return sb.toString();
095 }
096
097 /**
098 * Create a unique ID.
099 *
100 * @param type: Type of Id. Generally 'C' for Coordinator and 'W' for Workflow.
101 * @return unique ID.
102 */
103 public String generateId(ApplicationType type) {
104 StringBuilder sb = new StringBuilder();
105
106 if (counter != null) {
107 sb.append(longPadding(counter.getAndIncrement())).append('-').append(startTime);
108 }
109 else {
110 sb.append(UUID.randomUUID().toString());
111 if (sb.length() > (37 - systemId.length())) {
112 sb.setLength(37 - systemId.length());
113 }
114 }
115 sb.append('-').append(systemId);
116 sb.append('-').append(type.getType());
117 // limitation due to current DB schema for action ID length (100)
118 if (sb.length() > 40) {
119 throw new RuntimeException(XLog.format("ID exceeds limit of 40 characters, [{0}]", sb));
120 }
121 return sb.toString();
122 }
123
124 /**
125 * Create a child ID.
126 * <p/>
127 * If the same child name is given the returned child ID is the same.
128 *
129 * @param id unique ID.
130 * @param childName child name.
131 * @return a child ID.
132 */
133 public String generateChildId(String id, String childName) {
134 id = ParamChecker.notEmpty(id, "id") + "@" + ParamChecker.notEmpty(childName, "childName");
135
136 // limitation due to current DB schema for action ID length (100)
137 if (id.length() > 95) {
138 throw new RuntimeException(XLog.format("Child ID exceeds limit of 95 characters, [{0}]", id));
139 }
140 return id;
141 }
142
143 /**
144 * Return the ID from a child ID.
145 *
146 * @param childId child ID.
147 * @return ID of the child ID.
148 */
149 public String getId(String childId) {
150 int index = ParamChecker.notEmpty(childId, "childId").indexOf("@");
151 if (index == -1) {
152 throw new IllegalArgumentException(XLog.format("invalid child id [{0}]", childId));
153 }
154 return childId.substring(0, index);
155 }
156
157 /**
158 * Return the child name from a child ID.
159 *
160 * @param childId child ID.
161 * @return child name.
162 */
163 public String getChildName(String childId) {
164 int index = ParamChecker.notEmpty(childId, "childId").indexOf("@");
165 if (index == -1) {
166 throw new IllegalArgumentException(XLog.format("invalid child id [{0}]", childId));
167 }
168 return childId.substring(index + 1);
169 }
170
171 public enum ApplicationType {
172 WORKFLOW('W'), COORDINATOR('C'), BUNDLE('B');
173 private final char type;
174
175 private ApplicationType(char type) {
176 this.type = type;
177 }
178
179 public char getType() {
180 return type;
181 }
182 }
183 }