View Javadoc
1   /*
2    * Oceanus: Java Utilities
3    * Copyright 2012-2026. Tony Washer
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6    * use this file except in compliance with the License.  You may obtain a copy
7    * of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
14   * License for the specific language governing permissions and limitations under
15   * the License.
16   */
17  package io.github.tonywasher.joceanus.oceanus.logger;
18  
19  import io.github.tonywasher.joceanus.oceanus.convert.OceanusDataConverter;
20  
21  import java.io.ByteArrayOutputStream;
22  import java.io.PrintStream;
23  
24  /**
25   * Log Manager.
26   */
27  public final class OceanusLogManager {
28      /**
29       * The data section length.
30       */
31      private static final int DATA_SECTION = 32;
32  
33      /**
34       * The data advance.
35       */
36      private static final int DATA_ADVANCE = 3;
37  
38      /**
39       * The output stream.
40       */
41      private static OceanusLogSink theSink = new OceanusLogStdOut();
42  
43      /**
44       * The initial time.
45       */
46      private final long theTimeZero;
47  
48      /**
49       * The constructor.
50       */
51      private OceanusLogManager() {
52          theTimeZero = System.nanoTime();
53      }
54  
55      /**
56       * Obtain the singleton instance.
57       *
58       * @return the instance.
59       */
60      private static OceanusLogManager getInstance() {
61          return OceanusLogManagerHelper.INSTANCE;
62      }
63  
64      /**
65       * Obtain a logger.
66       *
67       * @param pOwner the owning class
68       * @return the logger
69       */
70      public static OceanusLogger getLogger(final Class<?> pOwner) {
71          return new OceanusLogger(getInstance(), pOwner);
72      }
73  
74      /**
75       * Set Sink.
76       *
77       * @param pSink the sink
78       */
79      public static void setSink(final OceanusLogSink pSink) {
80          theSink = pSink;
81      }
82  
83      /**
84       * Format message.
85       *
86       * @param pOwner   the owner
87       * @param pLevel   the log level
88       * @param pMessage the message to format
89       * @return the formatted string
90       */
91      String formatMessage(final Class<?> pOwner,
92                           final OceanusLogLevel pLevel,
93                           final String pMessage) {
94          return (System.nanoTime() - theTimeZero)
95                  + " "
96                  + pLevel.name()
97                  + ": "
98                  + pOwner.getSimpleName()
99                  + "- "
100                 + pMessage;
101     }
102 
103     /**
104      * Format data.
105      *
106      * @param pData the data to format
107      * @return the formatted data
108      */
109     public static String formatData(final byte[] pData) {
110         return pData == null
111                 ? "\nnull"
112                 : formatData(pData, 0, pData.length);
113     }
114 
115     /**
116      * Format data.
117      *
118      * @param pData   the data to format
119      * @param pOffset the offset
120      * @param pLength the length of data
121      * @return the formatted data
122      */
123     public static String formatData(final byte[] pData,
124                                     final int pOffset,
125                                     final int pLength) {
126         /* Handle null data */
127         if (pData == null) {
128             return "\nnull";
129         }
130 
131         /* Handle partial buffer */
132         byte[] myData = pData;
133         if (pOffset != 0 || pLength != pData.length) {
134             myData = new byte[pLength];
135             System.arraycopy(pData, pOffset, myData, 0, pLength);
136         }
137 
138         /* Format the data */
139         final String myFormatted = OceanusDataConverter.bytesToHexString(myData);
140 
141         /* Place it into StringBuilder buffer */
142         final StringBuilder myBuilder = new StringBuilder();
143         myBuilder.append(myFormatted);
144 
145         /* Loop through the data */
146         int myOffSet = 0;
147         for (int i = 0; i < pLength; i++) {
148             /* Insert blank/newLine between each HexPair */
149             final char myChar = (i % DATA_SECTION) == 0 ? '\n' : ' ';
150             myBuilder.insert(myOffSet, myChar);
151             myOffSet += DATA_ADVANCE;
152         }
153 
154         /* Return the data */
155         return myBuilder.toString();
156     }
157 
158     /**
159      * Write log message.
160      *
161      * @param pMessage the message to format
162      */
163     void writeLogMessage(final String pMessage) {
164         synchronized (this) {
165             theSink.writeLogMessage(pMessage);
166         }
167     }
168 
169     /**
170      * Write log message and exception.
171      *
172      * @param pMessage   the message to format
173      * @param pException the exception
174      */
175     void writeLogMessage(final String pMessage,
176                          final Throwable pException) {
177         synchronized (this) {
178             theSink.writeLogMessage(pMessage);
179             final ByteArrayOutputStream myBaos = new ByteArrayOutputStream();
180             try (PrintStream myPs = new PrintStream(myBaos)) {
181                 if (pException != null) {
182                     pException.printStackTrace(myPs);
183                 } else {
184                     myPs.println("Null Exception");
185                 }
186                 theSink.writeLogMessage(myBaos.toString());
187             }
188         }
189     }
190 
191     /**
192      * Log Manager Helper.
193      */
194     private static final class OceanusLogManagerHelper {
195         /**
196          * The Log Manager instance.
197          */
198         private static final OceanusLogManager INSTANCE = new OceanusLogManager();
199     }
200 
201     /**
202      * Default Log Sink.
203      */
204     static final class OceanusLogStdOut
205             implements OceanusLogSink {
206         /**
207          * The output stream.
208          */
209         private final PrintStream theOutput = System.out;
210 
211         /**
212          * Constructor.
213          */
214         private OceanusLogStdOut() {
215         }
216 
217         @Override
218         public void writeLogMessage(final String pMessage) {
219             theOutput.println(pMessage);
220         }
221     }
222 }