    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements. See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache license, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License. You may obtain a copy of the License at
    008     *
    009     *      http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the license for the specific language governing permissions and
    015     * limitations under the license.
    016     */
    017    package org.apache.logging.log4j.core.layout;
    018
    019    import java.io.ByteArrayOutputStream;
    020    import java.io.IOException;
    021    import java.io.ObjectOutputStream;
    022    import java.io.OutputStream;
    023
    024    import org.apache.logging.log4j.core.Layout;
    025    import org.apache.logging.log4j.core.LogEvent;
    026    import org.apache.logging.log4j.core.config.Node;
    027    import org.apache.logging.log4j.core.config.plugins.Plugin;
    028    import org.apache.logging.log4j.core.config.plugins.PluginFactory;
    029
    030    /**
    031     * Formats a {@link LogEvent} in its Java serialized form.
    032     */
    033    @Plugin(name = "SerializedLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
    034    public final class SerializedLayout extends AbstractLayout<LogEvent> {
    035
    036        private static final long serialVersionUID = 1L;
    037
    038        private static byte[] serializedHeader;
    039
    040        static {
    041            final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    042            try {
    043                final ObjectOutputStream oos = new ObjectOutputStream(baos);
    044                oos.close();
    045                serializedHeader = baos.toByteArray();
    046            } catch (final Exception ex) {
    047                LOGGER.error("Unable to generate Object stream header", ex);
    048            }
    049        }
    050
    051        private SerializedLayout() {
    052            super(null, null);
    053        }
    054
    055        /**
    056         * Formats a {@link org.apache.logging.log4j.core.LogEvent} as a serialized byte array of the LogEvent object.
    057         *
    058         * @param event The LogEvent.
    059         * @return the formatted LogEvent.
    060         */
    061        @Override
    062        public byte[] toByteArray(final LogEvent event) {
    063            final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    064            try {
    065                final ObjectOutputStream oos = new PrivateObjectOutputStream(baos);
    066                try {
    067                    oos.writeObject(event);
    068                    oos.reset();
    069                } finally {
    070                    oos.close();
    071                }
    072            } catch (final IOException ioe) {
    073                LOGGER.error("Serialization of LogEvent failed.", ioe);
    074            }
    075            return baos.toByteArray();
    076        }
    077
    078        /**
    079         * Returns the LogEvent.
    080         *
    081         * @param event The Logging Event.
    082         * @return The LogEvent.
    083         */
    084        @Override
    085        public LogEvent toSerializable(final LogEvent event) {
    086            return event;
    087        }
    088
    089        /**
    090         * Creates a SerializedLayout.
    091         * @return A SerializedLayout.
    092         */
    093        @PluginFactory
    094        public static SerializedLayout createLayout() {
    095            return new SerializedLayout();
    096        }
    097
    098        @Override
    099        public byte[] getHeader() {
    100            return serializedHeader;
    101        }
    102
    103        /**
    104         * SerializedLayout returns a binary stream.
    105         * @return The content type.
    106         */
    107        @Override
    108        public String getContentType() {
    109            return "application/octet-stream";
    110        }
    111
    112        /**
    113         * The stream header will be written in the Manager so skip it here.
    114         */
    115        private class PrivateObjectOutputStream extends ObjectOutputStream {
    116
    117            public PrivateObjectOutputStream(final OutputStream os) throws IOException {
    118                super(os);
    119            }
    120
    121            @Override
    122            protected void writeStreamHeader() {
    123            }
    124        }
    125    }