blob: 070ce78c6c3f155a8970f00ca94f75ae219c4804 [file] [log] [blame]
// Copyright 2009 Google Inc.
//
// 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.google.gwtorm.protobuf;
import com.google.gwtorm.client.Column;
import com.google.gwtorm.server.GeneratedClassLoader;
import com.google.gwtorm.server.OrmException;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
/** Creates {@link ProtobufCodec} implementations on demand. */
public final class CodecFactory {
private static final Map<Class<?>, String> encoders =
Collections.synchronizedMap(new WeakHashMap<Class<?>, String>());
/**
* Create an implementation to encode/decode an arbitrary object.
* <p>
* The object must use the {@link Column} annotations to denote the fields
* that should be encoded or decoded.
*
* @param <T> type of the object to be supported.
* @param type the object type.
* @return an encoder for this object type.
* @throws IllegalArgumentException the object's fields aren't declared
* properly. This is a programming error that cannot be recovered.
*/
public static <T> ProtobufCodec<T> encoder(Class<T> type)
throws IllegalStateException {
final GeneratedClassLoader loader = newLoader(type);
ProtobufCodec<T> encoder = null;
String cacheName = encoders.get(type);
if (cacheName != null) {
encoder = get(loader, cacheName);
}
if (encoder == null) {
final CodecGen<T> gen = new CodecGen<>(loader, type);
try {
encoder = gen.create();
} catch (OrmException e) {
throw new IllegalArgumentException("Class " + type.getName()
+ " cannot be supported on protobuf", e);
}
encoders.put(type, encoder.getClass().getName());
}
return encoder;
}
private static <T> GeneratedClassLoader newLoader(final Class<T> type) {
return new GeneratedClassLoader(type.getClassLoader());
}
@SuppressWarnings("unchecked")
private static <T> ProtobufCodec<T> get(ClassLoader cl, String name) {
try {
return (ProtobufCodec<T>) Class.forName(name, true, cl).newInstance();
} catch (InstantiationException e) {
return null;
} catch (IllegalAccessException e) {
return null;
} catch (ClassNotFoundException e) {
return null;
}
}
private CodecFactory() {
}
}