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> {
 | 
