Java tutorial
/* * Copyright 2009 The Corner Team. * * 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 corner.protobuf; import java.util.Collection; import org.apache.commons.codec.binary.Base64; import org.apache.tapestry5.ValueEncoder; import org.apache.tapestry5.internal.InternalConstants; import org.apache.tapestry5.ioc.MappedConfiguration; import org.apache.tapestry5.ioc.annotations.Inject; import org.apache.tapestry5.ioc.annotations.Symbol; import org.apache.tapestry5.ioc.internal.util.InternalUtils; import org.apache.tapestry5.ioc.services.ClassNameLocator; import org.apache.tapestry5.ioc.services.Coercion; import org.apache.tapestry5.services.ValueEncoderFactory; import corner.orm.model.PaginationOptions; /** * ?<a href="http://code.google.com/p/protobuf/">Google protocol buffer</a>Value Encoder. * ??Object<->String?,?. * * @author dong * @author <a href="jun.tsai@ganshane.net">Jun Tsai</a> * @version $Revision$ * @since 0.0.1 */ public class ProtocolBuffersModule { public static void contributeValueEncoderSource(MappedConfiguration<Class, ValueEncoderFactory> configuration, final ClassNameLocator classNameLocator, @Inject @Symbol(InternalConstants.TAPESTRY_APP_PACKAGE_PARAM) String appRootPackage) { final String protoPackage = appRootPackage + ".protobuf"; final Collection<String> protoClasses = classNameLocator.locateClassNames(protoPackage); final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); for (String className : protoClasses) { addProtobufferCoercer(configuration, contextClassLoader, className); } //add PaginationOptions class type coercer addProtobufferCoercer(configuration, contextClassLoader, PaginationOptions.class.getName()); } private static void addProtobufferCoercer(MappedConfiguration<Class, ValueEncoderFactory> configuration, ClassLoader contextClassLoader, String className) { try { Class protoClass = contextClassLoader.loadClass(className); //?classProtocolBuffer?? if (ProtocolBuffer.class.isAssignableFrom(protoClass)) { final ValueEncoderFactory factory = new ValueEncoderFactory() { /** * @see org.apache.tapestry5.services.ValueEncoderFactory#create(java.lang.Class) */ @Override @SuppressWarnings("unchecked") public ValueEncoder create(Class type) { return new ProtoValueEncoder(type); } }; configuration.add(protoClass, factory); } } catch (ClassNotFoundException ex) { throw new RuntimeException(ex); } } /** * ProtobufEncoder * @author dong * @author <a href="jun.tsai@ganshane.net">Jun Tsai</a> * @version $Revision$ * @since 0.0.1 */ public static class ProtoValueEncoder<T extends ProtocolBuffer> implements ValueEncoder<T> { final Coercion<T, String> proto2string = new Object2ProtoStringCoercion<T>(); final Coercion<String, T> string2proto; public ProtoValueEncoder(Class<T> type) { string2proto = new ProtoString2ObjectCoercion<T>(type); } /** * @see org.apache.tapestry5.ValueEncoder#toClient(java.lang.Object) */ @Override public String toClient(T value) { return proto2string.coerce(value); } /** * @see org.apache.tapestry5.ValueEncoder#toValue(java.lang.String) */ @Override public T toValue(String clientValue) { return this.string2proto.coerce(clientValue); } } /** * String Protobuffer * * @author dong * @author <a href="jun.tsai@ganshane.net">Jun Tsai</a> * @version $Revision$ * @since 0.0.1 */ static class ProtoString2ObjectCoercion<T extends ProtocolBuffer> implements Coercion<String, T> { private final Class<T> type; public ProtoString2ObjectCoercion(Class<T> type) { this.type = type; } /** * @see org.apache.tapestry5.ioc.services.Coercion#coerce(java.lang.Object) */ @Override public T coerce(String input) { if (input == null) { return null; } T obj = null; try { obj = this.type.newInstance(); if ("X".equals(input)) { return obj; } //base64? byte[] _b64 = Base64.decodeBase64(input.getBytes()); //?????? obj.mergeData(_b64); return obj; } catch (Throwable te) { throw new RuntimeException(te); } } } /** * Protobufstring? * @author dong * @author <a href="jun.tsai@ganshane.net">Jun Tsai</a> * @version $Revision$ * @since 0.0.1 */ static class Object2ProtoStringCoercion<T extends ProtocolBuffer> implements Coercion<T, String> { /** * @see org.apache.tapestry5.ioc.services.Coercion#coerce(java.lang.Object) */ @Override public String coerce(T input) { if (input == null) { return null; } String str = new String(Base64.encodeBase64(input.getData())); if (InternalUtils.isBlank(str)) { return "X"; } return str; } } }