Return-Path: Delivered-To: apmail-geronimo-scm-archive@www.apache.org Received: (qmail 48936 invoked from network); 19 Sep 2007 03:21:44 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 19 Sep 2007 03:21:44 -0000 Received: (qmail 20107 invoked by uid 500); 19 Sep 2007 03:21:36 -0000 Delivered-To: apmail-geronimo-scm-archive@geronimo.apache.org Received: (qmail 20071 invoked by uid 500); 19 Sep 2007 03:21:36 -0000 Mailing-List: contact scm-help@geronimo.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: dev@geronimo.apache.org List-Id: Delivered-To: mailing list scm@geronimo.apache.org Received: (qmail 20060 invoked by uid 99); 19 Sep 2007 03:21:36 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 18 Sep 2007 20:21:36 -0700 X-ASF-Spam-Status: No, hits=-100.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 19 Sep 2007 03:21:43 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 753971A9832; Tue, 18 Sep 2007 20:21:22 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r577140 - in /geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote: codec/ message/ transport/ Date: Wed, 19 Sep 2007 03:21:14 -0000 To: scm@geronimo.apache.org From: jdillon@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20070919032122.753971A9832@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: jdillon Date: Tue Sep 18 20:21:12 2007 New Revision: 577140 URL: http://svn.apache.org/viewvc?rev=577140&view=rev Log: Learned some more from gcache (yay), updating the marshalling bits to hopefully work better and not keep freaking out now weird shiz Added: geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/ geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/Externalizable.java (with props) geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/MarshallingUtil.java (with props) geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/MessageCodecFactory.java (with props) Removed: geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/message/MagicNumber.java geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/message/MessageCodecFactory.java Modified: geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/message/MessageType.java geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/transport/TransportSupport.java Added: geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/Externalizable.java URL: http://svn.apache.org/viewvc/geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/Externalizable.java?rev=577140&view=auto ============================================================================== --- geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/Externalizable.java (added) +++ geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/Externalizable.java Tue Sep 18 20:21:12 2007 @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.geronimo.gshell.remote.codec; + +import org.apache.mina.common.ByteBuffer; + +/** + * ??? + * + * @version $Rev$ $Date$ + */ +public interface Externalizable +{ + void writeExternal(final ByteBuffer out) throws Exception; + + void readExternal(final ByteBuffer in) throws Exception; +} \ No newline at end of file Propchange: geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/Externalizable.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/Externalizable.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Propchange: geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/Externalizable.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/MarshallingUtil.java URL: http://svn.apache.org/viewvc/geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/MarshallingUtil.java?rev=577140&view=auto ============================================================================== --- geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/MarshallingUtil.java (added) +++ geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/MarshallingUtil.java Tue Sep 18 20:21:12 2007 @@ -0,0 +1,246 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.geronimo.gshell.remote.codec; + +import java.io.IOException; +import java.io.ByteArrayInputStream; +import java.io.ObjectInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectOutputStream; +import java.nio.charset.Charset; +import java.nio.charset.CharacterCodingException; +import java.util.UUID; + +import org.apache.mina.common.ByteBuffer; + +/** + * ??? + * + * @version $Rev$ $Date$ + */ +public class MarshallingUtil +{ + // + // Boolean Serialization + // + + private static final byte TRUE = 1; + + private static final byte FALSE = 0; + + public static boolean readBoolean(final ByteBuffer in) { + assert in != null; + + byte b = in.get(); + + if (b == TRUE) { + return true; + } + else if (b == FALSE) { + return false; + } + else { + throw new Error(); + } + } + + public static void writeBoolean(final ByteBuffer out, final boolean bool) { + assert out != null; + + if (bool) { + out.put(TRUE); + } + else { + out.put(FALSE); + } + } + + // + // Byte[] Serialization + // + + public static byte[] readBytes(final ByteBuffer in) { + assert in != null; + + boolean isNull = readBoolean(in); + + if (isNull) { + return null; + } + + int len = in.getInt(); + + byte[] bytes = new byte[len]; + + in.get(bytes); + + return bytes; + } + + public static void writeBytes(final ByteBuffer out, final byte[] bytes) { + assert out != null; + + if (bytes == null) { + writeBoolean(out, true); + } + else { + writeBoolean(out, false); + + out.putInt(bytes.length); + + out.put(bytes); + } + } + + // + // ByteBuffer Serialization + // + + public static ByteBuffer readBuffer(final ByteBuffer in) { + assert in != null; + + byte[] bytes = readBytes(in); + + if (bytes == null) { + return null; + } + + return ByteBuffer.wrap(bytes); + } + + public static void writeBuffer(final ByteBuffer out, final ByteBuffer buffer) { + assert out != null; + + if (buffer == null) { + writeBytes(out, null); + } + else { + writeBoolean(out, false); + + out.putInt(buffer.remaining()); + + out.put(buffer); + } + } + + // + // Object Serialization + // + + public static Object readObject(final ByteBuffer in) throws IOException, ClassNotFoundException { + assert in != null; + + byte[] bytes = readBytes(in); + + if (bytes == null) { + return null; + } + + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais); + + return ois.readObject(); + } + + public static void writeObject(final ByteBuffer out, final Object obj) throws IOException { + assert out != null; + + byte[] bytes = null; + + if (obj != null) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + + oos.writeObject(obj); + oos.flush(); + + bytes = baos.toByteArray(); + } + + writeBytes(out, bytes); + } + + // + // String Serialization + // + + private static final Charset UTF_8_CHARSET = Charset.forName("UTF-8"); + + public static String readString(final ByteBuffer in) throws CharacterCodingException { + assert in != null; + + int len = in.getInt(); + + if (len == -1) { + return null; + } + + return in.getString(len, UTF_8_CHARSET.newDecoder()); + } + + public static void writeString(final ByteBuffer out, final String str) throws CharacterCodingException { + assert out != null; + + if (str == null) { + out.putInt(-1); + } + else { + int len = str.length(); + out.putInt(len); + + out.putString(str, len, UTF_8_CHARSET.newEncoder()); + } + } + + // + // UUID Serialization + // + + public static UUID readUuid(final ByteBuffer in) throws Exception { + assert in != null; + + boolean isNull = readBoolean(in); + + if (isNull) { + return null; + } + + long msb = in.getLong(); + + long lsb = in.getLong(); + + return new UUID(msb, lsb); + } + + public static void writeUuid(final ByteBuffer out, final UUID uuid) throws Exception { + assert out != null; + + if (uuid == null) { + writeBoolean(out, true); + } + else { + writeBoolean(out, false); + + out.putLong(uuid.getMostSignificantBits()); + + out.putLong(uuid.getLeastSignificantBits()); + } + } +} \ No newline at end of file Propchange: geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/MarshallingUtil.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/MarshallingUtil.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Propchange: geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/MarshallingUtil.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/MessageCodecFactory.java URL: http://svn.apache.org/viewvc/geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/MessageCodecFactory.java?rev=577140&view=auto ============================================================================== --- geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/MessageCodecFactory.java (added) +++ geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/MessageCodecFactory.java Tue Sep 18 20:21:12 2007 @@ -0,0 +1,266 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.geronimo.gshell.remote.codec; + +import java.io.ByteArrayOutputStream; +import java.nio.channels.Channels; +import java.nio.channels.WritableByteChannel; +import java.util.Set; +import java.util.Arrays; + +import org.apache.geronimo.gshell.remote.message.Message; +import org.apache.geronimo.gshell.remote.message.MessageType; +import org.apache.geronimo.gshell.remote.crypto.CryptoContext; +import org.apache.geronimo.gshell.remote.crypto.CryptoContextAware; +import org.apache.mina.common.ByteBuffer; +import org.apache.mina.common.IoSession; +import org.apache.mina.filter.codec.ProtocolDecoderOutput; +import org.apache.mina.filter.codec.ProtocolEncoderOutput; +import org.apache.mina.filter.codec.ProtocolCodecException; +import org.apache.mina.filter.codec.demux.DemuxingProtocolCodecFactory; +import org.apache.mina.filter.codec.demux.MessageDecoderAdapter; +import org.apache.mina.filter.codec.demux.MessageDecoderResult; +import org.apache.mina.filter.codec.demux.MessageEncoder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.codehaus.plexus.component.annotations.Requirement; +import org.codehaus.plexus.component.annotations.Component; + +/** + * Provides encoding and decoding support for {@link Message} instances. + * + * @version $Rev$ $Date$ + */ +@Component(role=MessageCodecFactory.class) +public class MessageCodecFactory + extends DemuxingProtocolCodecFactory +{ + private static final byte[] MAGIC = { 'g', 's', 'h', 0 }; + + private static final byte VERSION = 1; + + private static final int HEADER_SIZE = + MAGIC.length + + 1 + // version (byte) + 1 + // message type (enum byte) + 4; // body length (int) + + private final Logger log = LoggerFactory.getLogger(getClass()); + + @Requirement + private CryptoContext crypto; + + public MessageCodecFactory() { + register(new Decoder()); + + //noinspection unchecked + register(new Encoder()); + } + + private void attachCryptoContext(final Message msg) { + // We need to do a little bit of extra fluff to hook up support for encrypted messages + if (msg instanceof CryptoContextAware) { + log.debug("Attaching crypto context to: {}", msg); + + ((CryptoContextAware)msg).setCryptoContext(crypto); + } + } + + private void writeMagic(final ByteBuffer out) throws Exception { + assert out != null; + + out.put(MAGIC); + } + + private byte[] readMagic(final ByteBuffer in) throws Exception { + assert in != null; + + byte[] bytes = new byte[MAGIC.length]; + + in.get(bytes); + + if (!Arrays.equals(MAGIC, bytes)) { + throw new ProtocolCodecException("Invalid MAGIC"); + } + + return bytes; + } + + private void writeVersion(final ByteBuffer out) throws Exception { + assert out != null; + + out.put(VERSION); + } + + private byte readVersion(final ByteBuffer in) throws Exception { + assert in != null; + + byte version = in.get(); + + if (VERSION != version) { + throw new ProtocolCodecException("Invalid version"); + } + + return version; + } + + private byte[] marshal(final Message msg) throws Exception { + assert msg != null; + + log.debug("Marshalling: {}", msg); + + ByteBuffer out = ByteBuffer.allocate(256, false); + out.setAutoExpand(true); + + writeMagic(out); + + writeVersion(out); + + out.putEnum(msg.getType()); + + // Determine the length of the message body + out.mark(); + out.putInt(0); + msg.writeExternal(out); + + int bodyStart = HEADER_SIZE; + int pos = out.position(); + int len = pos - bodyStart; + + out.reset(); + + // Write the length of the body + out.putInt(len); + out.position(pos); + out.limit(pos); + out.flip(); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + WritableByteChannel channel = Channels.newChannel(baos); + channel.write(out.buf()); + channel.close(); + + byte[] bytes = baos.toByteArray(); + + log.debug("Marshalled size: {} bytes", bytes.length); + + return bytes; + } + + // + // Encoder + // + + public class Encoder + implements MessageEncoder + { + public Set getMessageTypes() { + return MessageType.types(); + } + + public void encode(final IoSession session, final Object message, final ProtocolEncoderOutput out) throws Exception { + assert session != null; + assert message != null; + assert out != null; + + Message msg = (Message)message; + + log.debug("Encoding: {}", msg); + + attachCryptoContext(msg); + + byte[] bytes = marshal(msg); + + log.debug("Encoded {} bytes", bytes.length); + + out.write(ByteBuffer.wrap(bytes)); + } + } + + // + // Decoder + // + + public class Decoder + extends MessageDecoderAdapter + { + public MessageDecoderResult decodable(final IoSession session, final ByteBuffer in) { + assert session != null; + assert in != null; + + if (in.remaining() < HEADER_SIZE) { + return MessageDecoderResult.NEED_DATA; + } + + try { + readMagic(in); + + readVersion(in); + + MessageType type = in.getEnum(MessageType.class); + + if (type == null) { + return MessageDecoderResult.NOT_OK; + } + } + catch (Exception e) { + return MessageDecoderResult.NOT_OK; + } + + // Make sure we have all of the data we need + int len = in.getInt(); + + if (in.remaining() != len) { + return MessageDecoderResult.NEED_DATA; + } + + return MessageDecoderResult.OK; + } + + public MessageDecoderResult decode(final IoSession session, final ByteBuffer in, final ProtocolDecoderOutput out) throws Exception { + assert session != null; + assert in != null; + assert out != null; + + readMagic(in); + + readVersion(in); + + MessageType type = in.getEnum(MessageType.class); + + Message msg = MessageType.create(type); + + attachCryptoContext(msg); + + int len = in.getInt(); + + log.debug("Decoding {} bytes", len); + + msg.readExternal(in); + + log.debug("Decoded: {}", msg); + + out.write(msg); + + return MessageDecoderResult.OK; + } + } +} \ No newline at end of file Propchange: geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/MessageCodecFactory.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/MessageCodecFactory.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Propchange: geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/codec/MessageCodecFactory.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/message/MessageType.java URL: http://svn.apache.org/viewvc/geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/message/MessageType.java?rev=577140&r1=577139&r2=577140&view=diff ============================================================================== --- geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/message/MessageType.java (original) +++ geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/message/MessageType.java Tue Sep 18 20:21:12 2007 @@ -19,6 +19,10 @@ package org.apache.geronimo.gshell.remote.message; +import java.util.HashSet; +import java.util.Set; +import java.util.Collections; + /** * Enumeration of supported message types and factory for message instances. * @@ -66,5 +70,15 @@ catch (IllegalAccessException e) { throw new Error(e); } + } + + public static Set types() { + Set set = new HashSet(); + + for (MessageType type : values()) { + set.add(type.type); + } + + return Collections.unmodifiableSet(set); } } Modified: geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/transport/TransportSupport.java URL: http://svn.apache.org/viewvc/geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/transport/TransportSupport.java?rev=577140&r1=577139&r2=577140&view=diff ============================================================================== --- geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/transport/TransportSupport.java (original) +++ geronimo/sandbox/gshell/trunk/gshell-remote/gshell-remote-common/src/main/java/org/apache/geronimo/gshell/remote/transport/TransportSupport.java Tue Sep 18 20:21:12 2007 @@ -23,7 +23,7 @@ import org.apache.geronimo.gshell.common.tostring.ReflectionToStringBuilder; import org.apache.geronimo.gshell.remote.logging.LoggingFilter; -import org.apache.geronimo.gshell.remote.message.MessageCodecFactory; +import org.apache.geronimo.gshell.remote.codec.MessageCodecFactory; import org.apache.geronimo.gshell.remote.message.MessageVisitor; import org.apache.mina.common.DefaultIoFilterChainBuilder; import org.apache.mina.common.IoService;