http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/component/ComponentLifecycle.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/component/ComponentLifecycle.java b/utils/src/main/java/com/cloud/utils/component/ComponentLifecycle.java new file mode 100644 index 0000000..897ddb1 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/component/ComponentLifecycle.java @@ -0,0 +1,64 @@ +// +// 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.utils.component; + +import java.util.Map; + +import javax.naming.ConfigurationException; + +public interface ComponentLifecycle extends Named { + public static final int RUN_LEVEL_SYSTEM_BOOTSTRAP = 0; // for system level bootstrap components + public static final int RUN_LEVEL_SYSTEM = 1; // for system level service components (i.e., DAOs) + public static final int RUN_LEVEL_FRAMEWORK_BOOTSTRAP = 2; // for framework startup checkers (i.e., DB migration check) + public static final int RUN_LEVEL_FRAMEWORK = 3; // for framework bootstrap components(i.e., clustering management components) + public static final int RUN_LEVEL_COMPONENT_BOOTSTRAP = 4; // general manager components + public static final int RUN_LEVEL_COMPONENT = 5; // regular adapters, plugin components + public static final int RUN_LEVEL_APPLICATION_MAINLOOP = 6; + public static final int MAX_RUN_LEVELS = 7; + + @Override + String getName(); + + void setName(String name); + + void setConfigParams(Map<String, Object> params); + + Map<String, Object> getConfigParams(); + + int getRunLevel(); + + void setRunLevel(int level); + + public boolean configure(String name, Map<String, Object> params) throws ConfigurationException; + + /** + * Start any background tasks. + * + * @return true if the tasks were started, false otherwise. + */ + public boolean start(); + + /** + * Stop any background tasks. + * + * @return true background tasks were stopped, false otherwise. + */ + public boolean stop(); +}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/component/ComponentLifecycleBase.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/component/ComponentLifecycleBase.java b/utils/src/main/java/com/cloud/utils/component/ComponentLifecycleBase.java new file mode 100644 index 0000000..829dc9b --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/component/ComponentLifecycleBase.java @@ -0,0 +1,87 @@ +// +// 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.utils.component; + +import java.util.HashMap; +import java.util.Map; + +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; + +public class ComponentLifecycleBase implements ComponentLifecycle { + private static final Logger s_logger = Logger.getLogger(ComponentLifecycleBase.class); + + protected String _name; + protected int _runLevel; + protected Map<String, Object> _configParams = new HashMap<String, Object>(); + + public ComponentLifecycleBase() { + _name = this.getClass().getSimpleName(); + _runLevel = RUN_LEVEL_COMPONENT; + } + + @Override + public String getName() { + return _name; + } + + @Override + public void setName(String name) { + _name = name; + } + + @Override + public void setConfigParams(Map<String, Object> params) { + _configParams = params; + } + + @Override + public Map<String, Object> getConfigParams() { + return _configParams; + } + + @Override + public int getRunLevel() { + return _runLevel; + } + + @Override + public void setRunLevel(int level) { + _runLevel = level; + } + + @Override + public boolean configure(String name, Map<String, Object> params) throws ConfigurationException { + _name = name; + _configParams = params; + return true; + } + + @Override + public boolean start() { + return true; + } + + @Override + public boolean stop() { + return true; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/component/ComponentMethodInterceptable.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/component/ComponentMethodInterceptable.java b/utils/src/main/java/com/cloud/utils/component/ComponentMethodInterceptable.java new file mode 100644 index 0000000..4d94391 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/component/ComponentMethodInterceptable.java @@ -0,0 +1,27 @@ +// +// 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.utils.component; + +/** + * Marker interface to work with CGLIB based CloudStack legacy AOP + * + */ +public interface ComponentMethodInterceptable { +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/component/ComponentMethodInterceptor.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/component/ComponentMethodInterceptor.java b/utils/src/main/java/com/cloud/utils/component/ComponentMethodInterceptor.java new file mode 100644 index 0000000..dca688a --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/component/ComponentMethodInterceptor.java @@ -0,0 +1,32 @@ +// +// 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.utils.component; + +import java.lang.reflect.Method; + +public interface ComponentMethodInterceptor { + boolean needToIntercept(Method method); + + Object interceptStart(Method method, Object target); + + void interceptComplete(Method method, Object target, Object objReturnedInInterceptStart); + + void interceptException(Method method, Object target, Object objReturnedInInterceptStart); +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/component/ComponentNamingPolicy.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/component/ComponentNamingPolicy.java b/utils/src/main/java/com/cloud/utils/component/ComponentNamingPolicy.java new file mode 100644 index 0000000..33d1dd4 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/component/ComponentNamingPolicy.java @@ -0,0 +1,65 @@ +// +// 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.utils.component; + +import net.sf.cglib.core.NamingPolicy; +import net.sf.cglib.core.Predicate; + +/** + * Copied/Modified from Spring source + * + */ +public class ComponentNamingPolicy implements NamingPolicy { + + public static final ComponentNamingPolicy INSTANCE = new ComponentNamingPolicy(); + + @Override + public String getClassName(String prefix, String source, Object key, Predicate names) { + if (prefix == null) { + prefix = "net.sf.cglib.empty.Object"; + } else if (prefix.startsWith("java")) { + prefix = "_" + prefix; + } + String base = prefix + "_" + source.substring(source.lastIndexOf('.') + 1) + getTag() + "_" + Integer.toHexString(key.hashCode()); + String attempt = base; + int index = 2; + while (names.evaluate(attempt)) + attempt = base + "_" + index++; + return attempt; + } + + /** + * Returns a string which is incorporated into every generated class name. + * By default returns "ByCloudStack" + */ + protected String getTag() { + return "ByCloudStack"; + } + + @Override + public int hashCode() { + return getTag().hashCode(); + } + + @Override + public boolean equals(Object o) { + return (o instanceof ComponentNamingPolicy) && ((ComponentNamingPolicy)o).getTag().equals(getTag()); + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/component/Manager.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/component/Manager.java b/utils/src/main/java/com/cloud/utils/component/Manager.java new file mode 100644 index 0000000..3200b46 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/component/Manager.java @@ -0,0 +1,27 @@ +// +// 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.utils.component; + +/** + * + * For now we only expose some simple methods. In the future, we can use this + **/ +public interface Manager extends ComponentLifecycle { +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/component/ManagerBase.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/component/ManagerBase.java b/utils/src/main/java/com/cloud/utils/component/ManagerBase.java new file mode 100644 index 0000000..01e4f40 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/component/ManagerBase.java @@ -0,0 +1,28 @@ +// +// 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.utils.component; + +public class ManagerBase extends ComponentLifecycleBase implements ComponentMethodInterceptable { + public ManagerBase() { + super(); + // set default run level for manager components + setRunLevel(ComponentLifecycle.RUN_LEVEL_COMPONENT_BOOTSTRAP); + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/component/Named.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/component/Named.java b/utils/src/main/java/com/cloud/utils/component/Named.java new file mode 100644 index 0000000..60835b0 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/component/Named.java @@ -0,0 +1,26 @@ +// +// 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.utils.component; + +public interface Named { + + String getName(); + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/component/PluggableService.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/component/PluggableService.java b/utils/src/main/java/com/cloud/utils/component/PluggableService.java new file mode 100644 index 0000000..60c64bf --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/component/PluggableService.java @@ -0,0 +1,29 @@ +// +// 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.utils.component; + +import java.util.List; + +// This interface defines methods for pluggable code within the Cloud Stack. +public interface PluggableService { + // The config command properties filenames that lists allowed API commands + // and role masks supported by this pluggable service + List<Class<?>> getCommands(); +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/component/Registry.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/component/Registry.java b/utils/src/main/java/com/cloud/utils/component/Registry.java new file mode 100644 index 0000000..d3a48df --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/component/Registry.java @@ -0,0 +1,51 @@ +// +// 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.utils.component; + +import java.util.List; + +/** + * Simple interface to represents a registry of items + * + * @param <T> + */ +public interface Registry<T> extends Named { + + /** + * Registers an item. If the item has already been registered the implementation + * should detect that it is registered and not re-register it. + * + * @param type + * @return true if register, false if not registered or already exists + */ + boolean register(T type); + + void unregister(T type); + + /** + * Returns a list that will dynamically change as items are registered/unregister. + * The list is thread safe to iterate upon. Traversing the list using an index + * would not be safe as the size may changed during traversal. + * + * @return Unmodifiable list of registered items + */ + List<T> getRegistered(); + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/component/SystemIntegrityChecker.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/component/SystemIntegrityChecker.java b/utils/src/main/java/com/cloud/utils/component/SystemIntegrityChecker.java new file mode 100644 index 0000000..a0e2581 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/component/SystemIntegrityChecker.java @@ -0,0 +1,30 @@ +// +// 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.utils.component; + +/** + * before any other components are loaded. Within ComponentLocator + * database upgrades and other verification to make sure it works. + */ +public interface SystemIntegrityChecker { + public static final String Name = "system-integrity-checker"; + + void check(); +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/concurrency/NamedThreadFactory.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/concurrency/NamedThreadFactory.java b/utils/src/main/java/com/cloud/utils/concurrency/NamedThreadFactory.java new file mode 100644 index 0000000..ed4d6b0 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/concurrency/NamedThreadFactory.java @@ -0,0 +1,38 @@ +// +// 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.utils.concurrency; + +import java.util.concurrent.ThreadFactory; + +public class NamedThreadFactory implements ThreadFactory { + private int _number; + private final String _name; + + public NamedThreadFactory(String name) { + _name = name; + _number = 1; + } + + @Override + public synchronized Thread newThread(Runnable r) { + return new Thread(r, _name + "-" + _number++); + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/concurrency/Scheduler.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/concurrency/Scheduler.java b/utils/src/main/java/com/cloud/utils/concurrency/Scheduler.java new file mode 100644 index 0000000..e0dba24 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/concurrency/Scheduler.java @@ -0,0 +1,31 @@ +// +// 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.utils.concurrency; + +import java.util.Date; + +public interface Scheduler { + + /** + * This is called from the TimerTask thread periodically about every one minute. + * + */ + public void poll(Date currentTimestamp); +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/concurrency/SynchronizationEvent.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/concurrency/SynchronizationEvent.java b/utils/src/main/java/com/cloud/utils/concurrency/SynchronizationEvent.java new file mode 100644 index 0000000..5207ad4 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/concurrency/SynchronizationEvent.java @@ -0,0 +1,89 @@ +// +// 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.utils.concurrency; + +import org.apache.log4j.Logger; + +public class SynchronizationEvent { + protected final static Logger s_logger = Logger.getLogger(SynchronizationEvent.class); + + private boolean signalled; + + public SynchronizationEvent() { + signalled = false; + } + + public SynchronizationEvent(boolean signalled) { + this.signalled = signalled; + } + + public void setEvent() { + synchronized (this) { + signalled = true; + notifyAll(); + } + } + + public void resetEvent() { + synchronized (this) { + signalled = false; + } + } + + public boolean waitEvent() throws InterruptedException { + synchronized (this) { + if (signalled) + return true; + + while (true) { + try { + wait(); + assert (signalled); + return signalled; + } catch (InterruptedException e) { + s_logger.debug("unexpected awaken signal in wait()"); + throw e; + } + } + } + } + + public boolean waitEvent(long timeOutMiliseconds) throws InterruptedException { + synchronized (this) { + if (signalled) + return true; + + try { + wait(timeOutMiliseconds); + return signalled; + } catch (InterruptedException e) { + // TODO, we don't honor time out semantics when the waiting thread is interrupted + s_logger.debug("unexpected awaken signal in wait(...)"); + throw e; + } + } + } + + public boolean isSignalled() { + synchronized (this) { + return signalled; + } + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/concurrency/TestClock.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/concurrency/TestClock.java b/utils/src/main/java/com/cloud/utils/concurrency/TestClock.java new file mode 100644 index 0000000..43fe56f --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/concurrency/TestClock.java @@ -0,0 +1,161 @@ +// +// 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.utils.concurrency; + +import java.util.Calendar; +import java.util.Date; +import java.util.TimerTask; + +/** + * A test clock which is also a TimerTask. The task calls a Scheduler's poll method + * + */ +public class TestClock extends TimerTask { + private int _minute = 0; + private int _hour = 0; + private int _day = 0; + private int _week = 0; + private int _month = 0; + private int _year = 0; + private Calendar _cal = null; + private final int _minutesPerHour; + private final int _hoursPerDay; + private final int _daysPerWeek; + private final int _daysPerMonth; + private final int _weeksPerMonth; + private final int _monthsPerYear; + private final Scheduler _scheduler; + + public TestClock(Scheduler scheduler, int minutesPerHour, int hoursPerDay, int daysPerWeek, int daysPerMonth, int weeksPerMonth, int monthsPerYear) { + _minutesPerHour = minutesPerHour; + _hoursPerDay = hoursPerDay; + _daysPerWeek = daysPerWeek; + _daysPerMonth = daysPerMonth; + _weeksPerMonth = weeksPerMonth; + _monthsPerYear = monthsPerYear; + _cal = Calendar.getInstance(); + _year = _cal.get(Calendar.YEAR); + _month = _cal.get(Calendar.MONTH); + _day = _cal.get(Calendar.DAY_OF_MONTH); + _week = _cal.get(Calendar.WEEK_OF_MONTH); + _hour = _cal.get(Calendar.HOUR_OF_DAY); + _minute = _cal.get(Calendar.MINUTE); + _scheduler = scheduler; + } + + public int getMinute() { + synchronized (this) { + return _minute; + } + } + + public int getHour() { + synchronized (this) { + return _hour; + } + } + + public int getDay() { + synchronized (this) { + return _day; + } + } + + public int getWeek() { + synchronized (this) { + return _week; + } + } + + public int getMonth() { + synchronized (this) { + return _month; + } + } + + public int getYear() { + synchronized (this) { + return _year; + } + } + + public int getMinutesPerHour() { + return _minutesPerHour; + } + + public int getHoursPerDay() { + return _hoursPerDay; + } + + public int getDaysPerMonth() { + return _daysPerMonth; + } + + public int getDaysPerWeek() { + return _daysPerWeek; + } + + public int getWeeksPerMonth() { + return _weeksPerMonth; + } + + public int getMonthsPerYear() { + return _monthsPerYear; + } + + @Override + public void run() { + synchronized (this) { + _minute++; + if ((_minute > 0) && ((_minute % _minutesPerHour) == 0)) { + _minute = 0; + _hour++; + } + + if ((_hour > 0) && ((_hour % _hoursPerDay) == 0)) { + _hour = 0; + _day++; + } + + if ((_day > 0) && ((_day % _daysPerWeek) == 0)) { + _week++; + } + + if ((_day > 0) && ((_day % _daysPerMonth) == 0)) { + _day = 0; + _week = 0; + _month++; + } + + if ((_month > 0) && ((_month % _monthsPerYear) == 0)) { + _month = 0; + _year++; + } + if (_scheduler != null) { + // XXX: Creating new date is hugely inefficient for every minute. + // Later the time in the database will be changed to currentTimeInMillis. + // Then we can use System.getCurrentTimeInMillis() which is damn cheap. + _cal.set(_year, _month, _day, _hour, _minute); + Date currentTimestamp = _cal.getTime(); + _scheduler.poll(currentTimestamp); + } + } + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/crypt/DBEncryptionUtil.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/crypt/DBEncryptionUtil.java b/utils/src/main/java/com/cloud/utils/crypt/DBEncryptionUtil.java new file mode 100644 index 0000000..52f2034 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/crypt/DBEncryptionUtil.java @@ -0,0 +1,87 @@ +// +// 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.utils.crypt; + +import java.util.Properties; + +import org.apache.log4j.Logger; +import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; +import org.jasypt.exceptions.EncryptionOperationNotPossibleException; + +import com.cloud.utils.db.DbProperties; +import com.cloud.utils.exception.CloudRuntimeException; + +public class DBEncryptionUtil { + + public static final Logger s_logger = Logger.getLogger(DBEncryptionUtil.class); + private static StandardPBEStringEncryptor s_encryptor = null; + + public static String encrypt(String plain) { + if (!EncryptionSecretKeyChecker.useEncryption() || (plain == null) || plain.isEmpty()) { + return plain; + } + if (s_encryptor == null) { + initialize(); + } + String encryptedString = null; + try { + encryptedString = s_encryptor.encrypt(plain); + } catch (EncryptionOperationNotPossibleException e) { + s_logger.debug("Error while encrypting: " + plain); + throw e; + } + return encryptedString; + } + + public static String decrypt(String encrypted) { + if (!EncryptionSecretKeyChecker.useEncryption() || (encrypted == null) || encrypted.isEmpty()) { + return encrypted; + } + if (s_encryptor == null) { + initialize(); + } + + String plain = null; + try { + plain = s_encryptor.decrypt(encrypted); + } catch (EncryptionOperationNotPossibleException e) { + s_logger.debug("Error while decrypting: " + encrypted); + throw e; + } + return plain; + } + + private static void initialize() { + final Properties dbProps = DbProperties.getDbProperties(); + + if (EncryptionSecretKeyChecker.useEncryption()) { + String dbSecretKey = dbProps.getProperty("db.cloud.encrypt.secret"); + if (dbSecretKey == null || dbSecretKey.isEmpty()) { + throw new CloudRuntimeException("Empty DB secret key in db.properties"); + } + + s_encryptor = new StandardPBEStringEncryptor(); + s_encryptor.setAlgorithm("PBEWithMD5AndDES"); + s_encryptor.setPassword(dbSecretKey); + } else { + throw new CloudRuntimeException("Trying to encrypt db values when encrytion is not enabled"); + } + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/crypt/EncryptionSecretKeyChecker.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/crypt/EncryptionSecretKeyChecker.java b/utils/src/main/java/com/cloud/utils/crypt/EncryptionSecretKeyChecker.java new file mode 100644 index 0000000..6524987 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/crypt/EncryptionSecretKeyChecker.java @@ -0,0 +1,146 @@ +// +// 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.utils.crypt; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.Properties; + +import javax.annotation.PostConstruct; + +import org.apache.log4j.Logger; +import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; +import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig; + +import com.cloud.utils.db.DbProperties; +import com.cloud.utils.exception.CloudRuntimeException; + +public class EncryptionSecretKeyChecker { + + private static final Logger s_logger = Logger.getLogger(EncryptionSecretKeyChecker.class); + + // Two possible locations with the new packaging naming + private static final String s_altKeyFile = "key"; + private static final String s_keyFile = "key"; + private static final String s_envKey = "CLOUD_SECRET_KEY"; + private static StandardPBEStringEncryptor s_encryptor = new StandardPBEStringEncryptor(); + private static boolean s_useEncryption = false; + + @PostConstruct + public void init() { + /* This will call DbProperties, which will call this to initialize the encryption. Yep, + * round about and annoying */ + DbProperties.getDbProperties(); + } + + public void check(Properties dbProps) throws IOException { + String encryptionType = dbProps.getProperty("db.cloud.encryption.type"); + + s_logger.debug("Encryption Type: " + encryptionType); + + if (encryptionType == null || encryptionType.equals("none")) { + return; + } + + if (s_useEncryption) { + s_logger.warn("Encryption already enabled, is check() called twice?"); + return; + } + + s_encryptor.setAlgorithm("PBEWithMD5AndDES"); + String secretKey = null; + + SimpleStringPBEConfig stringConfig = new SimpleStringPBEConfig(); + + if (encryptionType.equals("file")) { + InputStream is = this.getClass().getClassLoader().getResourceAsStream(s_keyFile); + if (is == null) { + is = this.getClass().getClassLoader().getResourceAsStream(s_altKeyFile); + } + if(is == null) { //This is means we are not able to load key file from the classpath. + throw new CloudRuntimeException(s_keyFile + " File containing secret key not found in the classpath: "); + } + + try (BufferedReader in = new BufferedReader(new InputStreamReader(is));) { + secretKey = in.readLine(); + //Check for null or empty secret key + } catch (IOException e) { + throw new CloudRuntimeException("Error while reading secret key from: " + s_keyFile, e); + } + + if (secretKey == null || secretKey.isEmpty()) { + throw new CloudRuntimeException("Secret key is null or empty in file " + s_keyFile); + } + + } else if (encryptionType.equals("env")) { + secretKey = System.getenv(s_envKey); + if (secretKey == null || secretKey.isEmpty()) { + throw new CloudRuntimeException("Environment variable " + s_envKey + " is not set or empty"); + } + } else if (encryptionType.equals("web")) { + int port = 8097; + try (ServerSocket serverSocket = new ServerSocket(port);) { + s_logger.info("Waiting for admin to send secret key on port " + port); + try ( + Socket clientSocket = serverSocket.accept(); + PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); + BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); + ) { + String inputLine; + if ((inputLine = in.readLine()) != null) { + secretKey = inputLine; + } + } catch (IOException e) { + throw new CloudRuntimeException("Accept failed on " + port); + } + } catch (IOException ioex) { + throw new CloudRuntimeException("Error initializing secret key reciever", ioex); + } + } else { + throw new CloudRuntimeException("Invalid encryption type: " + encryptionType); + } + + stringConfig.setPassword(secretKey); + s_encryptor.setConfig(stringConfig); + s_useEncryption = true; + } + + public static StandardPBEStringEncryptor getEncryptor() { + return s_encryptor; + } + + public static boolean useEncryption() { + return s_useEncryption; + } + + //Initialize encryptor for migration during secret key change + public static void initEncryptorForMigration(String secretKey) { + s_encryptor.setAlgorithm("PBEWithMD5AndDES"); + SimpleStringPBEConfig stringConfig = new SimpleStringPBEConfig(); + stringConfig.setPassword(secretKey); + s_encryptor.setConfig(stringConfig); + s_useEncryption = true; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/crypt/EncryptionSecretKeySender.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/crypt/EncryptionSecretKeySender.java b/utils/src/main/java/com/cloud/utils/crypt/EncryptionSecretKeySender.java new file mode 100644 index 0000000..ed44ac6 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/crypt/EncryptionSecretKeySender.java @@ -0,0 +1,65 @@ +// +// 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.utils.crypt; + + +import java.io.PrintWriter; +import java.net.InetAddress; +import java.net.Socket; +import com.cloud.utils.NumbersUtil; + + +public class EncryptionSecretKeySender { + public static void main(String args[]) { + try { + // Create a socket to the host + String hostname = "localhost"; + int port = 8097; + + if (args.length == 2) { + hostname = args[0]; + port = NumbersUtil.parseInt(args[1], port); + } + InetAddress addr = InetAddress.getByName(hostname); + try(Socket socket = new Socket(addr, port); + PrintWriter out = new PrintWriter(socket.getOutputStream(), true);) + { + java.io.BufferedReader stdin = new java.io.BufferedReader(new java.io.InputStreamReader(System.in)); + String validationWord = "cloudnine"; + String validationInput = ""; + while (!validationWord.equals(validationInput)) { + System.out.print("Enter Validation Word:"); + validationInput = stdin.readLine(); + System.out.println(); + } + System.out.print("Enter Secret Key:"); + String input = stdin.readLine(); + if (input != null) { + out.println(input); + } + }catch (Exception e) + { + System.out.println("Exception " + e.getMessage()); + } + } catch (Exception e) { + System.out.print("Exception while sending secret key " + e); + } + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/crypt/RSAHelper.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/crypt/RSAHelper.java b/utils/src/main/java/com/cloud/utils/crypt/RSAHelper.java new file mode 100644 index 0000000..692ac22 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/crypt/RSAHelper.java @@ -0,0 +1,90 @@ +// +// 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.utils.crypt; + +import java.io.ByteArrayInputStream; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.SecureRandom; +import java.security.Security; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.KeySpec; +import java.security.spec.RSAPublicKeySpec; + +import javax.crypto.Cipher; + +import org.apache.commons.codec.binary.Base64; +import org.apache.log4j.Logger; +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +public class RSAHelper { + final static Logger s_logger = Logger.getLogger(RSAHelper.class); + + static { + BouncyCastleProvider provider = new BouncyCastleProvider(); + if (Security.getProvider(provider.getName()) == null) + Security.addProvider(provider); + } + + private static RSAPublicKey readKey(String key) throws Exception { + byte[] encKey = Base64.decodeBase64(key.split(" ")[1]); + DataInputStream dis = new DataInputStream(new ByteArrayInputStream(encKey)); + + byte[] header = readElement(dis); + String pubKeyFormat = new String(header); + if (!pubKeyFormat.equals("ssh-rsa")) + throw new RuntimeException("Unsupported format"); + + byte[] publicExponent = readElement(dis); + byte[] modulus = readElement(dis); + + KeySpec spec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(publicExponent)); + KeyFactory keyFactory = KeyFactory.getInstance("RSA", BouncyCastleProvider.PROVIDER_NAME); + RSAPublicKey pubKey = (RSAPublicKey)keyFactory.generatePublic(spec); + + return pubKey; + } + + private static byte[] readElement(DataInput dis) throws IOException { + int len = dis.readInt(); + byte[] buf = new byte[len]; + dis.readFully(buf); + return buf; + } + + public static String encryptWithSSHPublicKey(String sshPublicKey, String content) { + String returnString = null; + try { + RSAPublicKey publicKey = readKey(sshPublicKey); + Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", BouncyCastleProvider.PROVIDER_NAME); + cipher.init(Cipher.ENCRYPT_MODE, publicKey, new SecureRandom()); + byte[] encrypted = cipher.doFinal(content.getBytes()); + returnString = Base64.encodeBase64String(encrypted); + } catch (Exception e) { + s_logger.info("[ignored]" + + "error during public key encryption: " + e.getLocalizedMessage()); + } + + return returnString; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/db/DbProperties.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/db/DbProperties.java b/utils/src/main/java/com/cloud/utils/db/DbProperties.java new file mode 100644 index 0000000..8420614 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/db/DbProperties.java @@ -0,0 +1,109 @@ +// +// 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.utils.db; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.apache.commons.io.IOUtils; +import org.apache.log4j.Logger; +import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; +import org.jasypt.properties.EncryptableProperties; + +import com.cloud.utils.PropertiesUtil; +import com.cloud.utils.crypt.EncryptionSecretKeyChecker; + +public class DbProperties { + + private static final Logger log = Logger.getLogger(DbProperties.class); + + private static Properties properties = new Properties(); + private static boolean loaded = false; + + protected static Properties wrapEncryption(Properties dbProps) throws IOException { + EncryptionSecretKeyChecker checker = new EncryptionSecretKeyChecker(); + checker.check(dbProps); + + if (EncryptionSecretKeyChecker.useEncryption()) { + return dbProps; + } else { + EncryptableProperties encrProps = new EncryptableProperties(EncryptionSecretKeyChecker.getEncryptor()); + encrProps.putAll(dbProps); + return encrProps; + } + } + + public synchronized static Properties getDbProperties() { + if (!loaded) { + Properties dbProps = new Properties(); + InputStream is = null; + try { + File props = PropertiesUtil.findConfigFile("db.properties"); + if (props != null && props.exists()) { + is = new FileInputStream(props); + } + + if (is == null) { + is = PropertiesUtil.openStreamFromURL("db.properties"); + } + + if (is == null) { + System.err.println("Failed to find db.properties"); + log.error("Failed to find db.properties"); + } + + if (is != null) { + dbProps.load(is); + } + + EncryptionSecretKeyChecker checker = new EncryptionSecretKeyChecker(); + checker.check(dbProps); + + if (EncryptionSecretKeyChecker.useEncryption()) { + StandardPBEStringEncryptor encryptor = EncryptionSecretKeyChecker.getEncryptor(); + EncryptableProperties encrDbProps = new EncryptableProperties(encryptor); + encrDbProps.putAll(dbProps); + dbProps = encrDbProps; + } + } catch (IOException e) { + throw new IllegalStateException("Failed to load db.properties", e); + } finally { + IOUtils.closeQuietly(is); + } + + properties = dbProps; + loaded = true; + } + + return properties; + } + + public synchronized static Properties setDbProperties(Properties props) throws IOException { + if (loaded) { + throw new IllegalStateException("DbProperties has already been loaded"); + } + properties = wrapEncryption(props); + loaded = true; + return properties; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/db/EntityManager.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/db/EntityManager.java b/utils/src/main/java/com/cloud/utils/db/EntityManager.java new file mode 100644 index 0000000..8f4e385 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/db/EntityManager.java @@ -0,0 +1,84 @@ +// +// 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.utils.db; + +import java.io.Serializable; +import java.util.List; + +/** + * Generic Entity Manager to retrieve database objects. + * + */ +public interface EntityManager { + /** + * Finds an entity by its id. + * @param <T> class of the entity you're trying to find. + * @param <K> class of the id that the entity uses. + * @param entityType Type of the entity. + * @param id id value + * @return T if found; null if not. + */ + public <T, K extends Serializable> T findById(Class<T> entityType, K id); + + /** + * Finds a unique entity by uuid string + * @param <T> entity class + * @param entityType type of entity you're looking for. + * @param uuid the unique id + * @return T if found, null if not. + */ + public <T> T findByUuid(Class<T> entityType, String uuid); + + /** + * Finds a unique entity by uuid string, including those removed entries + * @param <T> entity class + * @param entityType type of entity you're looking for. + * @param uuid the unique id + * @return T if found, null if not. + */ + public <T> T findByUuidIncludingRemoved(Class<T> entityType, String uuid); + + /** + * Finds an entity by external id which is always String + * @param <T> entity class + * @param entityType type of entity you're looking for. + * @param xid external id + * @return T if found, null if not. + */ + public <T> T findByXId(Class<T> entityType, String xid); + + /** + * Lists all entities. Use this method at your own risk. + * @param <T> entity class + * @param entityType type of entity you're looking for. + * @return List<T> + */ + public <T> List<? extends T> list(Class<T> entityType); + + public <T, K extends Serializable> void remove(Class<T> entityType, K id); + + public <T, K extends Serializable> T findByIdIncludingRemoved(Class<T> entityType, K id); + + public static final String MESSAGE_REMOVE_ENTITY_EVENT = "Message.RemoveEntity.Event"; + + public static final String MESSAGE_GRANT_ENTITY_EVENT = "Message.GrantEntity.Event"; + public static final String MESSAGE_REVOKE_ENTITY_EVENT = "Message.RevokeEntity.Event"; + public static final String MESSAGE_ADD_DOMAIN_WIDE_ENTITY_EVENT = "Message.AddDomainWideEntity.Event"; +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/db/UUIDManager.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/db/UUIDManager.java b/utils/src/main/java/com/cloud/utils/db/UUIDManager.java new file mode 100644 index 0000000..cac1876 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/db/UUIDManager.java @@ -0,0 +1,48 @@ +// +// 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.utils.db; + + +public interface UUIDManager { + + /** + * Generates a new uuid or uses the customId + * @param entityType the type of entity + * @param customId optional custom uuid of the object. + * @return newly created uuid. + */ + public <T> String generateUuid(Class<T> entityType, String customId); + + /** + * Checks the uuid for correct format, uniqueness and permissions. + * @param uuid uuid to check + * @param entityType the type of entity + * . + */ + <T> void checkUuid(String uuid, Class<T> entityType); + + /** + * Checks the uuid for correct format, uniqueness, without checking permissions + * @param uuid uuid to check + * @param entityType the type of entity + * . + */ + <T> void checkUuidSimple(String uuid, Class<T> entityType); +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/encoding/URLEncoder.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/encoding/URLEncoder.java b/utils/src/main/java/com/cloud/utils/encoding/URLEncoder.java new file mode 100644 index 0000000..58971e7 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/encoding/URLEncoder.java @@ -0,0 +1,113 @@ +// +// 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.utils.encoding; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.nio.charset.Charset; +import java.nio.charset.CharsetEncoder; +import java.util.BitSet; + +/** + * + * This class is very similar to the java.net.URLEncoder class. + * + * Unfortunately, with java.net.URLEncoder there is no way to specify to the + * java.net.URLEncoder which characters should NOT be encoded. + * + * This code was moved from DefaultServlet.java + * + * @author Craig R. McClanahan + * @author Remy Maucherat + */ + +public class URLEncoder { + protected static final char[] hexadecimal = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + + static CharsetEncoder asciiEncoder = Charset.forName("US-ASCII").newEncoder(); // or "ISO-8859-1" for ISO Latin 1 + + //Array containing the safe characters set. + protected BitSet safeCharacters = new BitSet(256); + + public URLEncoder() { + for (char i = 'a'; i <= 'z'; i++) { + addSafeCharacter(i); + } + for (char i = 'A'; i <= 'Z'; i++) { + addSafeCharacter(i); + } + for (char i = '0'; i <= '9'; i++) { + addSafeCharacter(i); + } + } + + private void addSafeCharacter(char c) { + safeCharacters.set(c); + } + + public String encode(String path) { + int maxBytesPerChar = 10; + StringBuffer rewrittenPath = new StringBuffer(path.length()); + ByteArrayOutputStream buf = new ByteArrayOutputStream(maxBytesPerChar); + OutputStreamWriter writer = null; + try { + writer = new OutputStreamWriter(buf, "UTF8"); + } catch (Exception e) { + e.printStackTrace(); + writer = new OutputStreamWriter(buf); + } + + for (int i = 0; i < path.length(); i++) { + int c = path.charAt(i); + // NOTICE - !isPureAscii(path.charAt(i)) check was added by + // CloudStack + if (safeCharacters.get(c) || !isPureAscii(path.charAt(i))) { + rewrittenPath.append((char)c); + } else { + // convert to external encoding before hex conversion + try { + writer.write((char)c); + writer.flush(); + } catch (IOException e) { + buf.reset(); + continue; + } + byte[] ba = buf.toByteArray(); + for (int j = 0; j < ba.length; j++) { + // Converting each byte in the buffer + byte toEncode = ba[j]; + rewrittenPath.append('%'); + int low = toEncode & 0x0f; + int high = (toEncode & 0xf0) >> 4; + rewrittenPath.append(hexadecimal[high]); + rewrittenPath.append(hexadecimal[low]); + } + buf.reset(); + } + } + return rewrittenPath.toString(); + } + + // NOTICE - this part was added by CloudStack + public static boolean isPureAscii(Character v) { + return asciiEncoder.canEncode(v); + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/events/EventArgs.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/events/EventArgs.java b/utils/src/main/java/com/cloud/utils/events/EventArgs.java new file mode 100644 index 0000000..5c06b4b --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/events/EventArgs.java @@ -0,0 +1,44 @@ +// +// 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.utils.events; + +import java.io.Serializable; + +public class EventArgs implements Serializable { + private static final long serialVersionUID = 30659016120504139L; + public static final EventArgs Empty = new EventArgs(); + + private String subject; + + public EventArgs() { + } + + public EventArgs(String subject) { + this.subject = subject; + } + + public String getSubject() { + return subject; + } + + public void setSubject(String subject) { + this.subject = subject; + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/events/SubscriptionMgr.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/events/SubscriptionMgr.java b/utils/src/main/java/com/cloud/utils/events/SubscriptionMgr.java new file mode 100644 index 0000000..254c27d --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/events/SubscriptionMgr.java @@ -0,0 +1,164 @@ +// +// 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.utils.events; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; + +public class SubscriptionMgr { + protected final static Logger s_logger = Logger.getLogger(SubscriptionMgr.class); + + private static SubscriptionMgr s_instance = new SubscriptionMgr(); + + private Map<String, List<SubscriberInfo>> registry; + + private SubscriptionMgr() { + registry = new HashMap<String, List<SubscriberInfo>>(); + } + + public static SubscriptionMgr getInstance() { + return s_instance; + } + + public <T> void subscribe(String subject, T subscriber, String listenerMethod) throws SecurityException, NoSuchMethodException { + + synchronized (this) { + List<SubscriberInfo> l = getAndSetSubscriberList(subject); + + Class<?> clazz = subscriber.getClass(); + SubscriberInfo subscribeInfo = new SubscriberInfo(clazz, subscriber, listenerMethod); + + if (!l.contains(subscribeInfo)) + l.add(subscribeInfo); + } + } + + public <T> void unsubscribe(String subject, T subscriber, String listenerMethod) { + synchronized (this) { + List<SubscriberInfo> l = getSubscriberList(subject); + if (l != null) { + for (SubscriberInfo info : l) { + if (info.isMe(subscriber.getClass(), subscriber, listenerMethod)) { + l.remove(info); + return; + } + } + } + } + } + + public void notifySubscribers(String subject, Object sender, EventArgs args) { + + List<SubscriberInfo> l = getExecutableSubscriberList(subject); + if (l != null) { + for (SubscriberInfo info : l) { + try { + info.execute(sender, args); + } catch (IllegalArgumentException e) { + s_logger.warn("Exception on notifying event subscribers: ", e); + } catch (IllegalAccessException e) { + s_logger.warn("Exception on notifying event subscribers: ", e); + } catch (InvocationTargetException e) { + s_logger.warn("Exception on notifying event subscribers: ", e); + } + } + } + } + + private List<SubscriberInfo> getAndSetSubscriberList(String subject) { + List<SubscriberInfo> l = registry.get(subject); + if (l == null) { + l = new ArrayList<SubscriberInfo>(); + registry.put(subject, l); + } + + return l; + } + + private List<SubscriberInfo> getSubscriberList(String subject) { + return registry.get(subject); + } + + private synchronized List<SubscriberInfo> getExecutableSubscriberList(String subject) { + List<SubscriberInfo> l = registry.get(subject); + if (l != null) { + // do a shadow clone + ArrayList<SubscriberInfo> clonedList = new ArrayList<SubscriberInfo>(l.size()); + for (SubscriberInfo info : l) + clonedList.add(info); + + return clonedList; + } + return null; + } + + private static class SubscriberInfo { + private Class<?> clazz; + private Object subscriber; + private String methodName; + private Method method; + + public SubscriberInfo(Class<?> clazz, Object subscriber, String methodName) throws SecurityException, NoSuchMethodException { + + this.clazz = clazz; + this.subscriber = subscriber; + this.methodName = methodName; + for (Method method : clazz.getMethods()) { + if (method.getName().equals(methodName)) { + Class<?>[] paramTypes = method.getParameterTypes(); + if (paramTypes != null && paramTypes.length == 2 && paramTypes[0] == Object.class && EventArgs.class.isAssignableFrom(paramTypes[1])) { + this.method = method; + + break; + } + } + } + if (this.method == null) + throw new NoSuchMethodException(); + } + + public void execute(Object sender, EventArgs args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { + + method.invoke(subscriber, sender, args); + } + + public boolean isMe(Class<?> clazz, Object subscriber, String methodName) { + return this.clazz == clazz && this.subscriber == subscriber && this.methodName.equals(methodName); + } + + @Override + public boolean equals(Object o) { + if (o == null) + return false; + + if (o instanceof SubscriberInfo) { + return this.clazz == ((SubscriberInfo)o).clazz && this.subscriber == ((SubscriberInfo)o).subscriber && + this.methodName.equals(((SubscriberInfo)o).methodName); + } + return false; + } + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/exception/CSExceptionErrorCode.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/exception/CSExceptionErrorCode.java b/utils/src/main/java/com/cloud/utils/exception/CSExceptionErrorCode.java new file mode 100644 index 0000000..62af14e --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/exception/CSExceptionErrorCode.java @@ -0,0 +1,100 @@ +// +// 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.utils.exception; + +import java.util.HashMap; + +import org.apache.log4j.Logger; + +/** + * CSExceptionErrorCode lists the CloudStack error codes that correspond + * to a each exception thrown by the CloudStack API. + */ + +public class CSExceptionErrorCode { + + public static final Logger s_logger = Logger.getLogger(CSExceptionErrorCode.class.getName()); + + // Declare a hashmap of CloudStack Error Codes for Exceptions. + protected static final HashMap<String, Integer> ExceptionErrorCodeMap; + + static { + try { + ExceptionErrorCodeMap = new HashMap<String, Integer>(); + ExceptionErrorCodeMap.put("com.cloud.utils.exception.CloudRuntimeException", 4250); + ExceptionErrorCodeMap.put("com.cloud.utils.exception.ExecutionException", 4260); + ExceptionErrorCodeMap.put("com.cloud.utils.exception.HypervisorVersionChangedException", 4265); + ExceptionErrorCodeMap.put("com.cloud.exception.CloudException", 4275); + ExceptionErrorCodeMap.put("com.cloud.exception.AccountLimitException", 4280); + ExceptionErrorCodeMap.put("com.cloud.exception.AgentUnavailableException", 4285); + ExceptionErrorCodeMap.put("com.cloud.exception.CloudAuthenticationException", 4290); + ExceptionErrorCodeMap.put("com.cloud.exception.ConcurrentOperationException", 4300); + ExceptionErrorCodeMap.put("com.cloud.exception.ConflictingNetworkSettingsException", 4305); + ExceptionErrorCodeMap.put("com.cloud.exception.DiscoveredWithErrorException", 4310); + ExceptionErrorCodeMap.put("com.cloud.exception.HAStateException", 4315); + ExceptionErrorCodeMap.put("com.cloud.exception.InsufficientAddressCapacityException", 4320); + ExceptionErrorCodeMap.put("com.cloud.exception.InsufficientCapacityException", 4325); + ExceptionErrorCodeMap.put("com.cloud.exception.InsufficientNetworkCapacityException", 4330); + ExceptionErrorCodeMap.put("com.cloud.exception.InsufficientVirtualNetworkCapacityException", 4331); + ExceptionErrorCodeMap.put("com.cloud.exception.InsufficientServerCapacityException", 4335); + ExceptionErrorCodeMap.put("com.cloud.exception.InsufficientStorageCapacityException", 4340); + ExceptionErrorCodeMap.put("com.cloud.exception.InternalErrorException", 4345); + ExceptionErrorCodeMap.put("com.cloud.exception.InvalidParameterValueException", 4350); + ExceptionErrorCodeMap.put("com.cloud.exception.ManagementServerException", 4355); + ExceptionErrorCodeMap.put("com.cloud.exception.NetworkRuleConflictException", 4360); + ExceptionErrorCodeMap.put("com.cloud.exception.PermissionDeniedException", 4365); + ExceptionErrorCodeMap.put("com.cloud.exception.ResourceAllocationException", 4370); + ExceptionErrorCodeMap.put("com.cloud.exception.ResourceInUseException", 4375); + ExceptionErrorCodeMap.put("com.cloud.exception.ResourceUnavailableException", 4380); + ExceptionErrorCodeMap.put("com.cloud.exception.StorageUnavailableException", 4385); + ExceptionErrorCodeMap.put("com.cloud.exception.UnsupportedServiceException", 4390); + ExceptionErrorCodeMap.put("com.cloud.exception.VirtualMachineMigrationException", 4395); + ExceptionErrorCodeMap.put("com.cloud.async.AsyncCommandQueued", 4540); + ExceptionErrorCodeMap.put("com.cloud.exception.RequestLimitException", 4545); + ExceptionErrorCodeMap.put("com.cloud.exception.StorageConflictException", 4550); + + // Have a special error code for ServerApiException when it is + // thrown in a standalone manner when failing to detect any of the above + // standard exceptions. + ExceptionErrorCodeMap.put("org.apache.cloudstack.api.ServerApiException", 9999); + } catch (Exception e) { + e.printStackTrace(); + throw new ExceptionInInitializerError(e); + } + } + + public static HashMap<String, Integer> getErrCodeList() { + return ExceptionErrorCodeMap; + } + + public static int getCSErrCode(String exceptionName) { + if (ExceptionErrorCodeMap.containsKey(exceptionName)) { + return ExceptionErrorCodeMap.get(exceptionName); + } else { + s_logger.info("Could not find exception: " + exceptionName + " in error code list for exceptions"); + return -1; + } + } + + public static String getCurMethodName() { + StackTraceElement stackTraceCalls[] = (new Throwable()).getStackTrace(); + return stackTraceCalls[1].toString(); + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/exception/CloudRuntimeException.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/exception/CloudRuntimeException.java b/utils/src/main/java/com/cloud/utils/exception/CloudRuntimeException.java new file mode 100644 index 0000000..dd5abc8 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/exception/CloudRuntimeException.java @@ -0,0 +1,141 @@ +// +// 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.utils.exception; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.List; + +import com.cloud.utils.Pair; +import com.cloud.utils.SerialVersionUID; + +/** + * wrap exceptions that you know there's no point in dealing with. + */ +public class CloudRuntimeException extends RuntimeException implements ErrorContext { + + private static final long serialVersionUID = SerialVersionUID.CloudRuntimeException; + + // This holds a list of uuids and their descriptive names. + transient protected ArrayList<ExceptionProxyObject> idList = new ArrayList<ExceptionProxyObject>(); + + transient protected ArrayList<Pair<Class<?>, String>> uuidList = new ArrayList<Pair<Class<?>, String>>(); + + protected int csErrorCode; + + public CloudRuntimeException(String message) { + super(message); + setCSErrorCode(CSExceptionErrorCode.getCSErrCode(this.getClass().getName())); + } + + public CloudRuntimeException(String message, Throwable th) { + super(message, th); + setCSErrorCode(CSExceptionErrorCode.getCSErrCode(this.getClass().getName())); + } + + protected CloudRuntimeException() { + super(); + + setCSErrorCode(CSExceptionErrorCode.getCSErrCode(this.getClass().getName())); + } + + public void addProxyObject(ExceptionProxyObject obj) { + idList.add(obj); + } + + public void addProxyObject(String uuid) { + idList.add(new ExceptionProxyObject(uuid, null)); + } + + public void addProxyObject(String voObjUuid, String description) { + ExceptionProxyObject proxy = new ExceptionProxyObject(voObjUuid, description); + idList.add(proxy); + } + + @Override + public CloudRuntimeException add(Class<?> entity, String uuid) { + uuidList.add(new Pair<Class<?>, String>(entity, uuid)); + return this; + } + + public ArrayList<ExceptionProxyObject> getIdProxyList() { + return idList; + } + + public void setCSErrorCode(int cserrcode) { + csErrorCode = cserrcode; + } + + public int getCSErrorCode() { + return csErrorCode; + } + + public CloudRuntimeException(Throwable t) { + super(t.getMessage(), t); + } + + @Override + public List<Pair<Class<?>, String>> getEntitiesInError() { + return uuidList; + } + + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + + int idListSize = idList.size(); + out.writeInt(idListSize); + for (ExceptionProxyObject proxy : idList) { + out.writeObject(proxy); + } + + int uuidListSize = uuidList.size(); + out.writeInt(uuidListSize); + for (Pair<Class<?>, String> entry : uuidList) { + out.writeObject(entry.first().getCanonicalName()); + out.writeObject(entry.second()); + } + } + + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + + int idListSize = in.readInt(); + if (idList == null) + idList = new ArrayList<ExceptionProxyObject>(); + if (uuidList == null) + uuidList = new ArrayList<Pair<Class<?>, String>>(); + + for (int i = 0; i < idListSize; i++) { + ExceptionProxyObject proxy = (ExceptionProxyObject)in.readObject(); + + idList.add(proxy); + } + + int uuidListSize = in.readInt(); + for (int i = 0; i < uuidListSize; i++) { + String clzName = (String)in.readObject(); + String val = (String)in.readObject(); + + uuidList.add(new Pair<Class<?>, String>(Class.forName(clzName), val)); + } + } +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/exception/ErrorContext.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/exception/ErrorContext.java b/utils/src/main/java/com/cloud/utils/exception/ErrorContext.java new file mode 100644 index 0000000..5391373 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/exception/ErrorContext.java @@ -0,0 +1,31 @@ +// +// 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.utils.exception; + +import java.util.List; + +import com.cloud.utils.Pair; + +public interface ErrorContext { + + ErrorContext add(Class<?> entity, String uuid); + + List<Pair<Class<?>, String>> getEntitiesInError(); +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/83fd8f60/utils/src/main/java/com/cloud/utils/exception/ExceptionProxyObject.java ---------------------------------------------------------------------- diff --git a/utils/src/main/java/com/cloud/utils/exception/ExceptionProxyObject.java b/utils/src/main/java/com/cloud/utils/exception/ExceptionProxyObject.java new file mode 100644 index 0000000..5a689d4 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/exception/ExceptionProxyObject.java @@ -0,0 +1,55 @@ +// +// 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.utils.exception; + +import java.io.Serializable; + + +public class ExceptionProxyObject implements Serializable { + private static final long serialVersionUID = -7514266713085362352L; + + private String uuid; + private String description; + + public ExceptionProxyObject(){ + + } + + public ExceptionProxyObject(String uuid, String desc){ + this.uuid = uuid; + description = desc; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +}