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 org.apache.logging.log4j.core.LogEvent;
020    import org.apache.logging.log4j.core.config.plugins.Plugin;
021    import org.apache.logging.log4j.core.config.plugins.PluginFactory;
022    
023    import java.io.ByteArrayOutputStream;
024    import java.io.IOException;
025    import java.io.ObjectOutputStream;
026    import java.io.OutputStream;
027    
028    /**
029     * Format a LogEvent in its serialized form.
030     */
031    @Plugin(name = "SerializedLayout", type = "Core", elementType = "layout", printObject = true)
032    public final class SerializedLayout extends AbstractLayout<LogEvent> {
033    
034        private static byte[] header;
035    
036        static {
037            final ByteArrayOutputStream baos = new ByteArrayOutputStream();
038            try {
039                final ObjectOutputStream oos = new ObjectOutputStream(baos);
040                oos.close();
041                header = baos.toByteArray();
042            } catch (final Exception ex) {
043                LOGGER.error("Unable to generate Object stream header", ex);
044            }
045        }
046    
047        private SerializedLayout() {
048        }
049    
050        /**
051         * Formats a {@link org.apache.logging.log4j.core.LogEvent} in conformance with the log4j.dtd.
052         *
053         * @param event The LogEvent.
054         * @return the formatted LogEvent.
055         */
056        public byte[] toByteArray(final LogEvent event) {
057            final ByteArrayOutputStream baos = new ByteArrayOutputStream();
058            try {
059                final ObjectOutputStream oos = new PrivateObjectOutputStream(baos);
060                try {
061                    oos.writeObject(event);
062                    oos.reset();
063                } finally {
064                    oos.close();
065                }
066            } catch (final IOException ioe) {
067                LOGGER.error("Serialization of LogEvent failed.", ioe);
068            }
069            return baos.toByteArray();
070        }
071    
072        /**
073         * Returns the LogEvent.
074         *
075         * @param event The Logging Event.
076         * @return The LogEvent.
077         */
078        public LogEvent toSerializable(final LogEvent event) {
079            return event;
080        }
081    
082        /**
083         * Create a SerializedLayout.
084         * @return A SerializedLayout.
085         */
086        @PluginFactory
087        public static SerializedLayout createLayout() {
088    
089            return new SerializedLayout();
090        }
091    
092        @Override
093        public byte[] getHeader() {
094            return header;
095        }
096    
097        /**
098         * SerializedLayout returns a binary stream.
099         * @return The content type.
100         */
101        public String getContentType() {
102            return "application/octet-stream";
103        }
104    
105        /**
106         * The stream header will be written in the Manager so skip it here.
107         */
108        private class PrivateObjectOutputStream extends ObjectOutputStream {
109    
110            public PrivateObjectOutputStream(final OutputStream os) throws IOException {
111                super(os);
112            }
113    
114            @Override
115            protected void writeStreamHeader() {
116            }
117        }
118    }