From 63033e24be5a155c948a3fb418f91829865cc324 Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Sat, 26 Jan 2008 22:59:11 +0000 Subject: Added DelegateStorableGenerator. --- .../carbonado/gen/DelegateStorableGenerator.java | 149 +++++++++++++++++++++ .../com/amazon/carbonado/gen/DelegateSupport.java | 38 ++++++ .../amazon/carbonado/gen/StorableGenerator.java | 1 + 3 files changed, 188 insertions(+) create mode 100644 src/main/java/com/amazon/carbonado/gen/DelegateStorableGenerator.java create mode 100644 src/main/java/com/amazon/carbonado/gen/DelegateSupport.java (limited to 'src') diff --git a/src/main/java/com/amazon/carbonado/gen/DelegateStorableGenerator.java b/src/main/java/com/amazon/carbonado/gen/DelegateStorableGenerator.java new file mode 100644 index 0000000..4de28bd --- /dev/null +++ b/src/main/java/com/amazon/carbonado/gen/DelegateStorableGenerator.java @@ -0,0 +1,149 @@ +/* + * Copyright 2008 Amazon Technologies, Inc. or its affiliates. + * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks + * of Amazon Technologies, Inc. or its affiliates. All rights reserved. + * + * 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 com.amazon.carbonado.gen; + +import java.util.EnumSet; +import java.util.Map; + +import org.cojen.classfile.ClassFile; +import org.cojen.classfile.CodeBuilder; +import org.cojen.classfile.MethodInfo; +import org.cojen.classfile.Modifiers; +import org.cojen.classfile.TypeDesc; + +import org.cojen.util.ClassInjector; +import org.cojen.util.KeyFactory; +import org.cojen.util.SoftValuedHashMap; + +import com.amazon.carbonado.Storable; +import com.amazon.carbonado.SupportException; + +/** + * Generates and caches concrete implementations of {@link Storable} types + * which delegate to {@link DelegateSupport}. The delegating classes extend + * those generated by {@link MasterStorableGenerator}. + * + * @author Brian S O'Neill + * @since 1.2 + */ +public class DelegateStorableGenerator { + private static final Map cCache; + + static { + cCache = new SoftValuedHashMap(); + } + + /** + * Delegate class has a constructor that accepts a {@link DelegateSupport} + * instance. + * + *
+     * public <init>(DelegateSupport);
+     * 
+ * + */ + public static Class + getDelegateClass(Class type, EnumSet features) + throws SupportException + { + Object key = KeyFactory.createKey(new Object[] {type, features}); + + synchronized (cCache) { + Class generatedClass = (Class) cCache.get(key); + if (generatedClass != null) { + return generatedClass; + } + generatedClass = new DelegateStorableGenerator(type, features) + .generateAndInjectClass(); + cCache.put(key, generatedClass); + return generatedClass; + } + } + + private final Class mStorableType; + + private final ClassInjector mClassInjector; + private final ClassFile mClassFile; + + private DelegateStorableGenerator(Class type, EnumSet features) + throws SupportException + { + mStorableType = type; + + final Class abstractClass = + MasterStorableGenerator.getAbstractClass(mStorableType, features); + + mClassInjector = ClassInjector.create(mStorableType.getName(), + abstractClass.getClassLoader()); + + mClassFile = new ClassFile(mClassInjector.getClassName(), abstractClass); + mClassFile.markSynthetic(); + mClassFile.setSourceFile(DelegateStorableGenerator.class.getName()); + mClassFile.setTarget("1.5"); + } + + private Class generateAndInjectClass() { + TypeDesc masterSupportType = TypeDesc.forClass(MasterSupport.class); + TypeDesc delegateSupportType = TypeDesc.forClass(DelegateSupport.class); + + // Add constructor that accepts a DelegateSupport. + { + TypeDesc[] params = {delegateSupportType}; + MethodInfo mi = mClassFile.addConstructor(Modifiers.PUBLIC, params); + CodeBuilder b = new CodeBuilder(mi); + b.loadThis(); + b.loadLocal(b.getParameter(0)); + b.invokeSuperConstructor(new TypeDesc[] {masterSupportType}); + b.returnVoid(); + } + + // Implement abstract methods which all delegate to DelegateSupport instance. + + generateDelegatedMethod + (MasterStorableGenerator.DO_TRY_LOAD_MASTER_METHOD_NAME, "doTryLoad"); + generateDelegatedMethod + (MasterStorableGenerator.DO_TRY_INSERT_MASTER_METHOD_NAME, "doTryInsert"); + generateDelegatedMethod + (MasterStorableGenerator.DO_TRY_UPDATE_MASTER_METHOD_NAME, "doTryUpdate"); + generateDelegatedMethod + (MasterStorableGenerator.DO_TRY_DELETE_MASTER_METHOD_NAME, "doTryDelete"); + + Class generatedClass = mClassInjector.defineClass(mClassFile); + + return generatedClass; + } + + private void generateDelegatedMethod(String masterMethodName, String supportMethodName) { + TypeDesc triggerSupportType = TypeDesc.forClass(TriggerSupport.class); + TypeDesc delegateSupportType = TypeDesc.forClass(DelegateSupport.class); + + TypeDesc[] storableParam = {TypeDesc.forClass(Storable.class)}; + + MethodInfo mi = mClassFile.addMethod + (Modifiers.PROTECTED, masterMethodName, TypeDesc.BOOLEAN, null); + CodeBuilder b = new CodeBuilder(mi); + + b.loadThis(); + b.loadField(StorableGenerator.SUPPORT_FIELD_NAME, triggerSupportType); + b.checkCast(delegateSupportType); + b.loadThis(); + b.invokeInterface(delegateSupportType, supportMethodName, TypeDesc.BOOLEAN, storableParam); + b.returnValue(TypeDesc.BOOLEAN); + } +} diff --git a/src/main/java/com/amazon/carbonado/gen/DelegateSupport.java b/src/main/java/com/amazon/carbonado/gen/DelegateSupport.java new file mode 100644 index 0000000..31f0288 --- /dev/null +++ b/src/main/java/com/amazon/carbonado/gen/DelegateSupport.java @@ -0,0 +1,38 @@ +/* + * Copyright 2008 Amazon Technologies, Inc. or its affiliates. + * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks + * of Amazon Technologies, Inc. or its affiliates. All rights reserved. + * + * 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 com.amazon.carbonado.gen; + +import com.amazon.carbonado.Storable; + +/** + * Provides runtime support for Storable classes generated by {@link DelegateStorableGenerator}. + * + * @author Brian S O'Neill + * @since 1.2 + */ +public interface DelegateSupport extends MasterSupport { + boolean doTryLoad(S storable); + + boolean doTryInsert(S storable); + + boolean doTryUpdate(S storable); + + boolean doTryDelete(S storable); +} + diff --git a/src/main/java/com/amazon/carbonado/gen/StorableGenerator.java b/src/main/java/com/amazon/carbonado/gen/StorableGenerator.java index 5c8c93d..711ee58 100644 --- a/src/main/java/com/amazon/carbonado/gen/StorableGenerator.java +++ b/src/main/java/com/amazon/carbonado/gen/StorableGenerator.java @@ -78,6 +78,7 @@ import static com.amazon.carbonado.gen.CommonMethodNames.*; * @author Brian S O'Neill * @author Don Schneider * @see MasterStorableGenerator + * @see DelegateStorableGenerator * @since 1.2 */ public final class StorableGenerator { -- cgit v1.2.3