diff options
Diffstat (limited to 'src')
3 files changed, 188 insertions, 0 deletions
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<S extends Storable> {
+ private static final Map<Object, Class> cCache;
+
+ static {
+ cCache = new SoftValuedHashMap();
+ }
+
+ /**
+ * Delegate class has a constructor that accepts a {@link DelegateSupport}
+ * instance.
+ *
+ * <pre>
+ * public <init>(DelegateSupport);
+ * </pre>
+ *
+ */
+ public static <S extends Storable> Class<? extends S>
+ getDelegateClass(Class<S> type, EnumSet<MasterFeature> features)
+ throws SupportException
+ {
+ Object key = KeyFactory.createKey(new Object[] {type, features});
+
+ synchronized (cCache) {
+ Class<? extends S> generatedClass = (Class<? extends S>) cCache.get(key);
+ if (generatedClass != null) {
+ return generatedClass;
+ }
+ generatedClass = new DelegateStorableGenerator<S>(type, features)
+ .generateAndInjectClass();
+ cCache.put(key, generatedClass);
+ return generatedClass;
+ }
+ }
+
+ private final Class<S> mStorableType;
+
+ private final ClassInjector mClassInjector;
+ private final ClassFile mClassFile;
+
+ private DelegateStorableGenerator(Class<S> type, EnumSet<MasterFeature> features)
+ throws SupportException
+ {
+ mStorableType = type;
+
+ final Class<? extends S> 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<? extends S> 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<? extends S> 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<S extends Storable> extends MasterSupport<S> {
+ 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<S extends Storable> {
|