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 */
017package org.apache.logging.log4j.core.layout;
018
019import java.io.ByteArrayOutputStream;
020import java.io.IOException;
021import java.io.ObjectOutputStream;
022import java.io.OutputStream;
023
024import org.apache.logging.log4j.core.Layout;
025import org.apache.logging.log4j.core.LogEvent;
026import org.apache.logging.log4j.core.config.Node;
027import org.apache.logging.log4j.core.config.plugins.Plugin;
028import 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)
034public 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}