2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #pragma warning ( disable: 4231 4251 4275 4786 )
21 #include <log4cxx/logstring.h>
22 #include <log4cxx/helpers/objectoutputstream.h>
23 #include <log4cxx/helpers/bytebuffer.h>
24 #include <log4cxx/helpers/outputstream.h>
25 #include <log4cxx/helpers/charsetencoder.h>
26 #include "apr_pools.h"
28 using namespace log4cxx;
29 using namespace log4cxx::helpers;
31 IMPLEMENT_LOG4CXX_OBJECT(ObjectOutputStream)
33 ObjectOutputStream::ObjectOutputStream(OutputStreamPtr outputStream, Pool& p)
35 utf8Encoder(CharsetEncoder::getUTF8Encoder()),
36 objectHandle(0x7E0000),
37 classDescriptions(new ClassDescriptionMap())
39 unsigned char start[] = { 0xAC, 0xED, 0x00, 0x05 };
40 ByteBuffer buf((char*)start, sizeof(start));
44 ObjectOutputStream::~ObjectOutputStream() {
45 delete classDescriptions;
48 void ObjectOutputStream::close(Pool& p) {
52 void ObjectOutputStream::flush(Pool& p) {
56 void ObjectOutputStream::writeObject(const LogString& val, Pool& p) {
58 writeByte(TC_STRING, p);
60 #if LOG4CXX_LOGCHAR_IS_UTF8
61 size_t len = val.size();
62 ByteBuffer dataBuf(const_cast<char*>(val.data()), val.size());
64 size_t maxSize = 6 * val.size();
65 char* data = p.pstralloc(maxSize);
66 ByteBuffer dataBuf(data, maxSize);
67 LogString::const_iterator iter(val.begin());
68 utf8Encoder->encode(val, iter, dataBuf);
70 size_t len = dataBuf.limit();
72 bytes[1] = (char) (len & 0xFF);
73 bytes[0] = (char) ((len >> 8) & 0xFF);
74 ByteBuffer lenBuf(bytes, sizeof(bytes));
76 os->write(dataBuf, p);
80 void ObjectOutputStream::writeObject(const MDC::Map& val, Pool& p) {
82 // TC_OBJECT and the classDesc for java.util.Hashtable
84 unsigned char prolog[] = {
85 0x72, 0x00, 0x13, 0x6A, 0x61, 0x76, 0x61,
86 0x2E, 0x75, 0x74, 0x69, 0x6C, 0x2E, 0x48, 0x61,
87 0x73, 0x68, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x13,
88 0xBB, 0x0F, 0x25, 0x21, 0x4A, 0xE4, 0xB8, 0x03,
89 0x00, 0x02, 0x46, 0x00, 0x0A, 0x6C, 0x6F, 0x61,
90 0x64, 0x46, 0x61, 0x63, 0x74, 0x6F, 0x72, 0x49,
91 0x00, 0x09, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68,
92 0x6F, 0x6C, 0x64, 0x78, 0x70 };
93 writeProlog("java.util.Hashtable", 1, (char *) prolog, sizeof(prolog), p);
95 // loadFactor = 0.75, threshold = 5, blockdata start, buckets.size = 7
96 char data[] = { 0x3F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
97 TC_BLOCKDATA, 0x08, 0x00, 0x00, 0x00, 0x07 };
98 ByteBuffer dataBuf(data, sizeof(data));
99 os->write(dataBuf, p);
101 size_t sz = val.size();
102 size[3] = (char) (sz & 0xFF);
103 size[2] = (char) ((sz >> 8) & 0xFF);
104 size[1] = (char) ((sz >> 16) & 0xFF);
105 size[0] = (char) ((sz >> 24) & 0xFF);
106 ByteBuffer sizeBuf(size, sizeof(size));
107 os->write(sizeBuf, p);
108 for(MDC::Map::const_iterator iter = val.begin();
111 writeObject(iter->first, p);
112 writeObject(iter->second, p);
114 writeByte(TC_ENDBLOCKDATA, p);
117 void ObjectOutputStream::writeUTFString(const std::string& val, Pool& p) {
119 size_t len = val.size();
120 ByteBuffer dataBuf(const_cast<char*>(val.data()), val.size());
123 bytes[1] = (char) ((len >> 8) & 0xFF);
124 bytes[2] = (char) (len & 0xFF);
125 ByteBuffer lenBuf(bytes, sizeof(bytes));
126 os->write(lenBuf, p);
127 os->write(dataBuf, p);
132 void ObjectOutputStream::writeByte(char val, Pool& p) {
133 ByteBuffer buf(&val, 1);
137 void ObjectOutputStream::writeInt(int val, Pool& p) {
139 bytes[3] = (char) (val & 0xFF);
140 bytes[2] = (char) ((val >> 8) & 0xFF);
141 bytes[1] = (char) ((val >> 16) & 0xFF);
142 bytes[0] = (char) ((val >> 24) & 0xFF);
143 ByteBuffer buf(bytes, sizeof(bytes));
147 void ObjectOutputStream::writeLong(log4cxx_time_t val, Pool& p) {
149 bytes[7] = (char) (val & 0xFF);
150 bytes[6] = (char) ((val >> 8) & 0xFF);
151 bytes[5] = (char) ((val >> 16) & 0xFF);
152 bytes[4] = (char) ((val >> 24) & 0xFF);
153 bytes[3] = (char) ((val >> 32) & 0xFF);
154 bytes[2] = (char) ((val >> 40) & 0xFF);
155 bytes[1] = (char) ((val >> 48) & 0xFF);
156 bytes[0] = (char) ((val >> 56) & 0xFF);
157 ByteBuffer buf(bytes, sizeof(bytes));
161 void ObjectOutputStream::writeBytes(const char* bytes, size_t len, Pool& p) {
162 ByteBuffer buf(const_cast<char*>(bytes), len);
166 void ObjectOutputStream::writeNull(Pool& p) {
167 writeByte(TC_NULL, p);
170 void ObjectOutputStream::writeProlog(const char* className,
171 int classDescIncrement,
175 ClassDescriptionMap::const_iterator match = classDescriptions->find(className);
176 if (match != classDescriptions->end()) {
178 bytes[0] = TC_OBJECT;
179 bytes[1] = TC_REFERENCE;
180 bytes[2] = (char) ((match->second >> 24) & 0xFF);
181 bytes[3] = (char) ((match->second >> 16) & 0xFF);
182 bytes[4] = (char) ((match->second >> 8) & 0xFF);
183 bytes[5] = (char) (match->second & 0xFF);
184 ByteBuffer buf(bytes, sizeof(bytes));
188 classDescriptions->insert(ClassDescriptionMap::value_type(className, objectHandle));
189 writeByte(TC_OBJECT, p);
190 ByteBuffer buf(classDesc, len);
192 objectHandle += (classDescIncrement + 1);